Users and sessions

View as markdown

A user ID is an identifier from your system (database ID, UUID, or any unique string) that scopes connected accounts and tool access to a specific user. User IDs can represent individuals, teams, or organizations. See User Management for patterns.

A session is an ephemeral configuration that combines:

  • Which user's connected accounts to use
  • Which toolkits are available
  • Which auth configs to use

Tool Router's meta-tools are the same for everyone. The session determines the context they operate within.

Creating a session

session = composio.create(user_id="user_123")
const const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const userId = 'user_123'; const session = await composio.create(userId, { manageConnections: true, }); console.log(session.sessionId); console.log(session.url); console.log(session.tools()); ```
create
("user_123");

Enabling toolkits

Restrict the session to specific toolkits:

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

# Using object format with enable key
session = composio.create(
    user_id="user_123",
    toolkits={"enable": ["github", "gmail", "slack"]}
)
// Using array format
const const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const userId = 'user_123'; const session = await composio.create(userId, { manageConnections: true, }); console.log(session.sessionId); console.log(session.url); console.log(session.tools()); ```
create
("user_123", {
toolkits?: string[] | {
    disable: string[];
} | {
    enable: string[];
} | undefined
toolkits
: ["github", "gmail", "slack"],
}); // Using object format with enable key const const session2: ToolRouterSession<unknown, unknown, OpenAIProvider>session2 = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const userId = 'user_123'; const session = await composio.create(userId, { manageConnections: true, }); console.log(session.sessionId); console.log(session.url); console.log(session.tools()); ```
create
("user_123", {
toolkits?: string[] | {
    disable: string[];
} | {
    enable: string[];
} | undefined
toolkits
: { enable: string[]enable: ["github", "gmail", "slack"] },
});

Disabling toolkits

Keep all toolkits enabled except specific ones:

session = composio.create(
    user_id="user_123",
    toolkits={"disable": ["exa", "firecrawl"]}
)
const const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const userId = 'user_123'; const session = await composio.create(userId, { manageConnections: true, }); console.log(session.sessionId); console.log(session.url); console.log(session.tools()); ```
create
("user_123", {
toolkits?: string[] | {
    disable: string[];
} | {
    enable: string[];
} | undefined
toolkits
: { disable: string[]disable: ["exa", "firecrawl"] },
});

Custom auth configs

Use your own OAuth credentials instead of Composio's defaults:

session = composio.create(
    user_id="user_123",
    auth_configs={
        "github": "ac_your_github_config",
        "slack": "ac_your_slack_config"
    }
)
const const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const userId = 'user_123'; const session = await composio.create(userId, { manageConnections: true, }); console.log(session.sessionId); console.log(session.url); console.log(session.tools()); ```
create
("user_123", {
authConfigs?: Record<string, string> | undefinedauthConfigs: { github: stringgithub: "ac_your_github_config", slack: stringslack: "ac_your_slack_config", }, });

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

Connected accounts

Connected accounts are stored in Composio and persist across sessions. When a user connects their GitHub account in one session, it remains available in future sessions. Sessions configure which connections to use, but don't own the connections themselves.

Account selection

If a user has multiple connected accounts for the same toolkit, you can specify which one to use:

session = composio.create(
    user_id="user_123",
    connected_accounts={
        "gmail": "ca_work_gmail",
        "github": "ca_personal_github"
    }
)
const const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.create: (userId: string, routerConfig?: ToolRouterCreateSessionConfig) => Promise<ToolRouterSession<unknown, unknown, OpenAIProvider>>
Creates a new tool router session for a user.
@paramuserId The user id to create the session for@paramconfig The config for the tool router session@returnsThe tool router session@example```typescript import { Composio } from '@composio/core'; const composio = new Composio(); const userId = 'user_123'; const session = await composio.create(userId, { manageConnections: true, }); console.log(session.sessionId); console.log(session.url); console.log(session.tools()); ```
create
("user_123", {
connectedAccounts?: Record<string, string> | undefinedconnectedAccounts: { gmail: stringgmail: "ca_work_gmail", github: stringgithub: "ca_personal_github", }, });

