Files
2026-07-13 12:38:34 +08:00

1089 lines
30 KiB
Markdown

# 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<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?: {
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<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<ToolRouterSessionProxyExecuteResponse>;
authorize: (toolkit: string, options?: { callbackUrl?: string }) => Promise<ConnectionRequest>;
toolkits: (options?: {
toolkits?: string[]; // Filter by specific toolkit slugs
cursor?: 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.