# Tool Router The Tool Router provides a powerful way to create isolated MCP (Model Context Protocol) sessions for users with scoped access to toolkits and tools. It enables dynamic configuration of which tools are available within a session and manages authentication for multiple toolkits. ## Overview Tool Router allows you to: - Create isolated sessions with specific toolkit configurations - Manage authentication flows for users across multiple toolkits - Access tools via an MCP-compatible server URL - Query toolkit connection states - Integrate with multiple AI frameworks (Vercel AI SDK, LangChain, OpenAI Agents, Claude Agents SDK) > **Note:** When using MCP clients to connect to Tool Router, you don't need to pass a provider to the Composio constructor. A provider is only required when using `session.tools()` to get framework-specific tool objects. ## Quick Start ### Using MCP (Recommended) When using Tool Router with MCP clients, you don't need to pass a provider: ## Installation ```bash # npm npm install @composio/core@0.4.0 # pnpm pnpm add @composio/core@0.4.0 # yarn yarn add @composio/core@0.4.0 ``` ```typescript import { Composio } from '@composio/core'; const composio = new Composio(); // Create a session for a user with access to Gmail tools const session = await composio.create('user_123', { toolkits: ['gmail'], }); // Use the MCP URL with any MCP-compatible client console.log(session.mcp.url); ``` ### Using Framework-Specific Tools If you want to use `session.tools()` to get tools formatted for a specific AI framework, pass the appropriate provider: ```typescript import { Composio } from '@composio/core'; import { VercelProvider } from '@composio/vercel'; const composio = new Composio({ provider: new VercelProvider(), }); // Create a session for a user with access to Gmail tools const session = await composio.create('user_123', { toolkits: ['gmail'], }); // Get the tools formatted for Vercel AI SDK const tools = await session.tools(); ``` ## Creating Sessions ### Basic Session Creation Use `composio.create()` to create a new Tool Router session: ```typescript import { Composio } from '@composio/core'; const composio = new Composio(); // Create a session with Gmail access const session = await composio.create('user_123', { toolkits: ['gmail'], }); console.log('Session ID:', session.sessionId); console.log('MCP URL:', session.mcp.url); ``` ### Using an Existing Session If you have an existing session ID, you can retrieve it using `composio.use()`: ```typescript const session = await composio.use('existing_session_id'); // Access session properties console.log(session.sessionId); console.log(session.mcp.url); ``` ## Configuration Options The session creation accepts a configuration object with the following options: ### `toolkits` Specify which toolkits to enable or disable in the session. ```typescript // Simple array of toolkit slugs to enable const session = await composio.create('user_123', { toolkits: ['gmail', 'slack', 'github'], }); // Explicit enabled configuration const session = await composio.create('user_123', { toolkits: { enable: ['gmail', 'slack'] }, }); // Disable specific toolkits (enable all others) const session = await composio.create('user_123', { toolkits: { disable: ['calendar'] }, }); ``` ### `tools` Fine-grained control over which tools are available within toolkits. Configure tools per toolkit using the toolkit slug as the key. ```typescript const session = await composio.create('user_123', { toolkits: ['gmail', 'slack'], tools: { // Configure tools per toolkit gmail: ['gmail_fetch_emails', 'gmail_send_email'], // Only these tools // OR use enable/disable objects // gmail: { enable: ['gmail_fetch_emails'] } // gmail: { disable: ['gmail_delete_email'] } // You can also set tags per toolkit to override global tags slack: { tags: ['readOnlyHint'] }, }, }); ``` ### `tags` Global tags to filter tools by their behavior hints. Tags can be overridden per toolkit in the `tools` configuration. ```typescript const session = await composio.create('user_123', { toolkits: ['gmail', 'github'], // Global tags applied to all toolkits tags: ['readOnlyHint', 'idempotentHint'], }); ``` Available tags: - `readOnlyHint` - Tools that only read data - `destructiveHint` - Tools that modify or delete data - `idempotentHint` - Tools that can be safely retried - `openWorldHint` - Tools that operate in an open world context ### `authConfigs` Map toolkits to specific authentication configurations: ```typescript const session = await composio.create('user_123', { toolkits: ['gmail', 'github'], authConfigs: { gmail: 'ac_gmail_work', github: 'ac_github_personal', }, }); ``` ### `connectedAccounts` Map toolkits to specific connected account IDs: ```typescript const session = await composio.create('user_123', { toolkits: ['gmail'], connectedAccounts: { gmail: 'ca_abc123', }, }); ``` ### `manageConnections` Control how connections are managed within the session: ```typescript // Boolean: enable/disable automatic connection management const session = await composio.create('user_123', { toolkits: ['gmail'], manageConnections: true, // default }); // Object: fine-grained control const session = await composio.create('user_123', { toolkits: ['gmail'], manageConnections: { enable: true, callbackUrl: 'https://your-app.com/auth/callback', waitForConnections: true, // Wait for user to complete authentication before proceeding }, }); ``` #### Wait for Connections The `waitForConnections` property (new in v0.4.0) allows the tool router session to wait for users to complete authentication before proceeding to the next step. When set to `true`, the session will block execution until all required connections are established. ```typescript const session = await composio.create('user_123', { toolkits: ['gmail', 'slack'], manageConnections: { enable: true, callbackUrl: 'https://your-app.com/auth/callback', waitForConnections: true, // Session waits for connections to complete }, }); ``` ### `workbench` Configure workbench behavior for tool execution: ```typescript // Disable workbench entirely — no code execution tools in the session const session = await composio.create('user_123', { toolkits: ['gmail'], workbench: { enable: false } }); // Fine-tune workbench settings const session2 = await composio.create('user_123', { toolkits: ['gmail'], workbench: { enable: true, // default enableProxyExecution: true, autoOffloadThreshold: 400000, // Automatically offload to workbench if response > 400k characters }, }); ``` | Field | Type | Default | Description | |-------|------|---------|-------------| | `enable` | `boolean` | `true` | Enables/disables the workbench entirely. When `false`, `COMPOSIO_REMOTE_WORKBENCH` and `COMPOSIO_REMOTE_BASH_TOOL` are excluded from the session. | | `enableProxyExecution` | `boolean` | `true` | Controls proxy API execution in the workbench. | | `autoOffloadThreshold` | `number` | auto | Character threshold for auto-offloading large responses to the workbench. | ### `experimental` Configure experimental features for the session. These features are not stable and may be modified or removed in future versions. #### Assistive Prompt ```typescript const session = await composio.create('user_123', { toolkits: ['gmail'], experimental: { assistivePrompt: { userTimezone: 'America/New_York', // IANA timezone identifier for timezone-aware assistive prompts }, }, }); // Access the generated assistive prompt from the session response if (session.experimental?.assistivePrompt) { console.log('Assistive prompt:', session.experimental.assistivePrompt); } ``` The `userTimezone` field accepts an IANA timezone identifier (e.g., 'America/New_York', 'Europe/London') which is used to generate a timezone-aware system prompt for optimal tool router usage. #### Custom Tools & Custom Toolkits Define your own tools that run in-process alongside Composio's remote tools. Custom tools are automatically indexed for search and routed to your `execute` function when called. There are three ways to define custom tools: **1. Standalone tool** — no auth needed, passed in `customTools`: ```typescript import { experimental_createTool } from '@composio/core'; import { z } from 'zod/v3'; const grep = experimental_createTool('GREP', { name: 'Grep Search', description: 'Search for patterns in files', inputParams: z.object({ pattern: z.string(), path: z.string() }), execute: async input => ({ matches: [] }), }); ``` **2. Extension tool** — extends a Composio toolkit, inherits its auth. Passed in `customTools` with `extendsToolkit`: ```typescript const getImportant = experimental_createTool('GET_IMPORTANT_EMAILS', { name: 'Get Important Emails', description: 'Fetch high-priority emails', extendsToolkit: 'gmail', inputParams: z.object({ limit: z.number().default(10) }), execute: async (input, ctx) => { // Same response shape as session.execute(): { data, error, logId } const result = await ctx.execute('GMAIL_SEARCH', { query: 'is:important' }); return { emails: result.data }; }, }); ``` **3. Custom toolkit** — groups related no-auth tools. Passed in `customToolkits`: ```typescript import { experimental_createToolkit } from '@composio/core'; const sed = experimental_createTool('SED', { name: 'Sed Replace', description: 'Find and replace in files', inputParams: z.object({ pattern: z.string(), replacement: z.string() }), execute: async input => ({ replaced: 0 }), }); const devTools = experimental_createToolkit('DEV_TOOLS', { name: 'Dev Tools', description: 'Local dev utilities', tools: [sed], }); ``` **Creating a session with custom tools:** ```typescript const session = await composio.create('user_123', { toolkits: ['gmail'], experimental: { customTools: [grep, getImportant], customToolkits: [devTools], }, }); ``` **Executing custom tools** — use the same slug you defined: ```typescript // Standalone tool await session.execute('GREP', { pattern: 'TODO', path: '/src' }); // Extension tool await session.execute('GET_IMPORTANT_EMAILS', { limit: 5 }); // Toolkit tool await session.execute('SED', { pattern: 'foo', replacement: 'bar' }); ``` Custom tools are searched alongside Composio tools. When the LLM calls a custom tool, the SDK executes it in-process — remote tools in the same batch are sent to the backend in parallel. ## Session Properties A Tool Router session provides the following properties and methods: ### `sessionId` The unique identifier for this session. ```typescript console.log(session.sessionId); ``` ### `mcp` The MCP server configuration for this session, including authentication headers. ```typescript console.log(session.mcp.url); // The URL to connect to console.log(session.mcp.type); // 'http' or 'sse' console.log(session.mcp.headers); // Authentication headers (includes x-api-key if configured) ``` ### `tools()` Retrieve the tools available in the session, formatted for your AI framework. ```typescript const tools = await session.tools(); // With session-specific modifiers (new in v0.4.0) const tools = await session.tools({ modifySchema: ({ toolSlug, toolkitSlug, schema }) => { // Customize the tool schema return schema; }, beforeExecute: ({ toolSlug, toolkitSlug, sessionId, params }) => { console.log(`Executing ${toolSlug} in session ${sessionId}`); return params; }, afterExecute: ({ toolSlug, toolkitSlug, sessionId, result }) => { console.log(`Completed ${toolSlug} in session ${sessionId}`); return result; }, }); ``` #### Session-Specific Modifiers Tool Router sessions now support enhanced modifier types (introduced in v0.4.0) that include session context: - **`modifySchema`**: Customize tool schemas before they're sent to the AI model - **`beforeExecute`**: Modify parameters before execution, with access to session ID - **`afterExecute`**: Transform results after execution, with access to session ID These modifiers provide better context for session-based tool execution, allowing you to track which session is executing which tools. ### Meta Tools Tool Router provides meta tools for managing connections and session state. You can access these directly using the `getRawToolRouterMetaTools` method (introduced in v0.4.0): ```typescript import { Composio } from '@composio/core'; const composio = new Composio(); // Get raw meta tools for a session const metaTools = await composio.tools.getRawToolRouterMetaTools('session_123', { modifySchema: ({ toolSlug, toolkitSlug, schema }) => { // Customize meta tool schemas console.log(`Modifying schema for ${toolSlug}`); return schema; }, }); console.log( 'Available meta tools:', metaTools.map(t => t.name) ); ``` Meta tools allow you to: - Authorize new toolkit connections within a session - Query toolkit connection states - Manage session configuration This method is useful when you need direct access to the underlying meta tools without creating a full session object. ### `execute()` Execute a tool within the session. Custom tools run in-process; remote tools are sent to the Composio backend. Works with any tool — custom or remote — using the same API. ```typescript // Custom tool const result = await session.execute('GET_USER_CONTEXT', { category: 'prefs' }); console.log(result.data); // { preferences: { ... } } console.log(result.error); // null on success // Remote Composio tool — same API const weather = await session.execute('WEATHERMAP_WEATHER', { location: 'Tokyo' }); ``` ### `search()` Search for tools by semantic use case. Returns relevant tools with schemas and guidance. ```typescript const results = await session.search({ query: 'send an email via gmail' }); for (const result of results.results) { console.log(result.useCase); console.log(result.primaryToolSlugs); // e.g. ['GMAIL_SEND_EMAIL'] } ``` ### `proxyExecute()` Proxy an API call through Composio's auth layer using the session's connected account. The backend resolves the connected account from the toolkit within the session. `ctx.proxyExecute()` inside a custom tool returns the same response shape as `session.proxyExecute()`. ```typescript const result = await session.proxyExecute({ toolkit: 'github', endpoint: 'https://api.github.com/user', method: 'GET', parameters: [{ in: 'header', name: 'X-Custom', value: 'value' }], }); ``` ### `authorize()` Initiate an authorization flow for a toolkit. ```typescript // Start authorization for Gmail const connectionRequest = await session.authorize('gmail'); console.log(connectionRequest.redirectUrl); // URL to redirect user for auth // Wait for the user to complete authorization const connectedAccount = await connectionRequest.waitForConnection(); console.log('Connected:', connectedAccount); ``` ### `toolkits()` Query the connection state of toolkits in the session. ```typescript const { items, cursor, totalPages } = await session.toolkits(); for (const toolkit of items) { console.log(`${toolkit.name} (${toolkit.slug})`); console.log(` Connected: ${toolkit.connection?.isActive}`); if (toolkit.connection?.connectedAccount) { console.log(` Account ID: ${toolkit.connection.connectedAccount.id}`); console.log(` Status: ${toolkit.connection.connectedAccount.status}`); } } // Pagination support const moreToolkits = await session.toolkits({ cursor, limit: 10, }); // Filter by specific toolkits const filteredToolkits = await session.toolkits({ toolkits: ['gmail', 'slack'], }); // Combine filtering with pagination const paginatedFilteredToolkits = await session.toolkits({ toolkits: ['gmail', 'github'], limit: 5, cursor: 'cursor_abc', }); ``` ### `files` Each session has a virtual filesystem mount for storing and retrieving files. Use `session.experimental.files` to list, upload, download, and delete files. This is useful for agent workflows, document processing, and tools that need file access. ```typescript // Upload a file (from path, URL, File, or buffer) const file = await session.experimental.files.upload('/path/to/report.pdf'); const file = await session.experimental.files.upload(buffer, { remotePath: 'data.json' }); // List files with pagination const { items, nextCursor } = await session.experimental.files.list({ path: '/' }); // Download a file const remoteFile = await session.experimental.files.download('report.pdf'); const buffer = await remoteFile.buffer(); await remoteFile.save('/tmp/report.pdf'); // Delete a file await session.experimental.files.delete('/temp/cache.json'); ``` See [Tool Router Session Files](./tool-router-files.md) for full documentation, including upload input types (paths, URLs, `File`, buffers), mimetype detection, pagination, and the `RemoteFile` API. ## Framework Integrations ### Vercel AI SDK (with Provider) When using the `session.tools()` method, you need to pass a provider to get framework-specific tools: ```typescript import { openai } from '@ai-sdk/openai'; import { Composio } from '@composio/core'; import { VercelProvider } from '@composio/vercel'; import { stepCountIs, streamText } from 'ai'; const composio = new Composio({ provider: new VercelProvider(), }); const session = await composio.create('user_123', { toolkits: ['gmail'], }); const tools = await session.tools(); const stream = await streamText({ model: openai('gpt-4o-mini'), prompt: 'Find my last email from gmail?', stopWhen: stepCountIs(10), tools, }); for await (const textPart of stream.textStream) { process.stdout.write(textPart); } ``` ### Vercel AI SDK (with MCP Client) When using MCP clients, no provider is needed. The MCP client fetches tools directly from the MCP server URL: ```typescript import { openai } from '@ai-sdk/openai'; import { experimental_createMCPClient as createMCPClient } from '@ai-sdk/mcp'; import { Composio } from '@composio/core'; import { stepCountIs, streamText } from 'ai'; // No provider needed when using MCP const composio = new Composio(); const { mcp } = await composio.create('user_123', { toolkits: ['gmail'], manageConnections: true, tools: { gmail: { disable: ['gmail_send_email'], // Disable specific tools }, }, }); // Create MCP client using the session URL and headers const client = await createMCPClient({ transport: { type: 'http', url: mcp.url, headers: mcp.headers, // Uses pre-configured authentication headers }, }); const tools = await client.tools(); const stream = await streamText({ model: openai('gpt-4o-mini'), prompt: 'Find my last email from gmail?', stopWhen: stepCountIs(10), onStepFinish: step => { if (step.toolCalls.length > 0) { for (const toolCall of step.toolCalls) { console.log(`Executed ${toolCall.toolName}`); } } }, tools, }); for await (const textPart of stream.textStream) { process.stdout.write(textPart); } ``` ### LangChain LangChain can connect to Tool Router via MCP adapters. No provider is needed: ```typescript import { MultiServerMCPClient } from '@langchain/mcp-adapters'; import { ChatOpenAI } from '@langchain/openai'; import { createAgent } from 'langchain'; import { Composio } from '@composio/core'; // No provider needed when using MCP const composio = new Composio(); const llm = new ChatOpenAI({ model: 'gpt-4o', }); const session = await composio.create('user_123', { toolkits: ['gmail'], }); const client = new MultiServerMCPClient({ composio: { transport: 'http', url: session.mcp.url, headers: session.mcp.headers, // Uses pre-configured authentication headers }, }); const tools = await client.getTools(); const agent = createAgent({ name: 'Gmail Assistant', systemPrompt: 'You are a helpful gmail assistant.', model: llm, tools, }); const result = await agent.invoke({ messages: [{ role: 'user', content: 'Fetch my last email from gmail' }], }); console.log(result); ``` ### OpenAI Agents SDK OpenAI Agents SDK supports hosted MCP tools. No provider is needed: ```typescript import { Agent, run, hostedMcpTool } from '@openai/agents'; import { Composio } from '@composio/core'; // No provider needed when using MCP const composio = new Composio(); const session = await composio.create('user_123', { toolkits: ['gmail'], }); console.log(`Tool Router Session Created: ${session.sessionId}`); console.log(`Connecting to MCP server: ${session.mcp.url}`); const mcpTool = hostedMcpTool({ serverLabel: 'ComposioApps', serverUrl: session.mcp.url, headers: session.mcp.headers, // Uses pre-configured authentication headers }); const agent = new Agent({ name: 'Gmail Assistant', instructions: 'You are a helpful gmail assistant.', tools: [mcpTool], }); const result = await run(agent, 'Summarize my last email from gmail', { stream: true, }); const stream = result.toStream(); for await (const event of stream) { if (event.type === 'raw_model_stream_event' && event.data.delta) { process.stdout.write(event.data.delta); } } ``` ### Claude Agents SDK Claude Agents SDK supports MCP servers natively. No provider is needed: ```typescript import { query } from '@anthropic-ai/claude-agent-sdk'; import { Composio } from '@composio/core'; // No provider needed when using MCP const composio = new Composio(); const session = await composio.create('user_123', { toolkits: ['gmail'], }); const stream = await query({ prompt: 'Use composio tools to fetch my last email from gmail', options: { model: 'claude-sonnet-4-5-20250929', permissionMode: 'bypassPermissions', mcpServers: { composio: { type: 'http', url: session.mcp.url, headers: session.mcp.headers, // Uses pre-configured authentication headers }, }, }, }); for await (const event of stream) { if (event.type === 'result' && event.subtype === 'success') { process.stdout.write(event.result); } } ``` ## Authorization Flow When a user needs to connect a toolkit, use the `authorize()` method: ```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const session = await composio.create('user_123', { toolkits: ['gmail'], }); // Initiate authorization for Gmail const connectionRequest = await session.authorize('gmail'); // Log the redirect URL for the user console.log('Redirect URL:', connectionRequest.redirectUrl); // Wait for the user to complete the authorization const connectedAccount = await connectionRequest.waitForConnection(); console.log('Connected Account:', connectedAccount); ``` You can also provide a custom callback URL: ```typescript const connectionRequest = await session.authorize('gmail', { callbackUrl: 'https://your-app.com/auth/callback', }); ``` ## Querying Toolkit States Use the `toolkits()` method to check connection states: ```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const session = await composio.create('user_123'); // Get all toolkits const toolkits = await session.toolkits(); console.log(JSON.stringify({ toolkits }, null, 2)); // Filter by specific toolkits const gmailAndSlack = await session.toolkits({ toolkits: ['gmail', 'slack'], }); ``` The response includes: ```typescript { items: [ { slug: 'gmail', name: 'Gmail', logo: 'https://...', isNoAuth: false, connection: { isActive: true, authConfig: { id: 'ac_xxx', mode: 'OAUTH2', isComposioManaged: true }, connectedAccount: { id: 'ca_xxx', status: 'ACTIVE' } } } ], cursor: 'cursor_abc', totalPages: 1 } ``` ## Using Modifiers Add custom behavior before and after tool execution. Tool Router supports enhanced session-specific modifiers (v0.4.0+): ```typescript import { SessionExecuteMetaModifiers } from '@composio/core'; const modifiers: SessionExecuteMetaModifiers = { modifySchema: ({ toolSlug, toolkitSlug, schema }) => { // Customize tool schema console.log(`Modifying schema for ${toolSlug}`); return schema; }, beforeExecute: ({ toolSlug, toolkitSlug, sessionId, params }) => { console.log(`[Session: ${sessionId}] Executing ${toolSlug} from ${toolkitSlug}`); // Add custom logging, validation, or parameter transformation return params; }, afterExecute: ({ toolSlug, toolkitSlug, sessionId, result }) => { console.log(`[Session: ${sessionId}] Executed ${toolSlug} from ${toolkitSlug}`); // Transform results, add telemetry, or handle errors return result; }, }; const tools = await session.tools(modifiers); ``` ### Modifier Types Tool Router provides specialized modifier types for session-based execution: - **`SessionExecuteMetaModifiers`**: Complete set of modifiers with session context - **`SessionMetaToolOptions`**: Configuration options for meta tools These types include the `sessionId` in their parameters, allowing you to track and manage tool execution across different user sessions. ## Best Practices 1. **User Isolation**: Create separate sessions per user to ensure proper isolation of connections and tools. 2. **Toolkit Selection**: Only enable toolkits that are necessary for the use case to maintain security and reduce complexity. 3. **Connection Management**: Use `manageConnections: true` (default) for interactive applications where users can be prompted to connect accounts. 4. **Tag Filtering**: Use global `tags` to filter tools by their behavior (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) and override per toolkit when needed. 5. **Session Reuse**: Store and reuse `sessionId` to maintain user sessions across requests. ```typescript // Store session ID after creation const session = await composio.create('user_123', config); await redis.set(`session:user_123`, session.sessionId); // Retrieve existing session const sessionId = await redis.get(`session:user_123`); if (sessionId) { const session = await composio.use(sessionId); } ``` ## Type Reference ### ToolRouterCreateSessionConfig ```typescript interface ToolRouterCreateSessionConfig { toolkits?: string[] | { enable: string[] } | { disable: string[] }; tools?: Record< string, | string[] | { enable: string[] } | { disable: string[] } | { tags: ('readOnlyHint' | 'destructiveHint' | 'idempotentHint' | 'openWorldHint')[] } >; tags?: ('readOnlyHint' | 'destructiveHint' | 'idempotentHint' | 'openWorldHint')[]; authConfigs?: Record; connectedAccounts?: Record; manageConnections?: | boolean | { enable?: boolean; callbackUrl?: string; waitForConnections?: boolean; // NEW in v0.4.0: Wait for connections to complete }; workbench?: { enable?: boolean; // Enable/disable workbench entirely (default: true) enableProxyExecution?: boolean; autoOffloadThreshold?: number; }; experimental?: { assistivePrompt?: { userTimezone?: string; // IANA timezone identifier for timezone-aware assistive prompts }; customTools?: CustomTool[]; // Standalone or extension tools (from experimental_createTool) customToolkits?: CustomToolkit[]; // Grouped no-auth tools (from experimental_createToolkit) }; } ``` ### ToolRouterSession ```typescript interface ToolRouterSession { sessionId: string; mcp: { type: 'http' | 'sse'; url: string; headers?: Record; // Authentication headers (includes x-api-key if configured) }; tools: (modifiers?: ProviderOptions) => Promise; execute: ( toolSlug: string, arguments?: Record ) => Promise; search: (params: { query: string; toolkits?: string[]; }) => Promise; proxyExecute: ( params: SessionProxyExecuteParams ) => Promise; authorize: (toolkit: string, options?: { callbackUrl?: string }) => Promise; toolkits: (options?: { toolkits?: string[]; // Filter by specific toolkit slugs cursor?: string; // Pagination cursor limit?: number; // Number of items per page }) => Promise; files: ToolRouterSessionFilesMount; // List, upload, download, delete files. See tool-router-files.md experimental?: { assistivePrompt?: string; // Generated system prompt for optimal tool router usage }; } ``` ### ToolkitConnectionState ```typescript interface ToolkitConnectionState { slug: string; name: string; logo?: string; isNoAuth: boolean; connection: { isActive: boolean; authConfig?: { id: string; mode: string; isComposioManaged: boolean; }; connectedAccount?: { id: string; status: string; }; }; } ``` ### SessionExecuteMetaModifiers (v0.4.0+) ```typescript interface SessionExecuteMetaModifiers { modifySchema?: (context: { toolSlug: string; toolkitSlug: string; schema: any }) => any; beforeExecute?: (context: { toolSlug: string; toolkitSlug: string; sessionId: string; params: any; }) => any; afterExecute?: (context: { toolSlug: string; toolkitSlug: string; sessionId: string; result: any; }) => any; } ``` ## What's New in v0.4.0 ### 1. Wait for Connections The new `waitForConnections` property allows sessions to wait for users to complete authentication before proceeding: ```typescript const session = await composio.create('user_123', { toolkits: ['gmail', 'slack'], manageConnections: { enable: true, callbackUrl: 'https://your-app.com/callback', waitForConnections: true, // NEW }, }); ``` ### 2. Enhanced Session Modifiers Session-specific modifiers now include session context, making it easier to track and manage tool execution: ```typescript const tools = await session.tools({ beforeExecute: ({ toolSlug, toolkitSlug, sessionId, params }) => { console.log(`[${sessionId}] Executing ${toolSlug}`); return params; }, }); ``` ### 3. Direct Meta Tools Access New method to fetch meta tools directly from a session: ```typescript const metaTools = await composio.tools.getRawToolRouterMetaTools('session_123', { modifySchema: ({ toolSlug, schema }) => schema, }); ``` ### 4. Performance Improvements - Optimized tool fetching with fewer API calls - Improved session API architecture for better reliability - Simplified internal tool execution paths All changes in v0.4.0 are fully backward compatible with existing code.