Configuring Sessions

Creating a session

session = composio.sessions.create(user_id="user_123")

By default, a session has access to every toolkit in the Composio catalog. Your agent can discover and use any of them through COMPOSIO_SEARCH_TOOLS. Use the options below to restrict or customize what's available.

You can also attach local custom tools and custom toolkits that run in-process alongside Composio tools. See Custom tools and toolkits.

API key permissions

If you use a scoped project API key, grant permissions for the session operations your application needs:

  • Session management controls creating, viewing, configuring, and deleting sessions. It does not grant tool execution access.
  • Session tool execution covers search, tool execution, proxy execution, and session-linked MCP access.

Enable both permissions if your application manages sessions and executes tools through them.

Using a saved Session config

A Session config is a saved, named access policy (sc_…) that you build in the Composio Dashboard under Sessions → Configs. Start a session from one instead of repeating toolkits, tools, and tags in your code:

const { items } = await composio.sessionConfigs.list({ search: "support" });

const session = await composio.sessions.create("user_123", {
  authConfigs: { github: "ac_123" },
  experimental: { sessionConfigId: items[0].id },
});

console.log(session.experimental.sourceSessionConfig); // { id: "sc_..." }

The backend resolves the config when it creates the session, so the session gets exactly the access the config grants. Later edits to the config in the Dashboard don't change sessions that already exist.

The top-level composio.sessionConfigs read methods are available in TypeScript. Applying a config and reading its source metadata use experimental. Reads require Session configs enabled for your project; otherwise they return 403. With a scoped project API key, they need the Session management read permission.

Finding a config

composio.sessionConfigs.list() returns summaries (id, name, archived, createdAt, updatedAt) and a nextCursor. It returns active configs unless you pass archived: true, which returns only archived ones. Pass search to match names and limit and cursor to page; the backend returns 20 per page by default and at most 100.

composio.sessionConfigs.get(id) adds the description and the stored policy under config:

const sessionConfig = await composio.sessionConfigs.get("sc_123");

console.log(sessionConfig.config);
// { toolkits: { enable: ["github"] }, tags: { disable: ["destructiveHint"] } }

A saved policy uses enable and disable, the same shape you send on create. session.config is the server's snapshot of a live session and names the same lists enabled and disabled.

What you can combine with a config

The config owns the session's toolkit, tool, and tag access. On create(), you can't pass sessionConfigId together with toolkits, tools, tags, experimental.customTools, or experimental.customToolkits. TypeScript reports the mix at compile time, and the SDK throws ValidationError before it sends a request. An empty list such as toolkits: [] counts as set.

Per-session settings stay yours: authConfigs, connectedAccounts, manageConnections, sandbox, multiAccount, preload, sessionPreset, mcp, and experimental.assistivePrompt.

SessionPreset.DIRECT_TOOLS defaults to preload: { tools: "all" } when you omit preload. With a saved config, the backend resolves its policy before validating that preload. The policy must select toolkits with enable, enable specific tools, or enable tags within a named toolkit's tool rule. An unrestricted policy, a denylist-only policy, or top-level tags alone returns 400. The resolved tool set must also contain at most 1,000 tools.

Live verification accepted DIRECT_TOOLS with a saved config that provided a positive toolkit/tool scope. The no-positive-scope case was not exercised in that run; its 400 behavior is enforced by the API's preload validation. The SDK passes these API errors through unchanged.

Applying a config to an existing session

Pass sessionConfigId in the experimental block of session.update() to replace the session's toolkit, tool, and tag access with the config's policy. Other settings are preserved.

const session = await composio.sessions.use("session_id");

await session.update({ experimental: { sessionConfigId: "sc_123" } });

The same rule applies here: sessionConfigId can't be combined with toolkits, tools, or tags, and null counts as set. A saved config and custom tools don't mix on update either: if the session was created with inline custom tools, the backend rejects a conflicting config with a 400.

A 409 while applying a config means the session or the config changed during the update. The SDK raises ComposioSessionConfigConflictError, and nothing was written: re-fetch the session with sessions.use() and retry.

Which config a session came from

session.experimental.sourceSessionConfig holds { id } of the last config applied to the session. The SDK sets it after create(), sessions.use(), and a successful update(). It stays set after later inline updates such as update({ toolkits: [...] }), and it's undefined when no config was applied. It reflects the last response this session object saw, so an update from another process leaves it stale until you call sessions.use() again.

When a config can't be used