Precedence

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

  1. connectedAccounts override if provided in session config
  2. authConfigs override - finds or creates connection on that config
  3. Auth config previously created by Tool Router for this toolkit
  4. Creates new auth config using Composio managed auth (tagged as Tool Router created)
  5. Error if no Composio managed auth scheme exists for the toolkit

If a user has multiple connected accounts for a toolkit, the most recently connected one is used.

Session methods

mcp

Get the MCP server URL to use with any MCP-compatible client.

mcp_url = session.mcp.url
const { 
const mcp: {
    type: "http" | "sse";
    url: string;
    headers?: Record<string, string> | undefined;
}
The MCP server config of the tool router session. Contains the URL, type ('http' or 'sse'), and headers for authentication.
mcp
} = const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session;
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(
const mcp: {
    type: "http" | "sse";
    url: string;
    headers?: Record<string, string> | undefined;
}
The MCP server config of the tool router session. Contains the URL, type ('http' or 'sse'), and headers for authentication.
mcp
.url: stringurl);

For framework examples, see provider-specific documentation like OpenAI Agents or Vercel AI SDK.

tools()

Get native tools from the session for use with AI frameworks.

tools = session.tools()
const const tools: OpenAiToolCollectiontools = await const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session.ToolRouterSession<unknown, unknown, OpenAIProvider>.tools: (modifiers?: SessionMetaToolOptions) => Promise<OpenAiToolCollection>
Get the tools available in the session, formatted for your AI framework. Requires a provider to be configured in the Composio constructor.
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()
const const connectionRequest: ConnectionRequestconnectionRequest = await const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session.
ToolRouterSession<unknown, unknown, OpenAIProvider>.authorize: (toolkit: string, options?: {
    callbackUrl?: string;
}) => Promise<ConnectionRequest>
Initiate an authorization flow for a toolkit. Returns a ConnectionRequest with a redirect URL for the user.
authorize
("github", {
callbackUrl?: string | undefinedcallbackUrl: "https://myapp.com/callback", }); var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(const connectionRequest: ConnectionRequestconnectionRequest.ConnectionRequestState.redirectUrl?: string | null | undefinedredirectUrl);
const
const connectedAccount: {
    id: string;
    authConfig: TypeOf<ZodObject<{
        id: ZodString;
        isComposioManaged: ZodBoolean;
        isDisabled: ZodBoolean;
    }, "strip", ZodTypeAny, {
        id: string;
        isComposioManaged: boolean;
        isDisabled: boolean;
    }, {
        id: string;
        isComposioManaged: boolean;
        isDisabled: boolean;
    }>>;
    data?: Record<string, unknown>;
    params?: Record<string, unknown>;
    status: ConnectedAccountStatusEnum;
    ... 6 more ...;
    updatedAt: string;
}
connectedAccount
= await const connectionRequest: ConnectionRequestconnectionRequest.ConnectionRequest.waitForConnection: (timeout?: number) => Promise<ConnectedAccountRetrieveResponse>waitForConnection();

For more details, see Manually authenticating users.

toolkits()

