Learn how to create custom providers for any AI platform in TypeScript
This guide provides a comprehensive walkthrough of creating custom providers for the Composio TypeScript SDK, enabling integration with different AI frameworks and platforms.
Non-agentic providers implement the BaseNonAgenticProvider abstract class:
import { class BaseNonAgenticProvider<TToolCollection$1, TTool$1, TMcpResponse$1 = McpServerGetResponse>
@publicBase class for all non-agentic providers.
This class is not meant to be used directly, but rather to be extended by concrete provider implementations.
@publicBase class for all non-agentic providers.
This class is not meant to be used directly, but rather to be extended by concrete provider implementations.
BaseNonAgenticProvider<type MyAIToolCollection = MyAITool[]MyAIToolCollection, MyAITool> { // Required: Unique provider name for telemetry readonlyMyAIProvider.name: "my-ai-platform"
@publicThe name of the provider.
Used to identify the provider in the telemetry.
name = 'my-ai-platform'; // Required: Method to transform a single tool overrideMyAIProvider.wrapTool(tool: Tool): MyAITool
Wrap a tool in the provider specific format.
@paramtool - The tool to wrap.@returnsThe wrapped tool.
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
result = await this.BaseProvider<McpServerGetResponse>.executeTool(toolSlug: string, body: ToolExecuteParams, modifers?: ExecuteToolModifiers): Promise<ToolExecuteResponse>
@publicGlobal function to execute a tool.
This function is used by providers to implement helper functions to execute tools.
This is a 1:1 mapping of the `execute` method in the `Tools` class.@paramtoolSlug - The slug of the tool to execute.@parambody - The body of the tool execution.@parammodifers - The modifiers of the tool execution.@returnsThe result of the tool execution.
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
@paramvalue A JavaScript value, usually an object or array, to be converted.@paramreplacer A function that transforms the results.@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.
Agentic providers implement the BaseAgenticProvider abstract class:
import { class BaseAgenticProvider<TToolCollection$1, TTool$1, TMcpResponse$1>
@publicBase class for all agentic providers.
This class is not meant to be used directly, but rather to be extended by concrete provider implementations.
@publicBase class for all agentic providers.
This class is not meant to be used directly, but rather to be extended by concrete provider implementations.
BaseAgenticProvider<AgentToolkit, AgentTool> { // Required: Unique provider name for telemetry readonlyMyAgentProvider.name: "my-agent-platform"name = 'my-agent-platform'; // Required: Method to transform a single tool with execute function overrideMyAgentProvider.wrapTool(tool: Tool, executeToolFn: ExecuteToolFn): AgentToolwrapTool(
result.data: Record<string, unknown>data; }, }; } // Required: Method to transform a collection of tools with execute function overrideMyAgentProvider.wrapTools(tools: Tool[], executeToolFn: ExecuteToolFn): AgentToolkitwrapTools(
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
tool, executeToolFn: ExecuteToolFnexecuteToolFn)); return {AgentToolkit.tools: AgentTool[]tools: const agentTools: AgentTool[]agentTools,AgentToolkit.createAgent: (config: Record<string, unknown>) => unknowncreateAgent: config: Record<string, unknown>config => { // Create an agent using the tools return {run: (prompt: string) => Promise<void>run: async (prompt: stringprompt: string) => { // Implementation depends on your agent frameworkvar 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
```
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(`Running agent with prompt: ${prompt: stringprompt}`); // The agent would use the tools.execute method to run tools }, }; }, }; } // Optional: Custom helper methods for your agent platform asyncMyAgentProvider.runAgent(agentToolkit: AgentToolkit, prompt: string): Promise<unknown>runAgent(agentToolkit: AgentToolkitagentToolkit:AgentToolkit, prompt: stringprompt: string):interface Promise<T>
Represents the completion of an asynchronous operation
After creating your provider, use it with the Composio SDK:
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 MyAIProviderMyAIProvider } from './my-ai-provider';// Create your provider instanceconstconst myProvider: anymyProvider = newimport MyAIProviderMyAIProvider();// Initialize Composio with your providerconstconst composio: Composio<any>composio = newnew Composio<any>(config?: ComposioConfig<any> | undefined): Composio<any>
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({apiKey?: string | null | undefined
The API key for the Composio API.
@example'sk-1234567890'
apiKey: 'your-composio-api-key',provider?: any
The tool provider to use for this Composio instance.
@examplenew OpenAIProvider()
provider: const myProvider: anymyProvider,});// Get tools - they will be transformed by your providerconstconst tools: anytools = awaitconst composio: Composio<any>composio.Composio<any>.tools: Tools<unknown, unknown, any>
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('default', {toolkits: [string]toolkits: ['github'],});// Use the tools with your AI platformvar 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
```
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 tools: anytools); // These will be in your custom format
Calls a defined callback function on each element of an array, and returns an array that contains the results.
@paramcallbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.@paramthisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
@returnsReturns the element associated with the specified key. If no element is associated with the specified key, undefined is returned.
Executes a tool call from OpenAI's chat completion.
This method processes a tool call from OpenAI's chat completion API,
executes the corresponding Composio tool, and returns the result.
@paramuserId - The user ID for authentication and tracking@paramtool - The tool call from OpenAI@paramoptions - Optional execution options@parammodifiers - Optional execution modifiers@returnsThe result of the tool call as a JSON string@example```typescript
// Execute a tool call from OpenAI
const toolCall = {
id: 'call_abc123',
type: 'function',
function: {
name: 'SEARCH_TOOL',
arguments: '{"query":"composio documentation"}'
}
};
const result = await provider.executeToolCall(
'user123',
toolCall,
{ connectedAccountId: 'conn_xyz456' }
);
console.log(JSON.parse(result));
```
Executes a tool call from OpenAI's chat completion.
This method processes a tool call from OpenAI's chat completion API,
executes the corresponding Composio tool, and returns the result.
@paramuserId - The user ID for authentication and tracking@paramtool - The tool call from OpenAI@paramoptions - Optional execution options@parammodifiers - Optional execution modifiers@returnsThe result of the tool call as a JSON string@example```typescript
// Execute a tool call from OpenAI
const toolCall = {
id: 'call_abc123',
type: 'function',
function: {
name: 'SEARCH_TOOL',
arguments: '{"query":"composio documentation"}'
}
};
const result = await provider.executeToolCall(
'user123',
toolCall,
{ connectedAccountId: 'conn_xyz456' }
);
console.log(JSON.parse(result));
```
Executes a tool call from OpenAI's chat completion.
This method processes a tool call from OpenAI's chat completion API,
executes the corresponding Composio tool, and returns the result.
@paramuserId - The user ID for authentication and tracking@paramtool - The tool call from OpenAI@paramoptions - Optional execution options@parammodifiers - Optional execution modifiers@returnsThe result of the tool call as a JSON string@example```typescript
// Execute a tool call from OpenAI
const toolCall = {
id: 'call_abc123',
type: 'function',
function: {
name: 'SEARCH_TOOL',
arguments: '{"query":"composio documentation"}'
}
};
const result = await provider.executeToolCall(
'user123',
toolCall,
{ connectedAccountId: 'conn_xyz456' }
);
console.log(JSON.parse(result));
```
@paramexecutor A callback used to initialize the promise. This callback is passed two arguments:
a resolve callback used to resolve the promise with a value or the result of another promise,
and a reject callback used to reject the promise with a provided reason or error.