The SDK never retries without the config or falls back to an unrestricted session. A missing, archived, or cross-project config fails with the backend's 404, and a project without Session configs fails with 403. A failed update() leaves the session object unchanged.

Reading and updating session configuration

In TypeScript, session.config exposes the configuration returned by the server. Call session.update() to change selected fields. It preserves omitted fields, updates session.config in place, and returns the updated configuration. See Updating a session for an example.

If you implement the TypeScript Session interface yourself, include the required config member. Sessions created by the SDK provide it automatically.

Enabling toolkits

To limit a session to specific toolkits, pass an array of toolkit slugs. The agent can only discover and use tools from these toolkits.

# Using array format
session = composio.sessions.create(
    user_id="user_123",
    toolkits=["github", "gmail", "slack"]
)

# Using object format with enable key
session = composio.sessions.create(
    user_id="user_123",
    toolkits={"enable": ["github", "gmail", "slack"]}
)

Disabling toolkits

To keep every toolkit discoverable except a few, use the disable syntax. This is useful when you want broad access but need to exclude specific toolkits.

session = composio.sessions.create(
    user_id="user_123",
    toolkits={"disable": ["exa", "firecrawl"]}
)

Denying every app toolkit

An explicit empty allowlist means no app toolkits at all. Omitting toolkits keeps the unrestricted default, and an empty disable list is also unrestricted. The three requests are different:

Toolkit configEffect
OmittedEvery toolkit in the catalog is available
{ enable: [] }No app toolkit is listed, searchable, executable, or served over MCP
{ disable: [] }Every toolkit in the catalog is available

Use an empty allowlist when a session should only run custom tools or session helpers. Meta tools such as COMPOSIO_SEARCH_TOOLS, connection management, and the sandbox keep their own enablement, so session.tools() can still return them.

session = composio.sessions.create(
    user_id="user_123",
    toolkits={"enable": []},
)

Requires @composio/core ≥ 0.19.1 (TypeScript) or composio ≥ 0.22.1 (Python) when you narrow an existing session with session.update(). Both SDKs send the empty allowlist as { enable: [] }; the backend previously read an empty allowlist as "allow every toolkit", which left the session unrestricted.

The session API rejects unknown root keys with a 400 before it creates anything. A typo such as a singular toolkit fails the request instead of silently creating an unrestricted session.

Direct tools preset

The direct tools preset preloads every tool allowed by session filters into the session's tool list and disables session meta tools by default. Use it for specialized agents with a narrow tool set that don't need dynamic tool discovery, in-chat auth, or workbench helpers.

This is not the default mode for broad agents. The default session behavior keeps meta tools available so the agent can search for relevant tools and avoid context bloat.

from composio import Composio, SESSION_PRESET_DIRECT_TOOLS
from composio_openai_agents import OpenAIAgentsProvider

composio = Composio(
    api_key="your_api_key",
    provider=OpenAIAgentsProvider(),
)

session = composio.sessions.create(
    user_id="user_123",
    toolkits=["gmail"],
    tools={
        "gmail": {
            "enable": [
                "GMAIL_FETCH_EMAILS",
                "GMAIL_CREATE_EMAIL_DRAFT",
            ],
        },
    },
    session_preset=SESSION_PRESET_DIRECT_TOOLS,
)

tools = session.tools()
print([tool.name for tool in tools])
# GMAIL_FETCH_EMAILS
# GMAIL_CREATE_EMAIL_DRAFT

Enable selected meta tools

With the direct tools preset, you can re-enable supported meta tool groups that your agent still needs. This session loads Gmail tools upfront while keeping connection management and workbench support available:

from composio import Composio, SESSION_PRESET_DIRECT_TOOLS
from composio_openai_agents import OpenAIAgentsProvider

composio = Composio(
    api_key="your_api_key",
    provider=OpenAIAgentsProvider(),
)

session = composio.sessions.create(
    user_id="user_123",
    toolkits=["gmail"],
    tools={
        "gmail": {
            "enable": [
                "GMAIL_FETCH_EMAILS",
                "GMAIL_CREATE_EMAIL_DRAFT",
            ],
        },
    },
    session_preset=SESSION_PRESET_DIRECT_TOOLS,
    manage_connections={
        "enable": True,
    },
    sandbox={
        "enable": True,
    },
)

