Our next generation SDKs

View as markdown

In the last few months, we have experienced very rapid growth in usage of our platform. As such, our team has been working hard to radically improve the performance and developer experience of our platform.

A lot of these changes have happened in the background, but we are excited to finally share our new SDKs with you that complement our new infra.

The new API features improved usability, enhanced stability, and better scalability. The SDKs built on top of it simplify the developer experience, making it easier than ever to build useful agents.

What's new?

A lot of the changes are on the infra side, but from the SDK point of view, here is what you can expect:

  • Faster and more reliable tool execution
  • A simpler but more opinionated SDK
  • Much more intuitive and consistent naming conventions
  • A vastly improved TypeScript SDK that is meaningfully more type-safe and has full feature parity with the Python SDK

There aren't too many new flashy features here (yet) mainly because we wanted to get the bones right — but we feel we have a solid foundation to ship incredible new experiences on top very quickly.

State of the new SDK and what is happening with the old SDKs?

Currently, the new SDKs are in a preview release. These new SDKs come almost fully formed, we do not expect many breaking changes to them but are releasing them in a preview state to get feedback and make necessary changes before locking them in.

As we lock the new SDKs in place, we will deprecate support for the old SDKs. They will continue to work for the foreseeable future but are no longer actively maintained. We will continue to push security updates and fix any critical bugs but will not support any new functionality in them.

We urge you to upgrade to the new SDKs as soon as possible.

Nomenclature

We have updated several key terms in the SDK and API to improve clarity and consistency. The following table summarizes these changes:

Previous TermCurrent TermDefinition
ActionsToolsIndividual operations or capabilities that can be performed by an LLM agent
AppsToolkitsA collection of tools grouped under a single application
IntegrationAuth ConfigConfiguration containing developer credentials and application-level settings such as scopes and API endpoints. Scoped to a toolkit.
ConnectionConnected accountsUser-linked accounts associated with a toolkit
Entity IDUser IDThe identifier of the user performing the action (UUID or email)
TriggerTriggerAn event that can be subscribed to
ToolsetsProvidersLLM or agent framework that can be used with Composio to create agents

Switch to nano IDs from UUIDs

We have transitioned from UUIDs to nano IDs throughout the platform for the following reasons:

  • Improved readability: UUIDs are lengthy and difficult to read
  • Better usability: Easier to copy with a single double-click
  • Better organization: Nano IDs allow us to distinguish between different resource types through prefixes
FeatureNano ID PrefixExample
Connected Accountca_ca_8x9w2l3k5m
Auth Configac_ac_1234567890
Triggerti_ti_So9EQf8XnAcy

Nano IDs are short, unique, and prefixed to indicate the resource type.

SDK Changes

Upgrade to the latest SDK version using the appropriate package manager:

pip install -U composio
npm install @composio/core

Both SDKs now implement proper namespacing for each concept.

User ID scoping

The concept of entity_id has been expanded and renamed to user_id.

All operations are now scoped to a user ID, including:

  • Fetching tools
  • Initiating connections
  • Executing tools
  • Managing triggers

This change provides explicit specification of the user for whom the action is being performed. When a user may have multiple accounts (such as work and personal Gmail connections), you can use the more specific connected account ID.

Replacing ToolSets with Providers

We have deprecated "toolsets" in favor of "providers". This change allows Composio to provide deeper standardization for tool implementation across different frameworks.

Previously, you needed to import and use a framework-specific ComposioToolSet class:

from composio_openai import ComposioToolSet, Action, App
from openai import OpenAI

toolset = ComposioToolSet()
import { import OpenAIToolSetOpenAIToolSet } from 'composio-core';

const const toolset: anytoolset = new import OpenAIToolSetOpenAIToolSet();

The SDK structure is now framework-agnostic and includes the OpenAI provider out of the box:

from composio import Composio
# from composio_langchain import LangchainProvider

composio = Composio()
# composio = Composio(provider=LangchainProvider())