List available toolkits and their connection status. You can use this to build a UI showing which apps are connected.

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}")
const 
const toolkits: {
    items: {
        slug: string;
        name: string;
        isNoAuth: boolean;
        logo?: string | undefined;
        connection?: {
            isActive: boolean;
            connectedAccount?: {
                status: string;
                id: string;
            } | undefined;
            authConfig?: {
                id: string;
                isComposioManaged: boolean;
                mode: string;
            } | null | undefined;
        } | undefined;
    }[];
    totalPages: number;
    nextCursor?: string | undefined;
}
toolkits
= await const session: ToolRouterSession<unknown, unknown, OpenAIProvider>session.ToolRouterSession<unknown, unknown, OpenAIProvider>.toolkits: (options?: ToolRouterToolkitsOptions) => Promise<ToolkitConnectionsDetails>
Query the connection state of toolkits in the session. Supports pagination and filtering by toolkit slugs.
toolkits
();
const toolkits: {
    items: {
        slug: string;
        name: string;
        isNoAuth: boolean;
        logo?: string | undefined;
        connection?: {
            isActive: boolean;
            connectedAccount?: {
                status: string;
                id: string;
            } | undefined;
            authConfig?: {
                id: string;
                isComposioManaged: boolean;
                mode: string;
            } | null | undefined;
        } | undefined;
    }[];
    totalPages: number;
    nextCursor?: string | undefined;
}
toolkits
.
items: {
    slug: string;
    name: string;
    isNoAuth: boolean;
    logo?: string | undefined;
    connection?: {
        isActive: boolean;
        connectedAccount?: {
            status: string;
            id: string;
        } | undefined;
        authConfig?: {
            id: string;
            isComposioManaged: boolean;
            mode: string;
        } | null | undefined;
    } | undefined;
}[]
items
.
Array<{ slug: string; name: string; isNoAuth: boolean; logo?: string | undefined; connection?: { isActive: boolean; connectedAccount?: { status: string; id: string; } | undefined; authConfig?: { id: string; isComposioManaged: boolean; mode: string; } | null | undefined; } | undefined; }>.forEach(callbackfn: (value: {
    slug: string;
    name: string;
    isNoAuth: boolean;
    logo?: string | undefined;
    connection?: {
        isActive: boolean;
        connectedAccount?: {
            status: string;
            id: string;
        } | undefined;
        authConfig?: {
            id: string;
            isComposioManaged: boolean;
            mode: string;
        } | null | undefined;
    } | undefined;
}, index: number, array: {
    slug: string;
    name: string;
    isNoAuth: boolean;
    logo?: string | undefined;
    connection?: {
        isActive: boolean;
        connectedAccount?: {
            status: string;
            id: string;
        } | undefined;
        authConfig?: {
            id: string;
            isComposioManaged: boolean;
            mode: string;
        } | null | undefined;
    } | undefined;
}[]) => void, thisArg?: any): void
Performs the specified action for each element in an array.
@paramcallbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
forEach
((
toolkit: {
    slug: string;
    name: string;
    isNoAuth: boolean;
    logo?: string | undefined;
    connection?: {
        isActive: boolean;
        connectedAccount?: {
            status: string;
            id: string;
        } | undefined;
        authConfig?: {
            id: string;
            isComposioManaged: boolean;
            mode: string;
        } | null | undefined;
    } | undefined;
}
toolkit
) => {
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v24.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(`${
toolkit: {
    slug: string;
    name: string;
    isNoAuth: boolean;
    logo?: string | undefined;
    connection?: {
        isActive: boolean;
        connectedAccount?: {
            status: string;
            id: string;
        } | undefined;
        authConfig?: {
            id: string;
            isComposioManaged: boolean;
            mode: string;
        } | null | undefined;
    } | undefined;
}
toolkit
.name: stringname}: ${
toolkit: {
    slug: string;
    name: string;
    isNoAuth: boolean;
    logo?: string | undefined;
    connection?: {
        isActive: boolean;
        connectedAccount?: {
            status: string;
            id: string;
        } | undefined;
        authConfig?: {
            id: string;
            isComposioManaged: boolean;
            mode: string;
        } | null | undefined;
    } | undefined;
}
toolkit
.
connection?: {
    isActive: boolean;
    connectedAccount?: {
        status: string;
        id: string;
    } | undefined;
    authConfig?: {
        id: string;
        isComposioManaged: boolean;
        mode: string;
    } | null | undefined;
} | undefined
connection
?.
connectedAccount?: {
    status: string;
    id: string;
} | undefined
connectedAccount
?.id: string | undefinedid ?? "Not connected"}`);
});

Returns the first 20 toolkits by default.