tools = session.tools()
print([tool.name for tool in tools])
# GMAIL_FETCH_EMAILS
# GMAIL_CREATE_EMAIL_DRAFT
# COMPOSIO_MANAGE_CONNECTIONS
# COMPOSIO_REMOTE_WORKBENCH
# COMPOSIO_REMOTE_BASH_TOOL

Enabling or disabling specific tools

To control which individual tools are available within a toolkit, use the tools configuration. The key is the toolkit slug and the value specifies which tools to enable or disable.

To enable only specific tools, pass an enable list per toolkit:

session = composio.sessions.create(
    user_id="user_123",
    tools={
        # Only these Gmail tools will be available
        "gmail": {"enable": ["GMAIL_SEND_EMAIL", "GMAIL_FETCH_EMAILS"]},
        # Only issue-related GitHub tools
        "github": {"enable": ["GITHUB_CREATE_ISSUE", "GITHUB_GET_ISSUE"]}
    }
)

The shorthand array syntax is equivalent to enable:

session = composio.sessions.create(
    user_id="user_123",
    tools={
        "gmail": ["GMAIL_SEND_EMAIL", "GMAIL_FETCH_EMAILS"],
        "github": ["GITHUB_CREATE_ISSUE", "GITHUB_GET_ISSUE"]
    }
)

To keep every tool in a toolkit except a few, use disable:

session = composio.sessions.create(
    user_id="user_123",
    tools={
        # All Slack tools except delete
        "slack": {"disable": ["SLACK_DELETE_MESSAGE"]},
        # All GitHub tools except destructive ones
        "github": {"disable": ["GITHUB_DELETE_REPO", "GITHUB_DELETE_BRANCH"]}
    }
)

Filtering tools by tags

Tools carry behavior tags that you can filter on. Every tool carries at least one of these four:

TagDescription
readOnlyHintReads, searches, lists or computes. Changes nothing
createHintCreates a new resource, such as sending an email or opening an issue
updateHintModifies an existing resource in place
destructiveHintIrreversibly removes, cancels or revokes data. An irreversible update also carries updateHint

The MCP annotation tags idempotentHint and openWorldHint are also accepted, but only some tools set them, so use the four above for access control.

MCP-backed toolkits (managed ones such as granola_mcp and custom MCP toolkits) carry the same four tags. readOnlyHint comes from the server's annotations; every other tool is classified into createHint, updateHint or destructiveHint when the toolkit is synced. A toolkit not synced since classification was added may carry only the server's annotations, and an enable filter hides any tool without a matching tag.

Sessions read the latest published version of each tool. The v3 tools endpoints default to the pinned version 00000000_00, so pass version=latest (or use v3.1) to see the tags a session enforces.

To apply tag filters across all toolkits, pass tags at the session level:

# Only include tools that read or create; no updates or deletes
session = composio.sessions.create(
    user_id="user_123",
    tags=["readOnlyHint", "createHint"]
)

# Enable some tags, disable others
session = composio.sessions.create(
    user_id="user_123",
    tags={
        "enable": ["readOnlyHint"],
        "disable": ["destructiveHint"]
    }
)

To override the global tags for a specific toolkit, set tags inside that toolkit's tools config:

session = composio.sessions.create(
    user_id="user_123",
    # Global: only read-only tools
    tags=["readOnlyHint"],
    tools={
        # Override for GitHub: allow all tools except destructive
        "github": {"tags": {"disable": ["destructiveHint"]}},
        # Override for Gmail: only read-only tools (explicit)
        "gmail": {"tags": ["readOnlyHint"]}
    }
)

Preloading tools

Return a known set of tools directly from session.tools() and the session MCP tool list, without the agent searching for them first.

By default, sessions expose meta tools that let the agent discover app tools at runtime. Use preload.tools when you already know which tools the agent needs, so it can call them without going through search each time.

Keep the preloaded set small, generally fewer than 20 tools, to avoid context bloat.

Requires @composio/core ≥ 0.9.0 (TypeScript) or composio ≥ 0.13.0 (Python). Older SDKs do not support preload.tools, sessionPreset / session_preset, or custom-tool preload.

preload.tools is not supported when multiAccount.enable is true. See Managing multiple connected accounts.

from composio import Composio
from composio_openai_agents import OpenAIAgentsProvider

composio = Composio(
    api_key="your_api_key",
    provider=OpenAIAgentsProvider(),
)

session = composio.sessions.create(
    user_id="user_123",
    toolkits=["gmail"],
    preload={
        "tools": [
            "GMAIL_FETCH_EMAILS",
            "GMAIL_CREATE_EMAIL_DRAFT",
        ],
    },
)