tools = composio.tools.get(
    user_id="0001",
    tools=["LINEAR_CREATE_LINEAR_ISSUE", "GITHUB_CREATE_COMMIT"]
)
# tools returned is formatted for the provider. by default, OpenAI.
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
// import { VercelProvider } from '@composio/vercel'; const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
({
// provider: new VercelProvider(), }); // Can specify other providers too, like OpenAI, Anthropic, Vercel AI SDK. const const tools: OpenAiToolCollectiontools = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.get<OpenAIProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<OpenAiToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
('user@example.com', {
tools: string[]tools: ['LINEAR_CREATE_LINEAR_ISSUE', 'GITHUB_CREATE_COMMIT'], }); // tools returned is formatted for the provider. by default, OpenAI.

You can now use the same tools across any framework with our unified interface, or create custom toolsets for frameworks we don't yet support.

Read more about providers in our documentation and explore the complete list of available providers.

Fetching and filtering tools

Previously, you could filter tools by:

  • Apps
  • Action names (tool names)
  • Tags

You could also specify an important flag to retrieve the most important tools:

from composio_openai import ComposioToolSet, Action, App
from openai import OpenAI

toolset = ComposioToolSet()
client = OpenAI()

tools = toolset.get_tools(
    actions=[Action.GITHUB_GET_THE_AUTHENTICATED_USER], check_connected_accounts=True
)

tools = toolset.get_tools(apps=[App.GITHUB, App.LINEAR, App.SLACK], check_connected_accounts=True)
import { import OpenAIToolSetOpenAIToolSet } from 'composio-core';

const const toolset: anytoolset = new import OpenAIToolSetOpenAIToolSet();

const const tools_1: anytools_1 = await const toolset: anytoolset.getTools({ apps: string[]apps: ['GITHUB'] });
const const tools_2: anytools_2 = await const toolset: anytoolset.getTools({
  actions: string[]actions: ['GITHUB_GET_THE_AUTHENTICATED_USER', 'LINEAR_CREATE_LINEAR_ISSUE'],
});

You can now filter tools by:

  • Toolkits
  • Tool slugs
  • Limit parameter
  • Search query

The important flag has been removed. Instead, tools are returned in order of importance by default:

Since user_id is now explicitly required, the check_connected_accounts flag is no longer necessary.

from composio import Composio

composio = Composio()

user_id = "user@acme.org"

tools_1 = composio.tools.get(user_id=user_id, toolkits=["GITHUB", "LINEAR"])

tools_2 = composio.tools.get(user_id=user_id, toolkits=["SLACK"], limit=5)  # Default limit=20

tools_3 = composio.tools.get(
    user_id=user_id,
    tools=["GITHUB_CREATE_AN_ISSUE", "GITHUB_CREATE_AN_ISSUE_COMMENT", "GITHUB_CREATE_A_COMMIT"],
)

tools_4 = composio.tools.get(user_id="john", search="hackernews posts")
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
const const userId: "user@acme.org"userId = 'user@acme.org'; const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
const const tools_1: OpenAiToolCollectiontools_1 = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.get<OpenAIProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<OpenAiToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
(const userId: "user@acme.org"userId, {
toolkits: [string, string]toolkits: ['GITHUB', 'LINEAR'], }); const const tools_2: OpenAiToolCollectiontools_2 = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.get<OpenAIProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<OpenAiToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
(const userId: "user@acme.org"userId, {
toolkits: [string]toolkits: ['GITHUB'], limit: numberlimit: 5, // Default limit=20 }); const const tools_3: OpenAiToolCollectiontools_3 = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.get<OpenAIProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<OpenAiToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
(const userId: "user@acme.org"userId, {
tools: string[]tools: ['GITHUB_CREATE_AN_ISSUE', 'GITHUB_CREATE_AN_ISSUE_COMMENT', 'GITHUB_CREATE_A_COMMIT'], }); const const tools_4: OpenAiToolCollectiontools_4 = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.get<OpenAIProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<OpenAiToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
(const userId: "user@acme.org"userId, {
search: stringsearch: 'hackernews posts', });

Fetching raw tool data

To examine the raw schema definition of a tool for understanding input/output parameters or building custom logic around tool definitions, use the following methods:

from composio import Composio

composio = Composio()

tool = composio.tools.get_raw_composio_tool_by_slug("HACKERNEWS_GET_LATEST_POSTS")

print(tool.model_dump_json())
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
const
const tool: {
    slug: string;
    name: string;
    description?: string | undefined;
    inputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    outputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    ... 6 more ...;
    isNoAuth?: boolean | undefined;
}
tool
= await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.getRawComposioToolBySlug(slug: string, options?: SchemaModifierOptions): Promise<Tool>
Retrieves a specific tool by its slug from the Composio API. This method fetches a single tool in raw format without provider-specific wrapping, providing direct access to the tool's schema and metadata. Tool versions are controlled at the Composio SDK initialization level through the `toolkitVersions` configuration.
@paramslug - The unique identifier of the tool (e.g., 'GITHUB_GET_REPOS')@paramoptions - Optional configuration for tool retrieval@paramoptions.modifySchema - Function to transform the tool schema@returnsThe requested tool with its complete schema and metadata@example```typescript // Get a tool by slug const tool = await composio.tools.getRawComposioToolBySlug('GITHUB_GET_REPOS'); console.log(tool.name, tool.description); // Get a tool with schema transformation const customizedTool = await composio.tools.getRawComposioToolBySlug( 'SLACK_SEND_MESSAGE', { modifySchema: ({ toolSlug, toolkitSlug, schema }) => { return { ...schema, description: `Enhanced ${schema.description} with custom modifications`, customMetadata: { lastModified: new Date().toISOString(), toolkit: toolkitSlug } }; } } ); // Get a custom tool (will check custom tools first) const customTool = await composio.tools.getRawComposioToolBySlug('MY_CUSTOM_TOOL'); // Access tool properties const githubTool = await composio.tools.getRawComposioToolBySlug('GITHUB_CREATE_ISSUE'); console.log({ slug: githubTool.slug, name: githubTool.name, toolkit: githubTool.toolkit?.name, version: githubTool.version, availableVersions: githubTool.availableVersions, inputParameters: githubTool.inputParameters }); ```
getRawComposioToolBySlug
('GITHUB_GET_OCTOCAT');
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
(var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON
.JSON.stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string (+1 overload)
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
@paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer An array of strings and numbers that acts as an approved list for selecting the object properties that will be stringified.@paramspace Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.@throws{TypeError} If a circular reference or a BigInt value is found.
stringify
(
const tool: {
    slug: string;
    name: string;
    description?: string | undefined;
    inputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    outputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    ... 6 more ...;
    isNoAuth?: boolean | undefined;
}
tool
, null, 2));

Executing tools

Tool execution remains largely unchanged, with user_id now explicitly required.

For agentic frameworks, the tool object returned from tools.get is now the respective framework's native tool object. Tool call execution is handled by the agentic framework itself.

For non-agentic frameworks, Composio provides a helper function to execute tool calls.

from composio import Composio
from openai import OpenAI

openai_client = OpenAI()
composio = Composio()

tools = composio.tools.get(user_id="user@acme.com", tools=["GITHUB_GET_THE_ZEN_OF_GITHUB"])
response = openai_client.chat.completions.create(
    model="gpt-4.1",
    messages=[{"role": "user", "content": "gimme some zen."}],
    tools=tools,
)

result = composio.provider.handle_tool_calls(user_id="user@acme.com", response=response)
print(result)
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
import { class AnthropicProvider
Anthropic Provider implementation for Composio
AnthropicProvider
} from '@composio/anthropic';
import class Anthropic
API Client for interfacing with the Anthropic API.
Anthropic
from '@anthropic-ai/sdk';
const const anthropic: Anthropicanthropic = new new Anthropic({ baseURL, apiKey, authToken, ...opts }?: ClientOptions): Anthropic
API Client for interfacing with the Anthropic API.
@paramopts.apiKey@paramopts.authToken@paramopts.baseURL ://api.anthropic.com] - Override the default base URL for the API.@paramopts.timeout minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.@paramopts.fetchOptions - Additional `RequestInit` options to be passed to `fetch` calls.@paramopts.fetch - Specify a custom `fetch` function implementation.@paramopts.maxRetries - The maximum number of times the client will retry a request.@paramopts.defaultHeaders - Default headers to include with every request to the API.@paramopts.defaultQuery - Default query parameters to include with every request to the API.@paramopts.dangerouslyAllowBrowser - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
Anthropic
();
const const composio: Composio<AnthropicProvider>composio = new new Composio<AnthropicProvider>(config?: ComposioConfig<AnthropicProvider> | undefined): Composio<AnthropicProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
({
provider?: AnthropicProvider | undefined
The tool provider to use for this Composio instance.
@examplenew OpenAIProvider()
provider
: new
new AnthropicProvider(options?: {
    cacheTools?: boolean;
}): AnthropicProvider
Creates a new instance of the AnthropicProvider.
@paramoptions - Configuration options for the provider@paramoptions.cacheTools - Whether to cache tools using Anthropic's ephemeral cache@example```typescript // Initialize with default settings (no caching) const provider = new AnthropicProvider(); // Initialize with tool caching enabled const providerWithCaching = new AnthropicProvider({ cacheTools: true }); // Use with Composio const composio = new Composio({ apiKey: 'your-api-key', provider: new AnthropicProvider({ cacheTools: true }) }); ```
AnthropicProvider
(),
}); const const userId: "user@example.com"userId = 'user@example.com'; const const tools: AnthropicToolCollectiontools = await const composio: Composio<AnthropicProvider>composio.Composio<AnthropicProvider>.tools: Tools<unknown, unknown, AnthropicProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, AnthropicProvider>.get<AnthropicProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<AnthropicToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
(const userId: "user@example.com"userId, {
toolkits: [string]toolkits: ['GMAIL'], }); const
const msg: Anthropic.Messages.Message & {
    _request_id?: string | null;
}
msg
= await const anthropic: Anthropicanthropic.Anthropic.messages: Anthropic.Messagesmessages.Messages.create(body: Anthropic.Messages.MessageCreateParamsNonStreaming, options?: RequestOptions): APIPromise<Anthropic.Messages.Message> (+2 overloads)
Send a structured list of input messages with text and/or image content, and the model will generate the next message in the conversation. The Messages API can be used for either single queries or stateless multi-turn conversations. Learn more about the Messages API in our [user guide](https://docs.claude.com/en/docs/initial-setup)
@example```ts const message = await client.messages.create({ max_tokens: 1024, messages: [{ content: 'Hello, world', role: 'user' }], model: 'claude-sonnet-4-5-20250929', }); ```
create
({
MessageCreateParamsBase.model: Anthropic.Messages.Model
The model that will complete your prompt.\n\nSee [models](https://docs.anthropic.com/en/docs/models-overview) for additional details and options.
model
: 'claude-3-7-sonnet-latest',
MessageCreateParamsBase.tools?: Anthropic.Messages.ToolUnion[] | undefined
Definitions of tools that the model may use. If you include `tools` in your API request, the model may return `tool_use` content blocks that represent the model's use of those tools. You can then run those tools using the tool input generated by the model and then optionally return results back to the model using `tool_result` content blocks. There are two types of tools: **client tools** and **server tools**. The behavior described below applies to client tools. For [server tools](https://docs.claude.com/en/docs/agents-and-tools/tool-use/overview#server-tools), see their individual documentation as each has its own behavior (e.g., the [web search tool](https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-search-tool)). Each tool definition includes: - `name`: Name of the tool. - `description`: Optional, but strongly-recommended description of the tool. - `input_schema`: [JSON schema](https://json-schema.org/draft/2020-12) for the tool `input` shape that the model will produce in `tool_use` output content blocks. For example, if you defined `tools` as: ```json [ { "name": "get_stock_price", "description": "Get the current stock price for a given ticker symbol.", "input_schema": { "type": "object", "properties": { "ticker": { "type": "string", "description": "The stock ticker symbol, e.g. AAPL for Apple Inc." } }, "required": ["ticker"] } } ] ``` And then asked the model "What's the S&P 500 at today?", the model might produce `tool_use` content blocks in the response like this: ```json [ { "type": "tool_use", "id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV", "name": "get_stock_price", "input": { "ticker": "^GSPC" } } ] ``` You might then run your `get_stock_price` tool with `{"ticker": "^GSPC"}` as an input, and return the following back to the model in a subsequent `user` message: ```json [ { "type": "tool_result", "tool_use_id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV", "content": "259.75 USD" } ] ``` Tools can be used for workflows that include running client-side tools and functions, or more generally whenever you want the model to produce a particular JSON structure of output. See our [guide](https://docs.claude.com/en/docs/tool-use) for more details.
tools
: const tools: AnthropicToolCollectiontools,
MessageCreateParamsBase.messages: Anthropic.Messages.MessageParam[]
Input messages. Our models are trained to operate on alternating `user` and `assistant` conversational turns. When creating a new `Message`, you specify the prior conversational turns with the `messages` parameter, and the model then generates the next `Message` in the conversation. Consecutive `user` or `assistant` turns in your request will be combined into a single turn. Each input message must be an object with a `role` and `content`. You can specify a single `user`-role message, or you can include multiple `user` and `assistant` messages. If the final message uses the `assistant` role, the response content will continue immediately from the content in that message. This can be used to constrain part of the model's response. Example with a single `user` message: ```json [{ "role": "user", "content": "Hello, Claude" }] ``` Example with multiple conversational turns: ```json [ { "role": "user", "content": "Hello there." }, { "role": "assistant", "content": "Hi, I'm Claude. How can I help you?" }, { "role": "user", "content": "Can you explain LLMs in plain English?" } ] ``` Example with a partially-filled response from Claude: ```json [ { "role": "user", "content": "What's the Greek name for Sun? (A) Sol (B) Helios (C) Sun" }, { "role": "assistant", "content": "The best answer is (" } ] ``` Each input message `content` may be either a single `string` or an array of content blocks, where each block has a specific `type`. Using a `string` for `content` is shorthand for an array of one content block of type `"text"`. The following input messages are equivalent: ```json { "role": "user", "content": "Hello, Claude" } ``` ```json { "role": "user", "content": [{ "type": "text", "text": "Hello, Claude" }] } ``` See [input examples](https://docs.claude.com/en/api/messages-examples). Note that if you want to include a [system prompt](https://docs.claude.com/en/docs/system-prompts), you can use the top-level `system` parameter — there is no `"system"` role for input messages in the Messages API. There is a limit of 100,000 messages in a single request.
messages
: [
{ MessageParam.role: "user" | "assistant"role: 'user', MessageParam.content: string | Anthropic.Messages.ContentBlockParam[]content: "Say hi to 'soham@composio.dev'", }, ], MessageCreateParamsBase.max_tokens: number
The maximum number of tokens to generate before stopping. Note that our models may stop _before_ reaching this maximum. This parameter only specifies the absolute maximum number of tokens to generate. Different models have different maximum values for this parameter. See [models](https://docs.claude.com/en/docs/models-overview) for details.
max_tokens
: 1024,
}); const const result: Anthropic.Messages.MessageParam[]result = await const composio: Composio<AnthropicProvider>composio.Composio<AnthropicProvider>.provider: AnthropicProvider
The tool provider instance used for wrapping tools in framework-specific formats
provider
.AnthropicProvider.handleToolCalls(userId: string, message: Anthropic.Message, options?: ExecuteToolFnOptions, modifiers?: ExecuteToolModifiers): Promise<Anthropic.Messages.MessageParam[]>
Handles tool calls from Anthropic's message response. This method processes tool calls from an Anthropic message response, extracts the tool use blocks, executes each tool call, and returns the results.
@paramuserId - The user ID for authentication and tracking@parammessage - The message response from Anthropic@paramoptions - Additional options for tool execution@parammodifiers - Modifiers for tool execution@returnsArray of tool execution results as JSON strings@example```typescript // Handle tool calls from an Anthropic message response const anthropic = new Anthropic({ apiKey: 'your-anthropic-api-key' }); const message = await anthropic.messages.create({ model: 'claude-3-opus-20240229', max_tokens: 1024, tools: provider.wrapTools(composioTools), messages: [ { role: 'user', content: 'Search for information about Composio' } ] }); // Process any tool calls in the response const results = await provider.handleToolCalls( 'user123', message, { connectedAccountId: 'conn_xyz456' } ); // Use the results to continue the conversation console.log(results); ```
handleToolCalls
(const userId: "user@example.com"userId,
const msg: Anthropic.Messages.Message & {
    _request_id?: string | null;
}
msg
);
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
('Tool results:', const result: Anthropic.Messages.MessageParam[]result);

For more information on executing tools for different frameworks, see Replacing ToolSets with Providers.

Tool Modifiers (formerly Tool Processors)

Tool processors have been renamed to tool modifiers and now provide an improved developer experience. The implementation is now available in TypeScript too! (previously Python-only).

Python (previous)
from composio_openai import ComposioToolSet, Action

toolset = ComposioToolSet()


def my_schema_processor(schema: dict) -> dict: ...
def my_preprocessor(inputs: dict) -> dict: ...
def my_postprocessor(result: dict) -> dict: ...


# Get tools with the modified schema
processed_tools = toolset.get_tools(
    actions=[Action.GMAIL_SEND_EMAIL],
    processors={
        # Applied BEFORE the LLM sees the schema
        "schema": {Action.SOME_ACTION: my_schema_processor},
        # Applied BEFORE the tool executes
        "pre": {Action.SOME_ACTION: my_preprocessor},
        # Applied AFTER the tool executes, BEFORE the result is returned
        "post": {Action.SOME_ACTION: my_postprocessor},
    },
)
PreviousCurrent
pre processorbeforeExecute modifier
post processorafterExecute modifier
schema processorschema modifier

The modifiers now leverage language-specific features to provide a more natural developer experience.

While tool processors could previously be applied during SDK initialization, tool fetching, and tool execution, we have restructured them as follows:

  • Chat Completion providers: Modifiers are specified and applied during tool execution
  • Agentic frameworks: Modifiers are specified and applied during tool fetching

Schema Modifiers

The following example demonstrates schema modifier usage, applicable across all providers:

from composio import Composio, schema_modifier
from composio.types import Tool

user_id = "your@email.com"

@schema_modifier(tools=["HACKERNEWS_GET_LATEST_POSTS"])
def modify_schema(
    tool: str,
    toolkit: str,
    schema: Tool,
) -> Tool:
    _ = schema.input_parameters["properties"].pop("page", None)
    schema.input_parameters["required"] = ["size"]
    return schema

tools = composio.tools.get(
    user_id=user_id,
    tools=["HACKERNEWS_GET_LATEST_POSTS", "HACKERNEWS_GET_USER"],
    modifiers=[
        modify_schema,
    ]
)
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
import { class OpenAI
API Client for interfacing with the OpenAI API.
OpenAI
} from 'openai';
const const userId: "your@email.com"userId = 'your@email.com'; const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
// Schema modifier to delete the `page` argument from the `HACKERNEWS_GET_LATEST_POSTS` tool const const tools: OpenAiToolCollectiontools = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.get<OpenAIProvider>(userId: string, filters: ToolListParams, options?: ToolOptions | undefined): Promise<OpenAiToolCollection> (+1 overload)
Get a list of tools from Composio based on filters. This method fetches the tools from the Composio API and wraps them using the provider.
@paramuserId - The user id to get the tools for@paramfilters - The filters to apply when fetching tools@paramoptions - Optional provider options including modifiers@returnsThe wrapped tools collection@example```typescript // Get tools from the GitHub toolkit const tools = await composio.tools.get('default', { toolkits: ['github'], limit: 10 }); // Get tools with search const searchTools = await composio.tools.get('default', { search: 'user', limit: 10 }); // Get a specific tool by slug const hackerNewsUserTool = await composio.tools.get('default', 'HACKERNEWS_GET_USER'); // Get a tool with schema modifications const tool = await composio.tools.get('default', 'GITHUB_GET_REPOS', { modifySchema: (toolSlug, toolkitSlug, schema) => { // Customize the tool schema return {...schema, description: 'Custom description'}; } }); ```
get
(
const userId: "your@email.com"userId, { tools: string[]tools: ['HACKERNEWS_GET_LATEST_POSTS', 'HACKERNEWS_GET_USER'], }, { modifySchema?: TransformToolSchemaModifier | undefined
Function to transform tool schemas before they're exposed to consumers. This allows customizing input/output parameters, descriptions, and other metadata.
modifySchema
: ({ toolSlug: stringtoolSlug, toolkitSlug: stringtoolkitSlug,
schema: {
    slug: string;
    name: string;
    description?: string | undefined;
    inputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    outputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    ... 6 more ...;
    isNoAuth?: boolean | undefined;
}
schema
}) => {
if (toolSlug: stringtoolSlug === 'HACKERNEWS_GET_LATEST_POSTS') { const {
const inputParameters: {
    type: "object";
    properties: Record<string, any>;
    description?: string | undefined;
    anyOf?: any[] | undefined;
    oneOf?: any[] | undefined;
    allOf?: any[] | undefined;
    not?: any;
    required?: string[] | undefined;
    title?: string | undefined;
    default?: any;
    nullable?: boolean | undefined;
    additionalProperties?: boolean | undefined;
} | undefined
inputParameters
} =
schema: {
    slug: string;
    name: string;
    description?: string | undefined;
    inputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    outputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    ... 6 more ...;
    isNoAuth?: boolean | undefined;
}
schema
;
if (
const inputParameters: {
    type: "object";
    properties: Record<string, any>;
    description?: string | undefined;
    anyOf?: any[] | undefined;
    oneOf?: any[] | undefined;
    allOf?: any[] | undefined;
    not?: any;
    required?: string[] | undefined;
    title?: string | undefined;
    default?: any;
    nullable?: boolean | undefined;
    additionalProperties?: boolean | undefined;
} | undefined
inputParameters
?.properties: Record<string, any> | undefinedproperties) {
delete
const inputParameters: {
    type: "object";
    properties: Record<string, any>;
    description?: string | undefined;
    anyOf?: any[] | undefined;
    oneOf?: any[] | undefined;
    allOf?: any[] | undefined;
    not?: any;
    required?: string[] | undefined;
    title?: string | undefined;
    default?: any;
    nullable?: boolean | undefined;
    additionalProperties?: boolean | undefined;
}
inputParameters
.properties: Record<string, any>properties['page'];
}
const inputParameters: {
    type: "object";
    properties: Record<string, any>;
    description?: string | undefined;
    anyOf?: any[] | undefined;
    oneOf?: any[] | undefined;
    allOf?: any[] | undefined;
    not?: any;
    required?: string[] | undefined;
    title?: string | undefined;
    default?: any;
    nullable?: boolean | undefined;
    additionalProperties?: boolean | undefined;
} | undefined
inputParameters
.required?: string[] | undefinedrequired = ['size'];
} return
schema: {
    slug: string;
    name: string;
    description?: string | undefined;
    inputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    outputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    ... 6 more ...;
    isNoAuth?: boolean | undefined;
}
schema
;
}, } ); 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
(var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON
.JSON.stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string (+1 overload)
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
@paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer An array of strings and numbers that acts as an approved list for selecting the object properties that will be stringified.@paramspace Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.@throws{TypeError} If a circular reference or a BigInt value is found.
stringify
(const tools: OpenAiToolCollectiontools, null, 2));

Before Modifiers

The following example shows creating and using a before modifier for a Chat Completion provider. For agentic frameworks, view the complete before modifier documentation:

@before_execute(tools=["HACKERNEWS_GET_LATEST_POSTS"])
def before_execute_modifier(
    tool: str,
    toolkit: str,
    params: ToolExecuteParams,
) -> ToolExecuteParams:
    params["arguments"]["size"] = 1
    return params


# Get tools
tools = composio.tools.get(user_id=user_id, slug="HACKERNEWS_GET_LATEST_POSTS")
const const result_1: anyresult_1 = await composio.tools.execute(
  'HACKERNEWS_GET_LATEST_POSTS',
  {
    userId: anyuserId,
    arguments: anyarguments: var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON
.JSON.parse(text: string, reviver?: (this: any, key: string, value: any) => any): any
Converts a JavaScript Object Notation (JSON) string into an object.
@paramtext A valid JSON string.@paramreviver A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is.@throws{SyntaxError} If `text` is not valid JSON.
parse
(toolArgs),
}, {
beforeExecute: ({ toolSlug, toolkitSlug, params }: {
    toolSlug: any;
    toolkitSlug: any;
    params: any;
}) => any
beforeExecute
: ({ toolSlug: anytoolSlug, toolkitSlug: anytoolkitSlug, params: anyparams }) => {
if (toolSlug: anytoolSlug === 'HACKERNEWS_GET_LATEST_POSTS') { params: anyparams.arguments.size = 1; } 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
(params: anyparams);
return params: anyparams; }, } );

After Modifiers

The following example shows creating and using an after modifier for a Chat Completion provider. For agentic frameworks, view the complete after modifier documentation:

@after_execute(tools=["HACKERNEWS_GET_USER"])
def after_execute_modifier(
    tool: str,
    toolkit: str,
    response: ToolExecutionResponse,
) -> ToolExecutionResponse:
    return {
        **response,
        "data": {
            "karma": response["data"]["karma"],
        },
    }

tools = composio.tools.get(user_id=user_id, slug="HACKERNEWS_GET_USER")
const const result_2: anyresult_2 = await composio.tools.execute(
  'HACKERNEWS_GET_USER',
  {
    userId: anyuserId,
    arguments: anyarguments: var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON
.JSON.parse(text: string, reviver?: (this: any, key: string, value: any) => any): any
Converts a JavaScript Object Notation (JSON) string into an object.
@paramtext A valid JSON string.@paramreviver A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is.@throws{SyntaxError} If `text` is not valid JSON.
parse
(toolArgs),
}, {
afterExecute: ({ toolSlug, toolkitSlug, result }: {
    toolSlug: any;
    toolkitSlug: any;
    result: any;
}) => any
afterExecute
: ({ toolSlug: anytoolSlug, toolkitSlug: anytoolkitSlug, result: anyresult }) => {
if (toolSlug: anytoolSlug === 'HACKERNEWS_GET_USER') { const { const data: anydata } = result: anyresult; const { const karma: numberkarma } = const data: anydata.response_data as { karma: numberkarma: number }; return { ...result: anyresult,
data: {
    karma: number;
}
data
: { karma: numberkarma },
}; } return result: anyresult; }, } );

Custom Tools

The SDK continues to support custom tools. Creating tools from your methods remains possible. We recommend reviewing the detailed custom tools documentation for more information.

Due to changes in the SDK architecture, creating custom tools that use Composio's managed authentication has been modified. In the previous SDK, you could create a custom tool as follows:

# Python Example using execute_request
from composio import action, ComposioToolSet
import typing as t

toolset = ComposioToolSet()

@action(toolname="github") # Associate with GitHub app for auth
def get_github_repo_topics(
    owner: t.Annotated[str, "Repository owner username"],
    repo: t.Annotated[str, "Repository name"],
    execute_request: t.Callable # Injected by Composio
) -> dict:
    """Gets the topics associated with a specific GitHub repository."""
    response_data = execute_request(
        endpoint=f"/repos/{owner}/{repo}/topics", # API path relative to base URL
        method="GET"
    )
    if isinstance(response_data, dict):
        return {"topics": response_data.get("names", [])}
import { import OpenAIToolSetOpenAIToolSet, type import ActionExecutionResDtoActionExecutionResDto } from "composio-core";
import { import zz } from "zod";

const const toolset: anytoolset = new import OpenAIToolSetOpenAIToolSet();

await const toolset: anytoolset.createAction({
    actionName: stringactionName: "get_github_repo_topics",
    toolName: stringtoolName: "github",
    description: stringdescription: "Gets the topics associated with a specific GitHub repository.",
    
inputParams: z.ZodObject<{
    owner: z.ZodString;
    repo: z.ZodString;
}, z.core.$strip>
inputParams
: import zz.
function object<{
    owner: z.ZodString;
    repo: z.ZodString;
}>(shape?: {
    owner: z.ZodString;
    repo: z.ZodString;
} | undefined, params?: string | {
    error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
    message?: string | undefined | undefined;
} | undefined): z.ZodObject<{
    owner: z.ZodString;
    repo: z.ZodString;
}, z.core.$strip>
object
({
owner: z.ZodStringowner: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string().ZodType<any, any, $ZodStringInternals<string>>.describe(description: string): z.ZodString
Returns a new instance that has been registered in `z.globalRegistry` with the specified description
describe
("Repository owner username"),
repo: z.ZodStringrepo: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string().ZodType<any, any, $ZodStringInternals<string>>.describe(description: string): z.ZodString
Returns a new instance that has been registered in `z.globalRegistry` with the specified description
describe
("Repository name"),
}), callback: (inputParams: any, _authCredentials: any, executeRequest: any) => Promise<ActionExecutionResDto>callback: async (inputParams: anyinputParams, _authCredentials: any_authCredentials, executeRequest: anyexecuteRequest): interface Promise<T>
Represents the completion of an asynchronous operation
Promise
<import ActionExecutionResDtoActionExecutionResDto> => {
const { const owner: stringowner, const repo: stringrepo } = inputParams: anyinputParams as { owner: stringowner: string, repo: stringrepo: string }; const const response: anyresponse = await executeRequest: anyexecuteRequest({ endpoint: stringendpoint: `/repos/${const owner: stringowner}/${const repo: stringrepo}/topics`, method: stringmethod: "GET", parameters: never[]parameters: [], }); const const topics: anytopics = (const response: anyresponse as any)?.names ?? []; return { successful: booleansuccessful: true,
data: {
    topics: any;
}
data
: { topics: anytopics: const topics: anytopics } };
} });

The execute tool request method handles injection of the appropriate base URL and authentication credentials for the tool:

from pydantic import BaseModel, Field
from composio import Composio
from composio.core.models.custom_tools import ExecuteRequestFn


composio = Composio()

class GetIssueInfoInput(BaseModel):
    issue_number: int = Field(
        ...,
        description="The number of the issue to get information about",
    )

# function name will be used as slug
@composio.tools.custom_tool(toolkit="github")
def get_issue_info(
    request: GetIssueInfoInput,
    execute_request: ExecuteRequestFn,
    auth_credentials: dict,
) -> dict:
    """Get information about a GitHub issue."""
    response = execute_request(
        endpoint=f"/repos/composiohq/composio/issues/{request.issue_number}",
        method="GET",
        parameters=[
            {
                "name": "Accept",
                "value": "application/vnd.github.v3+json",
                "type": "header",
            },
            {
                "name": "Authorization",
                "value": f"Bearer {auth_credentials['access_token']}",
                "type": "header",
            },
        ],
    )
    return {"data": response.data}
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from "@composio/core";
import import zz from "zod"; const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
const
const tool: {
    slug: string;
    name: string;
    description?: string | undefined;
    inputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    outputParameters?: {
        type: "object";
        properties: Record<string, any>;
        description?: string | undefined;
        anyOf?: any[] | undefined;
        oneOf?: any[] | undefined;
        allOf?: any[] | undefined;
        not?: any;
        required?: string[] | undefined;
        title?: string | undefined;
        default?: any;
        nullable?: boolean | undefined;
        additionalProperties?: boolean | undefined;
    } | undefined;
    ... 6 more ...;
    isNoAuth?: boolean | undefined;
}
tool
= await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>
List, retrieve, and execute tools
tools
.Tools<unknown, unknown, OpenAIProvider>.createCustomTool<CustomToolInputParameter>(body: CustomToolOptions<CustomToolInputParameter>): Promise<Tool>
Creates a custom tool that can be used within the Composio SDK. Custom tools allow you to extend the functionality of Composio with your own implementations while keeping a consistent interface for both built-in and custom tools.
@parambody - The configuration for the custom tool@returnsThe created custom tool@example```typescript // creating a custom tool with a toolkit await composio.tools.createCustomTool({ name: 'My Custom Tool', description: 'A custom tool that does something specific', slug: 'MY_CUSTOM_TOOL', userId: 'default', connectedAccountId: '123', toolkitSlug: 'github', inputParameters: z.object({ param1: z.string().describe('First parameter'), }), execute: async (input, connectionConfig, executeToolRequest) => { // Custom logic here return { data: { result: 'Success!' } }; } }); ```@example```typescript // creating a custom tool without a toolkit await composio.tools.createCustomTool({ name: 'My Custom Tool', description: 'A custom tool that does something specific', slug: 'MY_CUSTOM_TOOL', inputParameters: z.object({ param1: z.string().describe('First parameter'), }), execute: async (input) => { // Custom logic here return { data: { result: 'Success!' } }; } });
createCustomTool
({
slug: stringslug: 'GITHUB_STAR_COMPOSIOHQ_REPOSITORY', name: stringname: 'Github star composio repositories', toolkitSlug: stringtoolkitSlug: 'github', description?: string | undefineddescription: 'Star any specificied repo of `composiohq` user', inputParams: CustomToolInputParameterinputParams: import zz.
function object<{
    repository: z.ZodString;
    page: z.ZodOptional<z.ZodNumber>;
    customHeader: z.ZodOptional<z.ZodString>;
}>(shape?: {
    repository: z.ZodString;
    page: z.ZodOptional<z.ZodNumber>;
    customHeader: z.ZodOptional<z.ZodString>;
} | undefined, params?: string | {
    error?: string | z.core.$ZodErrorMap<NonNullable<z.core.$ZodIssueInvalidType<unknown> | z.core.$ZodIssueUnrecognizedKeys>> | undefined;
    message?: string | undefined | undefined;
} | undefined): z.ZodObject<{
    repository: z.ZodString;
    page: z.ZodOptional<z.ZodNumber>;
    customHeader: z.ZodOptional<...>;
}, z.core.$strip>
object
({
repository: z.ZodStringrepository: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string().ZodType<any, any, $ZodStringInternals<string>>.describe(description: string): z.ZodString
Returns a new instance that has been registered in `z.globalRegistry` with the specified description
describe
('The repository to star'),
page: z.ZodOptional<z.ZodNumber>page: import zz.function number(params?: string | z.core.$ZodNumberParams): z.ZodNumbernumber().ZodType<any, any, $ZodNumberInternals<number>>.optional(): z.ZodOptional<z.ZodNumber>optional().ZodType<any, any, $ZodOptionalInternals<ZodNumber>>.describe(description: string): z.ZodOptional<z.ZodNumber>
Returns a new instance that has been registered in `z.globalRegistry` with the specified description
describe
('Pagination page number'),
customHeader: z.ZodOptional<z.ZodString>customHeader: import zz.function string(params?: string | z.core.$ZodStringParams): z.ZodString (+1 overload)string().ZodType<any, any, $ZodStringInternals<string>>.optional(): z.ZodOptional<z.ZodString>optional().ZodType<any, any, $ZodOptionalInternals<ZodString>>.describe(description: string): z.ZodOptional<z.ZodString>
Returns a new instance that has been registered in `z.globalRegistry` with the specified description
describe
('Custom header'),
}), execute: (input: any, connectionConfig: ConnectionData | null, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>) => Promise<ToolExecuteResponse>execute: async (input: anyinput,
connectionConfig: {
    authScheme: "OAUTH1";
    val: objectOutputType<{
        subdomain: ZodOptional<ZodString>;
        "your-domain": ZodOptional<ZodString>;
        region: ZodOptional<ZodString>;
        shop: ZodOptional<ZodString>;
        account_url: ZodOptional<ZodString>;
        COMPANYDOMAIN: ZodOptional<ZodString>;
        extension: ZodOptional<ZodString>;
        form_api_base_url: ZodOptional<ZodString>;
        instanceEndpoint: ZodOptional<ZodString>;
        api_url: ZodOptional<ZodString>;
        borneo_dashboard_url: ZodOptional<ZodString>;
        proxy_username: ZodOptional<ZodString>;
        proxy_password: ZodOptional<ZodString>;
        domain: ZodOptional<ZodString>;
        version: ZodOptional<ZodString>;
        dc: ZodOptional<ZodString>;
        site_name: ZodOptional<ZodString>;
        instanceName: ZodOptional<ZodString>;
        account_id: ZodOptional<ZodString>;
        your_server: ZodOptional<ZodString>;
        server_location: ZodOptional<ZodString>;
        base_url: ZodOptional<ZodString>;
        api_key: ZodOptional<ZodString>;
        generic_api_key: ZodOptional<ZodString>;
        bearer_token: ZodOptional<ZodString>;
        basic_encoded: ZodOptional<ZodString>;
        long_redirect_url: ZodOptional<ZodBoolean>;
        state_prefix: ZodOptional<ZodString>;
        registration_access_token: ZodOptional<ZodString>;
        registration_client_uri: ZodOptional<ZodString>;
        composio_link_redirect_url: ZodOptional<ZodString>;
    } & {
        status: ZodLiteral<"INITIALIZING">;
    }, ZodUnknown, "strip"> | objectOutputType<{
        subdomain: ZodOptional<ZodString>;
        "your-domain": ZodOptional<ZodString>;
        region: ZodOptional<ZodString>;
        shop: ZodOptional<ZodString>;
        account_url: ZodOptional<ZodString>;
        COMPANYDOMAIN: ZodOptional<ZodString>;
        extension: ZodOptional<ZodString>;
        form_api_base_url: ZodOptional<ZodString>;
        instanceEndpoint: ZodOptional<ZodString>;
        api_url: ZodOptional<ZodString>;
        borneo_dashboard_url: ZodOptional<ZodString>;
        proxy_username: ZodOptional<ZodString>;
        proxy_password: ZodOptional<ZodString>;
        domain: ZodOptional<ZodString>;
        version: ZodOptional<ZodString>;
        dc: ZodOptional<ZodString>;
        site_name: ZodOptional<ZodString>;
        instanceName: ZodOptional<ZodString>;
        account_id: ZodOptional<ZodString>;
        your_server: ZodOptional<ZodString>;
        server_location: ZodOptional<ZodString>;
        base_url: ZodOptional<ZodString>;
        api_key: ZodOptional<ZodString>;
        generic_api_key: ZodOptional<ZodString>;
        bearer_token: ZodOptional<ZodString>;
        basic_encoded: ZodOptional<ZodString>;
        long_redirect_url: ZodOptional<ZodBoolean>;
        state_prefix: ZodOptional<ZodString>;
        registration_access_token: ZodOptional<ZodString>;
        registration_client_uri: ZodOptional<ZodString>;
        composio_link_redirect_url: ZodOptional<ZodString>;
    } & {
        status: ZodLiteral<"INITIATED">;
        authUri: ZodString;
        oauth_token: ZodString;
        oauth_token_secret: ZodString;
        redirectUrl: ZodString;
        callbackUrl: ZodOptional<ZodString>;
    }, ZodUnknown, "strip"> | objectOutputType<{
        subdomain: ZodOptional<ZodString>;
        "your-domain": ZodOptional<ZodString>;
        region: ZodOptional<ZodString>;
        shop: ZodOptional<ZodString>;
        account_url: ZodOptional<ZodString>;
        COMPANYDOMAIN: ZodOptional<ZodString>;
        extension: ZodOptional<ZodString>;
        form_api_base_url: ZodOptional<ZodString>;
        instanceEndpoint: ZodOptional<ZodString>;
        api_url: ZodOptional<ZodString>;
        borneo_dashboard_url: ZodOptional<ZodString>;
        proxy_username: ZodOptional<ZodString>;
        proxy_password: ZodOptional<ZodString>;
        domain: ZodOptional<ZodString>;
        version: ZodOptional<ZodString>;
        dc: ZodOptional<ZodString>;
        site_name: ZodOptional<ZodString>;
        instanceName: ZodOptional<ZodString>;
        account_id: ZodOptional<ZodString>;
        your_server: ZodOptional<ZodString>;
        server_location: ZodOptional<ZodString>;
        base_url: ZodOptional<ZodString>;
        api_key: ZodOptional<ZodString>;
        generic_api_key: ZodOptional<ZodString>;
        bearer_token: ZodOptional<ZodString>;
        basic_encoded: ZodOptional<ZodString>;
        long_redirect_url: ZodOptional<ZodBoolean>;
        state_prefix: ZodOptional<ZodString>;
        registration_access_token: ZodOptional<ZodString>;
        registration_client_uri: ZodOptional<ZodString>;
        composio_link_redirect_url: ZodOptional<ZodString>;
    } & {
        status: ZodLiteral<"ACTIVE">;
        oauth_token: ZodString;
        oauth_token_secret: ZodString;
        consumer_key: ZodOptional<ZodString>;
        oauth_verifier: ZodOptional<ZodString>;
        redirectUrl: ZodOptional<ZodString ...
connectionConfig
, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest) => {
const const result: ToolExecuteResponseresult = await executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest({ endpoint: stringendpoint: `/user/starred/composiohq/${input: anyinput.repository}`, method: "PUT" | "GET" | "POST" | "DELETE" | "PATCH"method: 'PUT', body?: unknownbody: {},
parameters?: {
    name: string;
    value: string | number;
    in: "query" | "header";
}[] | undefined
parameters
: [
{ name: stringname: 'page', value: string | numbervalue: input: anyinput.page?.toString() || '1', in: "query" | "header"in: 'query', }, { name: stringname: 'x-custom-header', value: string | numbervalue: input: anyinput.customHeader || 'default-value', in: "query" | "header"in: 'header', }, ], }); return const result: ToolExecuteResponseresult; }, });

For more information, including executing custom tools and defining custom headers and query parameters, refer to the Custom Tools documentation.

Auth configs (formerly integrations)

Integrations are now called auth configs. While the terminology has changed, the underlying concept remains the same.

Auth configs store the configuration required for authentication with a given toolkit, including OAuth developer credentials, configurable base URLs, and scopes.

Auth configs now use nano IDs instead of UUIDs:

Previous (UUID) ExampleCurrent (Nano ID) Example
b7a9c1e2-3f4d-4a6b-8c2e-1d2f3a4b5c6dac_8x9w2l3k5m

We recommend storing auth config nano IDs in your database for connecting users to the appropriate auth configuration.

For most use cases, you will create auth configs through the dashboard, and this process remains unchanged. Read more about creating auth configs and customizing auth configs.

Creating auth configs programmatically in the previous SDK:

from composio_openai import App, ComposioToolSet

toolset = ComposioToolSet()

integration = toolset.create_integration(
    app=App.GITHUB,
    auth_mode="OAUTH2",
    use_composio_oauth_app=True,
    # For use_composio_oauth_app=False, you can provide your own OAuth app credentials here
    # auth_config={
    #     "client_id": "123456",
    #     "client_secret": "123456"
    # }

)
print(integration.id)
import { import OpenAIToolSetOpenAIToolSet } from "composio-core";

const const composioToolset: anycomposioToolset = new import OpenAIToolSetOpenAIToolSet();

const const integration: anyintegration = await const composioToolset: anycomposioToolset.integrations.create({
    name: stringname: "gmail_integration",
    appUniqueKey: stringappUniqueKey: "gmail",
    forceNewIntegration: booleanforceNewIntegration: true,
    useComposioAuth: booleanuseComposioAuth: false,
    // For useComposioAuth: false, you can provide your own OAuth app credentials here
    // authScheme: "OAUTH2",
    // authConfig: {
    //     clientId: "123456",
    //     clientSecret: "123456"
    // }
})

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 integration: anyintegration.id)

Creating auth configs programmatically in the current SDK:

from composio import Composio

composio = Composio()

# Use composio managed auth
auth_config = composio.auth_configs.create(
    toolkit="notion",
    options={
        "type": "use_composio_managed_auth",
        # "type": "use_custom_auth",
        # "auth_scheme": "OAUTH2",
        # "credentials": {
        #     "client_id": "1234567890",
        #     "client_secret": "1234567890",
        #     "oauth_redirect_uri": "https://backend.composio.dev/api/v3/toolkits/auth/callback",
        # },
    },
)
print(auth_config)
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
const
const authConfig: {
    toolkit: string;
    authScheme: string;
    id: string;
    isComposioManaged: boolean;
}
authConfig
= await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.authConfigs: AuthConfigs
Manage authentication configurations for toolkits
authConfigs
.AuthConfigs.create(toolkit: string, options?: CreateAuthConfigParams): Promise<CreateAuthConfigResponse>
Create a new auth config
@paramtoolkit - Unique identifier of the toolkit@paramoptions - Options for creating a new auth config@returnsCreated auth config@exampleconst authConfig = await authConfigs.create('my-toolkit', { type: AuthConfigTypes.CUSTOM, name: 'My Custom Auth Config', authScheme: AuthSchemeTypes.API_KEY, credentials: { apiKey: '1234567890', }, });@linkhttps://docs.composio.dev/reference/auth-configs/create-auth-config
create
('LINEAR', {
name?: string | undefinedname: 'Linear', type: "use_composio_managed_auth"type: 'use_composio_managed_auth', // type: "use_custom_auth", // credentials: { // client_id: "1234567890", // client_secret: "1234567890", // oauth_redirect_uri: "https://backend.composio.dev/api/v3/toolkits/auth/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 authConfig: {
    toolkit: string;
    authScheme: string;
    id: string;
    isComposioManaged: boolean;
}
authConfig
);

For using custom authentication credentials, refer to the Programmatic Auth Configs documentation.

The callback URL for creating custom OAuth configs is now https://backend.composio.dev/api/v3/toolkits/auth/callback. The previous URL was https://backend.composio.dev/api/v1/auth-apps/add.

Connected accounts / User IDs

The primary change in connected accounts and user IDs is that user IDs are now a more prominent concept compared to entities in previous versions.

We have simplified the process of connecting a user to a toolkit. Instead of multiple methods and parameters for initiating a connection, both the SDK and API now require only a user_id and auth_config_id to initiate a connection.

This approach is more explicit and works well with the ability for developers to have multiple auth configs for a given toolkit.

Connected accounts now use nano IDs instead of UUIDs:

Previous (UUID) ExampleCurrent (Nano ID) Example
b7a9c1e2-3f4d-4a6b-8c2e-1d2f3a4b5c6dca_8x9w2l3k5m

Previously, you might have initiated a connection like this:

from composio_openai import ComposioToolSet

toolset = ComposioToolSet()
user_id = "your_user_unique_id"
google_integration_id = "0000-0000"

entity = toolset.get_entity(id=user_id)

try:
    print(f"Initiating OAuth connection for entity {entity.id}...")
    connection_request = toolset.initiate_connection(
        integration_id=google_integration_id,
        entity_id=user_id,
        # Optionally add: redirect_url="https://yourapp.com/final-destination"
        # if you want user sent somewhere specific *after* Composio finishes.
    )

    # Check if a redirect URL was provided (expected for OAuth)
    if connection_request.redirectUrl:
        print(f"Received redirect URL: {connection_request.redirectUrl}")
    else:
        print("Error: Expected a redirectUrl for OAuth flow but didn't receive one.")


except Exception as e:
    print(f"Error initiating connection: {e}")
import { import OpenAIToolSetOpenAIToolSet } from "composio-core";

const const toolset: anytoolset = new import OpenAIToolSetOpenAIToolSet();
const const userId: "your_user_unique_id"userId = "your_user_unique_id";
const const googleIntegrationId: "0000-0000"googleIntegrationId = "0000-0000";

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
(`Initiating OAuth connection for entity ${const userId: "your_user_unique_id"userId}...`);
const const connectionRequest: anyconnectionRequest = await const toolset: anytoolset.connectedAccounts.initiate({ integrationId: stringintegrationId: const googleIntegrationId: "0000-0000"googleIntegrationId, entityId: stringentityId: const userId: "your_user_unique_id"userId, // Optionally add: redirectUri: "https://yourapp.com/final-destination" // if you want user sent somewhere specific *after* Composio finishes. }); // Check if a redirect URL was provided (expected for OAuth) if (const connectionRequest: anyconnectionRequest?.redirectUrl) { 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
(`Received redirect URL: ${const connectionRequest: anyconnectionRequest.redirectUrl}`);
// Proceed to Step 2: Redirect the user // Return or pass connectionRequest to the next stage } else { 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.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` 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 code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v24.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
("Error: Expected a redirectUrl for OAuth flow but didn't receive one.");
}

The current process for initiating a connection is as follows:

from composio import Composio

linear_auth_config_id = "ac_1234"
user_id = "user@email.com"
composio = Composio()

# Create a new connected account
connection_request = composio.connected_accounts.initiate(
    user_id=user_id,
    auth_config_id=linear_auth_config_id,
)
print(connection_request.redirect_url)

# Wait for the connection to be established
connected_account = connection_request.wait_for_connection()
print(connected_account)
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from "@composio/core";
const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
const const linearAuthConfigId: "ac_1234"linearAuthConfigId = "ac_1234"; const const userId: "user@email.com"userId = "user@email.com"; // Initiate the OAuth connection request const const connRequest: ConnectionRequestconnRequest = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.connectedAccounts: ConnectedAccounts
Manage authenticated connections
connectedAccounts
.ConnectedAccounts.initiate(userId: string, authConfigId: string, options?: CreateConnectedAccountOptions): Promise<ConnectionRequest>
Compound function to create a new connected account. This function creates a new connected account and returns a connection request. Users can then wait for the connection to be established using the `waitForConnection` method.
@paramuserId - User ID of the connected account@paramauthConfigId - Auth config ID of the connected account@paramoptions - Options for creating a new connected account@returnsConnection request object@example```typescript // For OAuth2 authentication const connectionRequest = await composio.connectedAccounts.initiate( 'user_123', 'auth_config_123', { callbackUrl: 'https://your-app.com/callback', config: AuthScheme.OAuth2({ access_token: 'your_access_token', token_type: 'Bearer' }) } ); // For API Key authentication const connectionRequest = await composio.connectedAccounts.initiate( 'user_123', 'auth_config_123', { config: AuthScheme.ApiKey({ api_key: 'your_api_key' }) } ); // For Basic authentication const connectionRequest = await composio.connectedAccounts.initiate( 'user_123', 'auth_config_123', { config: AuthScheme.Basic({ username: 'your_username', password: 'your_password' }) } ); ```@linkhttps://docs.composio.dev/reference/connected-accounts/create-connected-account
initiate
(const userId: "user@email.com"userId, const linearAuthConfigId: "ac_1234"linearAuthConfigId);
const { const redirectUrl: string | null | undefinedredirectUrl, const id: stringid } = const connRequest: ConnectionRequestconnRequest; 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 redirectUrl: string | null | undefinedredirectUrl);
// Wait for the connection to be established await const connRequest: ConnectionRequestconnRequest.ConnectionRequest.waitForConnection: (timeout?: number) => Promise<ConnectedAccountRetrieveResponse>waitForConnection(); // If you only have the connection request ID, you can also wait using: await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.connectedAccounts: ConnectedAccounts
Manage authenticated connections
connectedAccounts
.ConnectedAccounts.waitForConnection(connectedAccountId: string, timeout?: number): Promise<ConnectedAccountRetrieveResponse>
Waits for a connection request to complete and become active. This method continuously polls the Composio API to check the status of a connection until it either becomes active, enters a terminal error state, or times out.
@paramconnectedAccountId - The ID of the connected account to wait for@paramtimeout - Maximum time to wait in milliseconds (default: 60 seconds)@returnsThe finalized connected account data@throws{ComposioConnectedAccountNotFoundError} If the connected account cannot be found@throws{ConnectionRequestFailedError} If the connection enters a failed, expired, or deleted state@throws{ConnectionRequestTimeoutError} If the connection does not complete within the timeout period@example```typescript // Wait for a connection to complete with default timeout const connectedAccount = await composio.connectedAccounts.waitForConnection('conn_123abc'); // Wait with a custom timeout of 2 minutes const connectedAccount = await composio.connectedAccounts.waitForConnection('conn_123abc', 120000); ```
waitForConnection
(const id: stringid);

Triggers

Composio continues to support listening to application events using triggers through WebSockets and webhooks.

Creating triggers

The process for creating triggers and specifying their configuration has been redesigned for improved clarity and intuitiveness.

Some triggers require configuration, such as repository names for GitHub triggers or channel names for Slack triggers. The process usually follows the pattern of fetching the trigger type and then creating the trigger with the appropriate configuration.

from composio import Composio

composio = Composio()

user_id = "user@example.com"
trigger_config = composio.triggers.get_type("GITHUB_COMMIT_EVENT")
print(trigger_config.config)
### Trigger Config
# {
#     "properties": {
#         "owner": {
#             "description": "Owner of the repository",
#             "title": "Owner",
#             "type": "string"
#         },
#         "repo": {
#             "description": "Repository name",
#             "title": "Repo",
#             "type": "string"
#         }
#     },
#     "required": ["owner", "repo"],
#     "title": "WebhookConfigSchema",
#     "type": "object"

trigger = composio.triggers.create(
    slug="GITHUB_COMMIT_EVENT",
    user_id=user_id,
    trigger_config={"repo": "composiohq", "owner": "composio"},
)
print(trigger)


# Managing triggers

composio.triggers.enable(id="ti_abcd123")
import { class Composio<TProvider extends BaseComposioProvider<unknown, unknown, unknown> = OpenAIProvider>
This is the core class for Composio. It is used to initialize the Composio SDK and provide a global configuration.
Composio
} from '@composio/core';
const const composio: Composio<OpenAIProvider>composio = new new Composio<OpenAIProvider>(config?: ComposioConfig<OpenAIProvider> | undefined): Composio<OpenAIProvider>
Creates a new instance of the Composio SDK. The constructor initializes the SDK with the provided configuration options, sets up the API client, and initializes all core models (tools, toolkits, etc.).
@paramconfig - Configuration options for the Composio SDK@paramconfig.apiKey - The API key for authenticating with the Composio API@paramconfig.baseURL - The base URL for the Composio API (defaults to production URL)@paramconfig.allowTracking - Whether to allow anonymous usage analytics@paramconfig.provider - The provider to use for this Composio instance (defaults to OpenAIProvider)@example```typescript // Initialize with default configuration const composio = new Composio(); // Initialize with custom API key and base URL const composio = new Composio({ apiKey: 'your-api-key', baseURL: 'https://api.composio.dev' }); // Initialize with custom provider const composio = new Composio({ apiKey: 'your-api-key', provider: new CustomProvider() }); ```
Composio
();
const const userId: "user@acme.com"userId = 'user@acme.com'; // Fetch the trigger details const
const triggerType: {
    slug: string;
    name: string;
    description: string;
    toolkit: {
        slug: string;
        name: string;
        logo: string;
    };
    payload: Record<string, unknown>;
    config: Record<string, unknown>;
    version?: string | undefined;
    instructions?: string | undefined;
}
triggerType
= await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.triggers: Triggers<OpenAIProvider>
Manage webhook triggers and event subscriptions
triggers
.Triggers<OpenAIProvider>.getType(slug: string): Promise<TriggersTypeRetrieveResponse>
Retrieve a trigger type by its slug for the provided version of the app Use the global toolkit versions param when initializing composio to pass a toolkitversion
@paramslug - The slug of the trigger type@returnsThe trigger type object
getType
('GITHUB_COMMIT_EVENT');
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
(var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON
.JSON.stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string (+1 overload)
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
@paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer An array of strings and numbers that acts as an approved list for selecting the object properties that will be stringified.@paramspace Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.@throws{TypeError} If a circular reference or a BigInt value is found.
stringify
(
const triggerType: {
    slug: string;
    name: string;
    description: string;
    toolkit: {
        slug: string;
        name: string;
        logo: string;
    };
    payload: Record<string, unknown>;
    config: Record<string, unknown>;
    version?: string | undefined;
    instructions?: string | undefined;
}
triggerType
.config: Record<string, unknown>config, null, 2));
/*--- Trigger config --- { "properties": { "owner": { "description": "Owner of the repository", "title": "Owner", "type": "string" }, "repo": { "description": "Repository name", "title": "Repo", "type": "string" } }, "required": ["owner", "repo"], "title": "WebhookConfigSchema", "type": "object" } */ const
const createResponse: {
    triggerId: string;
}
createResponse
= await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.triggers: Triggers<OpenAIProvider>
Manage webhook triggers and event subscriptions
triggers
.Triggers<OpenAIProvider>.create(userId: string, slug: string, body?: TriggerInstanceUpsertParams): Promise<TriggerInstanceUpsertResponse>
Create a new trigger instance for a user If the connected account id is not provided, the first connected account for the user and toolkit will be used
@paramuserId - The user id of the trigger instance@paramslug - The slug of the trigger instance@parambody - The parameters to create the trigger instance@returnsThe created trigger instance
create
(const userId: "user@acme.com"userId, 'GITHUB_COMMIT_EVENT', {
triggerConfig?: Record<string, unknown> | undefinedtriggerConfig: { owner: stringowner: 'composiohq', repo: stringrepo: 'composio', }, }); 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 createResponse: {
    triggerId: string;
}
createResponse
);

Enabling/Disabling triggers

You can enable or disable triggers through either the SDK or the dashboard. The dashboard process remains unchanged.

Managing triggers with the SDK:

# Disable a trigger instance
disabled_instance = composio.triggers.disable(trigger_id="ti_abcd123")
print(disabled_instance)
await composio.triggers.disable("ti_abcd123");

If needed, the trigger can be enabled again.

# Enable a trigger instance
enabled_instance = composio.triggers.enable(trigger_id="ti_abcd123")
print(enabled_instance)
await composio.triggers.enable("ti_abcd123");

Listening to triggers

We recommend listening to triggers through webhooks. The following are example routes for Next.js and FastAPI.

For development, you can also listen to triggers through the SDK.

app/route.py
from fastapi import FastAPI, Request, HTTPException
from typing import Dict, Any
import uvicorn
import json
import hmac
import hashlib
import base64
import os

def verify_webhook_signature(request: Request, body: bytes) -> bool:
    """Verify Composio webhook signature"""
    webhook_signature = request.headers.get("webhook-signature")
    webhook_id = request.headers.get("webhook-id")
    webhook_timestamp = request.headers.get("webhook-timestamp")
    webhook_secret = os.getenv("COMPOSIO_WEBHOOK_SECRET")

    if not all([webhook_signature, webhook_id, webhook_timestamp, webhook_secret]):
        raise HTTPException(status_code=400, detail="Missing required webhook headers or secret")

    if not webhook_signature.startswith("v1,"):
        raise HTTPException(status_code=401, detail="Invalid signature format")

    received = webhook_signature[3:]
    signing_string = f"{webhook_id}.{webhook_timestamp}.{body.decode()}"
    expected = base64.b64encode(
        hmac.new(webhook_secret.encode(), signing_string.encode(), hashlib.sha256).digest()
    ).decode()

    if not hmac.compare_digest(received, expected):
        raise HTTPException(status_code=401, detail="Invalid webhook signature")

    return True

@app.post("/webhook")
async def webhook_handler(request: Request):
    payload = await request.json()

    trigger_type = payload.get("type")
    event_data = payload.get("data", {})

    if trigger_type == "github_star_added_event":
        repo_name = event_data.get("repository_name")
        starred_by = event_data.get("starred_by")
        print(f"Repository {repo_name} starred by {starred_by}")
        # Add your business logic here

    return {"status": "success", "message": "Webhook processed"}
app/api/webhook/route.ts
import type { NextApiRequest, 
type NextApiResponse<Data = any> = ServerResponse<IncomingMessage> & {
    send: Send<Data>;
    json: Send<Data>;
    status: (statusCode: number) => NextApiResponse<Data>;
    redirect(url: string): NextApiResponse<Data>;
    redirect(status: number, url: string): NextApiResponse<Data>;
    setDraftMode: (options: {
        enable: boolean;
    }) => NextApiResponse<Data>;
    setPreviewData: (data: object | string, options?: {
        maxAge?: number;
        path?: string;
    }) => NextApiResponse<Data>;
    clearPreviewData: (options?: {
        path?: string;
    }) => NextApiResponse<Data>;
    revalidate: (urlPath: string, opts?: {
        unstable_onlyGenerated?: boolean;
    }) => Promise<void>;
}
Next `API` route response
NextApiResponse
} from 'next';
import { interface TriggerEvent<TPayload = unknown>
Generic trigger event type that can be used with generated trigger payload types
@templateTPayload - The specific trigger payload type (e.g., GITHUB_COMMIT_EVENT_PAYLOAD)
TriggerEvent
} from '@composio/core';
import module "crypto"
The `node:crypto` module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions. ```js const { createHmac } = await import('node:crypto'); const secret = 'abcdefg'; const hash = createHmac('sha256', secret) .update('I love cupcakes') .digest('hex'); console.log(hash); // Prints: // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/crypto.js)
crypto
from 'crypto';
type
type GitHubStarEventData = {
    repository_name: string;
    repository_url: string;
    starred_by: string;
    starred_at: string;
}
GitHubStarEventData
= {
repository_name: stringrepository_name: string; repository_url: stringrepository_url: string; starred_by: stringstarred_by: string; starred_at: stringstarred_at: string; }; function function verifyWebhookSignature(req: NextApiRequest, body: string): booleanverifyWebhookSignature( req: NextApiRequestreq: NextApiRequest, body: stringbody: string ): boolean { const const signature: string | undefinedsignature = req: NextApiRequestreq.IncomingMessage.headers: IncomingHttpHeaders
The request/response headers object. Key-value pairs of header names and values. Header names are lower-cased. ```js // Prints something like: // // { 'user-agent': 'curl/7.22.0', // host: '127.0.0.1:8000', // accept: '*' } console.log(request.headers); ``` Duplicates in raw headers are handled in the following ways, depending on the header name: * Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`, `max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded. To allow duplicate values of the headers listed above to be joined, use the option `joinDuplicateHeaders` in {@link request } and {@link createServer } . See RFC 9110 Section 5.3 for more information. * `set-cookie` is always an array. Duplicates are added to the array. * For duplicate `cookie` headers, the values are joined together with `; `. * For all other headers, the values are joined together with `, `.
@sincev0.1.5
headers
['webhook-signature'] as string | undefined;
const const msgId: string | undefinedmsgId = req: NextApiRequestreq.IncomingMessage.headers: IncomingHttpHeaders
The request/response headers object. Key-value pairs of header names and values. Header names are lower-cased. ```js // Prints something like: // // { 'user-agent': 'curl/7.22.0', // host: '127.0.0.1:8000', // accept: '*' } console.log(request.headers); ``` Duplicates in raw headers are handled in the following ways, depending on the header name: * Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`, `max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded. To allow duplicate values of the headers listed above to be joined, use the option `joinDuplicateHeaders` in {@link request } and {@link createServer } . See RFC 9110 Section 5.3 for more information. * `set-cookie` is always an array. Duplicates are added to the array. * For duplicate `cookie` headers, the values are joined together with `; `. * For all other headers, the values are joined together with `, `.
@sincev0.1.5
headers
['webhook-id'] as string | undefined;
const const timestamp: string | undefinedtimestamp = req: NextApiRequestreq.IncomingMessage.headers: IncomingHttpHeaders
The request/response headers object. Key-value pairs of header names and values. Header names are lower-cased. ```js // Prints something like: // // { 'user-agent': 'curl/7.22.0', // host: '127.0.0.1:8000', // accept: '*' } console.log(request.headers); ``` Duplicates in raw headers are handled in the following ways, depending on the header name: * Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`, `max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded. To allow duplicate values of the headers listed above to be joined, use the option `joinDuplicateHeaders` in {@link request } and {@link createServer } . See RFC 9110 Section 5.3 for more information. * `set-cookie` is always an array. Duplicates are added to the array. * For duplicate `cookie` headers, the values are joined together with `; `. * For all other headers, the values are joined together with `, `.
@sincev0.1.5
headers
['webhook-timestamp'] as string | undefined;
const const secret: string | undefinedsecret = var process: NodeJS.Processprocess.NodeJS.Process.env: NodeJS.ProcessEnv
The `process.env` property returns an object containing the user environment. See [`environ(7)`](http://man7.org/linux/man-pages/man7/environ.7.html). An example of this object looks like: ```js { TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'maciej', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/maciej', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/maciej', LOGNAME: 'maciej', _: '/usr/local/bin/node' } ``` It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other `Worker` threads. In other words, the following example would not work: ```bash node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo ``` While the following will: ```js import { env } from 'node:process'; env.foo = 'bar'; console.log(env.foo); ``` Assigning a property on `process.env` will implicitly convert the value to a string. **This behavior is deprecated.** Future versions of Node.js may throw an error when the value is not a string, number, or boolean. ```js import { env } from 'node:process'; env.test = null; console.log(env.test); // => 'null' env.test = undefined; console.log(env.test); // => 'undefined' ``` Use `delete` to delete a property from `process.env`. ```js import { env } from 'node:process'; env.TEST = 1; delete env.TEST; console.log(env.TEST); // => undefined ``` On Windows operating systems, environment variables are case-insensitive. ```js import { env } from 'node:process'; env.TEST = 1; console.log(env.test); // => 1 ``` Unless explicitly specified when creating a `Worker` instance, each `Worker` thread has its own copy of `process.env`, based on its parent thread's `process.env`, or whatever was specified as the `env` option to the `Worker` constructor. Changes to `process.env` will not be visible across `Worker` threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of `process.env` on a `Worker` instance operates in a case-sensitive manner unlike the main thread.
@sincev0.1.27
env
.string | undefinedCOMPOSIO_WEBHOOK_SECRET;
if (!const signature: string | undefinedsignature || !const msgId: string | undefinedmsgId || !const timestamp: string | undefinedtimestamp || !const secret: string | undefinedsecret) { throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('Missing required webhook headers or secret');
} if (!const signature: stringsignature.String.startsWith(searchString: string, position?: number): boolean
Returns true if the sequence of elements of searchString converted to a String is the same as the corresponding elements of this object (converted to a String) starting at position. Otherwise returns false.
startsWith
('v1,')) {
throw new
var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error
('Invalid signature format');
} const const received: stringreceived = const signature: stringsignature.String.slice(start?: number, end?: number): string
Returns a section of a string.
@paramstart The index to the beginning of the specified portion of stringObj.@paramend The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end. If this value is not specified, the substring continues to the end of stringObj.
slice
(3);
const const signingString: stringsigningString = `${const msgId: stringmsgId}.${const timestamp: stringtimestamp}.${body: stringbody}`; const const expected: stringexpected = module "crypto"
The `node:crypto` module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions. ```js const { createHmac } = await import('node:crypto'); const secret = 'abcdefg'; const hash = createHmac('sha256', secret) .update('I love cupcakes') .digest('hex'); console.log(hash); // Prints: // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/crypto.js)
crypto
.function createHmac(algorithm: string, key: crypto.BinaryLike | crypto.KeyObject, options?: Stream.TransformOptions): crypto.Hmac
Creates and returns an `Hmac` object that uses the given `algorithm` and `key`. Optional `options` argument controls stream behavior. The `algorithm` is dependent on the available algorithms supported by the version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc. On recent releases of OpenSSL, `openssl list -digest-algorithms` will display the available digest algorithms. The `key` is the HMAC key used to generate the cryptographic HMAC hash. If it is a `KeyObject`, its type must be `secret`. If it is a string, please consider `caveats when using strings as inputs to cryptographic APIs`. If it was obtained from a cryptographically secure source of entropy, such as {@link randomBytes } or {@link generateKey } , its length should not exceed the block size of `algorithm` (e.g., 512 bits for SHA-256). Example: generating the sha256 HMAC of a file ```js import { createReadStream, } from 'node:fs'; import { argv } from 'node:process'; const { createHmac, } = await import('node:crypto'); const filename = argv[2]; const hmac = createHmac('sha256', 'a secret'); const input = createReadStream(filename); input.on('readable', () => { // Only one element is going to be produced by the // hash stream. const data = input.read(); if (data) hmac.update(data); else { console.log(`${hmac.digest('hex')} ${filename}`); } }); ```
@sincev0.1.94@paramoptions `stream.transform` options
createHmac
('sha256', const secret: stringsecret)
.Hmac.update(data: crypto.BinaryLike): crypto.Hmac (+1 overload)
Updates the `Hmac` content with the given `data`, the encoding of which is given in `inputEncoding`. If `encoding` is not provided, and the `data` is a string, an encoding of `'utf8'` is enforced. If `data` is a `Buffer`, `TypedArray`, or`DataView`, then `inputEncoding` is ignored. This can be called many times with new data as it is streamed.
@sincev0.1.94@paraminputEncoding The `encoding` of the `data` string.
update
(const signingString: stringsigningString)
.Hmac.digest(encoding: crypto.BinaryToTextEncoding): string (+1 overload)
Calculates the HMAC digest of all of the data passed using `hmac.update()`. If `encoding` is provided a string is returned; otherwise a `Buffer` is returned; The `Hmac` object can not be used again after `hmac.digest()` has been called. Multiple calls to `hmac.digest()` will result in an error being thrown.
@sincev0.1.94@paramencoding The `encoding` of the return value.
digest
('base64');
return module "crypto"
The `node:crypto` module provides cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions. ```js const { createHmac } = await import('node:crypto'); const secret = 'abcdefg'; const hash = createHmac('sha256', secret) .update('I love cupcakes') .digest('hex'); console.log(hash); // Prints: // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e ```
@see[source](https://github.com/nodejs/node/blob/v24.x/lib/crypto.js)
crypto
.function timingSafeEqual(a: NodeJS.ArrayBufferView, b: NodeJS.ArrayBufferView): boolean
This function compares the underlying bytes that represent the given `ArrayBuffer`, `TypedArray`, or `DataView` instances using a constant-time algorithm. This function does not leak timing information that would allow an attacker to guess one of the values. This is suitable for comparing HMAC digests or secret values like authentication cookies or [capability urls](https://www.w3.org/TR/capability-urls/). `a` and `b` must both be `Buffer`s, `TypedArray`s, or `DataView`s, and they must have the same byte length. An error is thrown if `a` and `b` have different byte lengths. If at least one of `a` and `b` is a `TypedArray` with more than one byte per entry, such as `Uint16Array`, the result will be computed using the platform byte order. **When both of the inputs are `Float32Array`s or `Float64Array`s, this function might return unexpected results due to IEEE 754** **encoding of floating-point numbers. In particular, neither `x === y` nor `Object.is(x, y)` implies that the byte representations of two floating-point** **numbers `x` and `y` are equal.** Use of `crypto.timingSafeEqual` does not guarantee that the _surrounding_ code is timing-safe. Care should be taken to ensure that the surrounding code does not introduce timing vulnerabilities.
@sincev6.6.0
timingSafeEqual
(var Buffer: BufferConstructorBuffer.BufferConstructor.from(string: WithImplicitCoercion<string>, encoding?: BufferEncoding): Buffer<ArrayBuffer> (+3 overloads)
Creates a new `Buffer` containing `string`. The `encoding` parameter identifies the character encoding to be used when converting `string` into bytes. ```js import { Buffer } from 'node:buffer'; const buf1 = Buffer.from('this is a tést'); const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); console.log(buf1.toString()); // Prints: this is a tést console.log(buf2.toString()); // Prints: this is a tést console.log(buf1.toString('latin1')); // Prints: this is a tést ``` A `TypeError` will be thrown if `string` is not a string or another type appropriate for `Buffer.from()` variants. `Buffer.from(string)` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.
@sincev5.10.0@paramstring A string to encode.@paramencoding The encoding of `string`. **Default:** `'utf8'`.
from
(const received: stringreceived), var Buffer: BufferConstructorBuffer.BufferConstructor.from(string: WithImplicitCoercion<string>, encoding?: BufferEncoding): Buffer<ArrayBuffer> (+3 overloads)
Creates a new `Buffer` containing `string`. The `encoding` parameter identifies the character encoding to be used when converting `string` into bytes. ```js import { Buffer } from 'node:buffer'; const buf1 = Buffer.from('this is a tést'); const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); console.log(buf1.toString()); // Prints: this is a tést console.log(buf2.toString()); // Prints: this is a tést console.log(buf1.toString('latin1')); // Prints: this is a tést ``` A `TypeError` will be thrown if `string` is not a string or another type appropriate for `Buffer.from()` variants. `Buffer.from(string)` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.
@sincev5.10.0@paramstring A string to encode.@paramencoding The encoding of `string`. **Default:** `'utf8'`.
from
(const expected: stringexpected));
} export default async function function webhookHandler(req: NextApiRequest, res: NextApiResponse): Promise<void>webhookHandler(req: NextApiRequestreq: NextApiRequest, res: NextApiResponseres:
type NextApiResponse<Data = any> = ServerResponse<IncomingMessage> & {
    send: Send<Data>;
    json: Send<Data>;
    status: (statusCode: number) => NextApiResponse<Data>;
    redirect(url: string): NextApiResponse<Data>;
    redirect(status: number, url: string): NextApiResponse<Data>;
    setDraftMode: (options: {
        enable: boolean;
    }) => NextApiResponse<Data>;
    setPreviewData: (data: object | string, options?: {
        maxAge?: number;
        path?: string;
    }) => NextApiResponse<Data>;
    clearPreviewData: (options?: {
        path?: string;
    }) => NextApiResponse<Data>;
    revalidate: (urlPath: string, opts?: {
        unstable_onlyGenerated?: boolean;
    }) => Promise<void>;
}
Next `API` route response
NextApiResponse
) {
const const payload: anypayload = req: NextApiRequestreq.NextApiRequest.body: anybody; if (const payload: anypayload.type === 'github_star_added_event') { const const event: TriggerEvent<GitHubStarEventData>event: interface TriggerEvent<TPayload = unknown>
Generic trigger event type that can be used with generated trigger payload types
@templateTPayload - The specific trigger payload type (e.g., GITHUB_COMMIT_EVENT_PAYLOAD)
TriggerEvent
<
type GitHubStarEventData = {
    repository_name: string;
    repository_url: string;
    starred_by: string;
    starred_at: string;
}
GitHubStarEventData
> = {
TriggerEvent<GitHubStarEventData>.type: stringtype: const payload: anypayload.type, TriggerEvent<GitHubStarEventData>.timestamp: stringtimestamp: const payload: anypayload.timestamp, TriggerEvent<GitHubStarEventData>.data: TriggerEventData<GitHubStarEventData>data: const payload: anypayload.data }; 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
(`Repository ${const event: TriggerEvent<GitHubStarEventData>event.TriggerEvent<GitHubStarEventData>.data: TriggerEventData<GitHubStarEventData>data.repository_name: stringrepository_name} starred by ${const event: TriggerEvent<GitHubStarEventData>event.TriggerEvent<GitHubStarEventData>.data: TriggerEventData<GitHubStarEventData>data.starred_by: stringstarred_by}`);
// Add your business logic here } res: NextApiResponseres.status: (statusCode: number) => NextApiResponse<any>status(200).json: (body: any) => void
Send data `json` data in response
json
({
status: stringstatus: 'success', message: stringmessage: 'Webhook processed' }); }

Coming Soon

Local tools

Previously, the Python SDK included local tools. These were tools defined within the SDK and consisted of local shell and code-related tools such as "clipboard", "sqltool", and "shelltool".

This feature is currently in development for both Python and TypeScript SDKs, with newly created tools built for improved agent accuracy.

This feature is currently in development for both Python and TypeScript SDKs.

API Endpoints

The following table lists important API endpoints that have changed. You can use this reference to quickly find the new v3 API endpoint for migration:

This list is not exhaustive. Please refer to the API Reference for the complete list of endpoints.

Toolkits (formerly Apps)

Previous EndpointCurrent Endpoint
GET /api/v1/appsGET /api/v3/toolkits
GET /api/v1/apps/list/categoriesGET /api/v3/toolkits/categories
GET /api/v1/apps/{appName}GET /api/v3/toolkits/{slug}

Tools (formerly Actions)

Previous EndpointCurrent Endpoint
GET /api/v2/actionsGET /api/v3/tools
GET /api/v2/actions/list/enumsGET /api/v3/tools/enum
GET /api/v2/actions/{actionId}GET /api/v3/tools/{tool_slug}
POST /api/v2/actions/{actionId}/executePOST /api/v3/tools/execute/{tool_slug}
POST /api/v2/actions/{actionId}/execute/get.inputsPOST /api/v3/tools/execute/{tool_slug}/input
POST /api/v2/actions/proxyPOST /api/v3/tools/execute/proxy

Auth Configs (formerly Integrations/Connectors)

Previous EndpointCurrent Endpoint
GET /api/v1/integrationsGET /api/v3/auth_configs
POST /api/v1/integrationsPOST /api/v3/auth_configs
GET /api/v1/integrations/{integrationId}GET /api/v3/auth_configs/{nanoid}
PATCH /api/v1/integrations/{integrationId}PATCH /api/v3/auth_configs/{nanoid}
DELETE /api/v1/integrations/{integrationId}DELETE /api/v3/auth_configs/{nanoid}
POST /api/v2/integrations/createPOST /api/v3/auth_configs

Connected Accounts (formerly Connections)

Previous EndpointCurrent Endpoint
GET /api/v1/connectedAccountsGET /api/v3/connected_accounts
POST /api/v1/connectedAccountsPOST /api/v3/connected_accounts
POST /api/v2/connectedAccounts/initiateConnectionPOST /api/v3/connected_accounts
GET /api/v1/connectedAccounts/{connectedAccountId}GET /api/v3/connected_accounts/{nanoid}
DELETE /api/v1/connectedAccounts/{connectedAccountId}DELETE /api/v3/connected_accounts/{nanoid}
POST /api/v1/connectedAccounts/{connectedAccountId}/disablePATCH /api/v3/connected_accounts/{nanoId}/status
POST /api/v1/connectedAccounts/{connectedAccountId}/enablePATCH /api/v3/connected_accounts/{nanoId}/status
POST /api/v1/connectedAccounts/{connectedAccountId}/reinitiatePOST /api/v3/connected_accounts/{nanoid}/refresh

Triggers

Previous EndpointCurrent Endpoint
GET /api/v1/triggersGET /api/v3/triggers_types
GET /api/v1/triggers/list/enumsGET /api/v3/triggers_types/list/enum
GET /api/v2/triggers/{triggerName}GET /api/v3/triggers_types/{slug}
GET /api/v1/triggers/active_triggersGET /api/v3/trigger_instances/active
POST /api/v1/triggers/enable/{connectedAccountId}/{triggerName}POST /api/v3/trigger_instances/{slug}/upsert
DELETE /api/v1/triggers/instance/{triggerInstanceId}DELETE /api/v3/trigger_instances/manage/{triggerId}
PATCH /api/v1/triggers/instance/{triggerId}/statusPATCH /api/v3/trigger_instances/manage/{triggerId}