Back to Composio

Tool Router

ts/docs/api/tool-router.md

0.11.129.1 KB
Original Source

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

When using Tool Router with MCP clients, you don't need to pass a provider:

Installation

bash
# npm
npm install @composio/[email protected]

# pnpm
pnpm add @composio/[email protected]

# yarn
yarn add @composio/[email protected]
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
const session = await composio.create('user_123', {
  toolkits: ['gmail'],
  workbench: {
    enableProxyExecution: true,
    autoOffloadThreshold: 400000 // Automatically offload to workbench if response > 400k characters
  }
});

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) => {
    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.

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, nextCursor, 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({ 
  nextCursor: nextCursor,
  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,
  nextCursor: '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 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'
        }
      }
    }
  ],
  nextCursor: '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<string, string>;
  connectedAccounts?: Record<string, string>;
  manageConnections?: boolean | {
    enable?: boolean;
    callbackUrl?: string;
    waitForConnections?: boolean; // NEW in v0.4.0: Wait for connections to complete
  };
  workbench?: {
    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<string, string>; // Authentication headers (includes x-api-key if configured)
  };
  tools: (modifiers?: ProviderOptions) => Promise<Tools>;
  execute: (toolSlug: string, arguments?: Record<string, unknown>) => Promise<ToolRouterSessionExecuteResponse>;
  search: (params: { query: string; toolkits?: string[] }) => Promise<ToolRouterSessionSearchResponse>;
  proxyExecute: (params: SessionProxyExecuteParams) => Promise<ToolRouterSessionExecuteResponse>;
  authorize: (toolkit: string, options?: { callbackUrl?: string }) => Promise<ConnectionRequest>;
  toolkits: (options?: {
    toolkits?: string[];   // Filter by specific toolkit slugs
    nextCursor?: string;   // Pagination cursor
    limit?: number;        // Number of items per page
  }) => Promise<ToolkitConnectionsDetails>;
  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.