tools = session.tools()
print([tool.name for tool in tools])
# GMAIL_FETCH_EMAILS
# GMAIL_CREATE_EMAIL_DRAFT
# COMPOSIO_SEARCH_TOOLS
# ... other default meta tools

For SDK custom tools, set preload: true on the custom tool or custom toolkit. See Preloading custom tools.

To preload every tool allowed by the session filters, use the preload.tools = "all" shortcut (preload={"tools": "all"} in Python, preload: { tools: "all" } in TypeScript). The all shorthand works for both Composio tools and SDK custom tools.

Custom auth configs

Use your own OAuth credentials instead of Composio's defaults. Pass an auth config ID per toolkit:

session = composio.sessions.create(
    user_id="user_123",
    auth_configs={
        "github": "ac_your_github_config",
        "slack": "ac_your_slack_config"
    }
)

See White-labeling authentication for branding, or Managed vs custom auth for toolkits that require your own credentials.

Account selection

When a user has multiple connected accounts for the same toolkit, specify which one the session uses:

session = composio.sessions.create(
    user_id="user_123",
    connected_accounts={
        "gmail": ["ca_work_gmail"],
        "github": ["ca_personal_github"],
    }
)

Arrays are the preferred format for connectedAccounts. A single string (e.g. "ca_work_gmail") is still accepted for backwards compatibility and is automatically coerced to a single-element array. Only one account per toolkit is allowed when multi-account mode is disabled.

Precedence

When executing a tool, the session selects the connected account in this order:

  1. The connectedAccounts override, if provided in the session config.
  2. The authConfigs override, which finds or creates a connection on that config.
  3. An auth config previously created for this toolkit.
  4. A new auth config created using Composio managed auth.
  5. Otherwise, an error if no Composio managed auth scheme exists for the toolkit.

When a user has multiple connected accounts for a toolkit, the session uses the most recently connected one.

Disabling the sandbox

By default, sessions include the sandbox, a persistent environment that provides COMPOSIO_REMOTE_WORKBENCH and COMPOSIO_REMOTE_BASH_TOOL. If your use case doesn't need code execution, disable it:

session = composio.sessions.create(
    user_id="user_123",
    sandbox={
        "enable": False
    }
)

When disabled:

  • COMPOSIO_REMOTE_WORKBENCH and COMPOSIO_REMOTE_BASH_TOOL are excluded from the session
  • Sandbox-related system prompt lines are stripped
  • Direct sandbox calls are rejected with a 400 error

Zero Data Retention does not cover the sandbox, so disable it in sessions that handle data that needs ZDR.

To keep the sandbox but block raw HTTP calls from it, set enable_proxy_execution (Python) or enableProxyExecution (TypeScript) to false. See Proxy execute for how session restrictions apply to proxy calls.

sandbox is the preferred config key. workbench still works as a fully supported alias and isn't deprecated, so existing code keeps running unchanged.

Sandbox compute tier

The sandbox runs per session. Pick a compute tier to match the workload: heavier code execution or larger in-memory data benefits from a bigger sandbox. Pass the tier via sandbox.sandbox_size (snake_case on the wire, sandboxSize in the TypeScript SDK).

Requires @composio/core ≥ 0.8.1 (TypeScript) or composio ≥ 0.12.1 (Python). Older SDKs reject sandboxSize (TypeScript) or silently drop sandbox_size (Python). See the release notes.

TiervCPURAM
standard11 GB
medium22 GB
large44 GB
xlarge88 GB

Defaults to standard when omitted.

session = composio.sessions.create(
    user_id="user_123",
    sandbox={
        "sandbox_size": "large",
    },
)

Pricing: Sandboxes are not billed today. Composio plans to begin billing for sandbox usage soon (metered by tier and runtime). Pick a tier that matches your workload, but expect future pricing to track actual usage.

Changing sandbox_size on an existing session recreates the sandbox on the next access. The sandbox's in-memory filesystem state is lost, but the persistent /mnt/files/ mount survives the restart.

Updating a session

session.update() patches the stored configuration in place. Fields you omit are preserved, so you can widen or narrow one part of a session without restating the rest. The SDK refreshes session.config and the session's config version only after the API accepts the change.

session = composio.sessions.use("session_id")

session.update(toolkits={"enable": ["gmail", "github"]})

The update behavior below requires @composio/core ≥ 0.19.1 (TypeScript) or composio ≥ 0.22.1 (Python).

Maps replace, they don't merge

A tools, authConfigs, or connectedAccounts map you send replaces the stored map entirely. The API does not merge entries, so a Slack-only tools map removes a Gmail entry that was stored before it.

Stored before the update:

{
  "tools": {
    "gmail": { "enable": ["GMAIL_FETCH_EMAILS"] },
    "slack": { "enable": ["SLACK_SEND_MESSAGE"] }
  }
}

The update:

session.update(
    tools={"slack": {"enable": ["SLACK_SEND_MESSAGE", "SLACK_LIST_CHANNELS"]}},
)

Stored after the update. The gmail entry is gone:

{
  "tools": {
    "slack": { "enable": ["SLACK_SEND_MESSAGE", "SLACK_LIST_CHANNELS"] }
  }
}

To change one entry, send the whole map with every entry you want to keep. An empty map ({}) is stored as an explicit empty map.

The same rule applies to toolkits, tags, and preload: a value replaces the stored policy. manageConnections, sandbox, and multiAccount merge the subfields you send, and an empty object changes nothing.

Narrowing an existing session to no app toolkits

An empty allowlist on update denies every app toolkit, exactly as it does on create. The SDK sends { "enable": [] } as-is instead of dropping it from the request.

session.update(toolkits={"enable": []})

Removing a callback URL

manageConnections.callbackUrl: null removes only the stored callback URL. enable and the other connection settings stay as they are. An empty string is rejected.

session.update(manage_connections={"callback_url": None})

Clearing a block with null

Passing null (None in Python) for a whole block removes the stored override and the session falls back to the default for that block. Every policy block accepts it: toolkits, tools, tags, authConfigs, connectedAccounts, preload, manageConnections, sandbox, multiAccount, search, execute, and experimental.

session.update(manage_connections=None, multi_account=None)

Clearing a policy can widen access. toolkits: null removes the toolkit policy and restores the unrestricted default, which is the opposite of { "enable": [] }; clearing preload does the same for preloaded tools, so the agent can reach more than before the update. Send toolkits: [] when you want to deny every app toolkit. Clearing multiAccount resolves to disabled, while omitting it preserves the stored setting.

Blocks you can set only on update

search, execute, and experimental are not part of create(). Reach them with session.update() on an existing session.

session.update(
    search={"enable": False},
    execute={"enable_multi_execute": False},
)

Both blocks are on by default. search controls the session's search helper, so disabling it leaves the agent with the tools you preloaded. execute.enableMultiExecute controls whether the agent can run several tool calls in one request. manageConnections.enableConnectionRemoval is update-only as well, and controls whether the session exposes the connection-removal tool.

The experimental block on update holds server-side session settings: permissions, linkUrlOverwrite, fastMode, submitFeedback, and sessionConfigId. sessionConfigId applies a saved Session config and can't be combined with toolkits, tools, or tags. The experimental block on update is a different field from the experimental option on create(), which holds custom tools and toolkits that run in your process, so experimental: null on an update leaves those alone.

Multi-account mode after an update

The canonical disabled state is { "enable": false, "require_explicit_selection": false } with no maximum. Sending enable: false resets a stale maximum or selection setting, and reapplying that disabled configuration is accepted. Combining enable: false with maxAccountsPerToolkit or requireExplicitSelection: true is rejected with a 400.

Preload must stay inside the policy

An update that narrows toolkits, tools, or tags while leaving an explicitly preloaded tool outside the new policy is rejected with a 400, and nothing changes. Fix preload in the same update:

session.update(
    toolkits={"enable": ["slack"]},
    preload={"tools": ["SLACK_SEND_MESSAGE"]},
)

Concurrent updates

Every session response carries a config version (session.configVersion in TypeScript, session.config_version in Python, config_version on the wire). By default, session.update() sends no precondition, so the last writer wins. To make an update conditional, pass the version you read as expectedConfigVersion (expected_config_version in Python). The API then applies the update only when the stored version still matches. Otherwise it answers 409 and writes nothing: no config change, no history entry, no cache update. The SDK never retries that request, so a conflict is reported exactly once.

The API must support expected_config_version. If it doesn't, it rejects a conditional update with a 400.

On a conflict, the SDK raises ComposioSessionConfigConflictError (TypeScript) or SessionConfigConflictError (Python) and leaves the session object as it was. Re-read the session with sessions.use(), reapply your change on top of the fresh config, and retry:

from composio.exceptions import SessionConfigConflictError

session = composio.sessions.use("session_id")

try:
    session.update(
        toolkits={"enable": ["gmail", "github"]},
        expected_config_version=session.config_version,
    )
except SessionConfigConflictError:
    # Another client changed the session first. Nothing was written.
    session = composio.sessions.use("session_id")
    session.update(
        toolkits={"enable": ["gmail", "github"]},
        expected_config_version=session.config_version,
    )

You can also pass a version you read elsewhere, for example one stored with a queued job. expectedConfigVersion: false (expected_config_version=False) is the same as omitting it. The API still commits only a fully validated configuration, so a losing update never leaves a half-applied session behind.

Raw HTTP callers set expected_config_version in the PATCH body themselves; without it the last writer wins.

To roll a session back, read a previous configuration from its config history (GET /api/v3.1/tool_router/session/{session_id}/config_history) and convert it into an update request. A history entry is not a request body: it carries metadata and version fields, and it names toolkits and tools as enabled and disabled, which map to enable and disable in the update.

Session methods

For framework examples, see provider-specific documentation like OpenAI or Vercel AI SDK. To connect over MCP instead, see Using sessions via MCP.

tools()

Get the tools the session exposes for your AI framework. By default these are the session's meta tools, formatted for your configured provider.

tools = session.tools()

authorize()

Manually authenticate a user to a toolkit outside of the chat flow.

connection_request = session.authorize("github")

print(connection_request.redirect_url)

connected_account = connection_request.wait_for_connection()

For more details, see Manually authenticating users.

toolkits()

List the toolkits enabled for the session and their connection status, sorted by popularity. Use it to build a UI showing which apps are connected. Each toolkit includes its slug, name, logo, and connection status, and the call returns the first 20 by default.

toolkits = session.toolkits()

for toolkit in toolkits.items:
    status = toolkit.connection.connected_account.id if toolkit.connection.is_active else "Not connected"
    print(f"{toolkit.name}: {status}")

Filter to only connected toolkits:

connected = session.toolkits(is_connected=True)

Paginate through every toolkit with limit and the returned cursor:

all_toolkits = []
cursor = None

while True:
    result = session.toolkits(limit=20, next_cursor=cursor)
    all_toolkits.extend(result.items)
    cursor = result.next_cursor
    if not cursor:
        break

update()

Patch the session configuration in place. See Updating a session for what omitted fields, replaced maps, null, and expectedConfigVersion do.

config = session.update(toolkits={"enable": ["gmail", "github"]})

Configuration history

Inspect the configurations a session has used with session.list_config_history(limit=10) in Python or await session.listConfigHistory({ limit: 10 }) in TypeScript. Results are newest first, with the live configuration first. Each session.update() archives the previous configuration.

The response contains items with each version's config and an is_current (Python) or isCurrent (TypeScript) flag. Pass the response's next_cursor (Python) or nextCursor (TypeScript) as cursor to fetch another page; limit supports up to 100 items per page.

delete()

Delete a session when you're done with it. Deleted sessions immediately stop being retrievable or executable, and the call returns the deleted session_id. Deleting a missing or already-deleted session surfaces the backend 404.

Requires @composio/core ≥ 0.13.1 (TypeScript) or composio ≥ 0.17.1 (Python).

result = session.delete()
print(result["session_id"], result["deleted"])

Browsing the catalog

Before configuring a session, explore the toolkits and tools available. Browse them visually at dashboard.composio.dev or in the docs catalog, or fetch them programmatically:

# List toolkits
toolkits = composio.toolkits.get()

# List tools within a toolkit (top 20 by default)
tools = composio.tools.get("user_123", toolkits=["GITHUB"])

Inspect a tool's input and output schema without a user context with getRawComposioToolBySlug:

tool = composio.tools.get_raw_composio_tool_by_slug("GMAIL_SEND_EMAIL")
print(tool.name)
print(tool.description)
print(tool.input_parameters)
print(tool.output_parameters)

To fetch several toolkits in one request, use composio.toolkits.get_many(["github", "slack"]) in Python or await composio.toolkits.getMany(['github', 'slack']) in TypeScript. Both return the matching toolkits.

Next

Sandbox

Give sessions a persistent compute environment with COMPOSIO_REMOTE_WORKBENCH and COMPOSIO_REMOTE_BASH_TOOL