Creating Custom Tools
Learn how to extend Composio's toolkits with your own tools
Custom tools allow you to create your own tools that can be used with Composio.
- Standalone tools - Simple tools that don't require any authentication
- Toolkit-based tools - Tools that require authentication and can use toolkit credentials
Creating a Custom Tool
Standalone Tool
A standalone tool is the simplest form of custom tool. It only requires input parameters and an execute function:
from pydantic import BaseModel, Field
from composio import Composio
from composio.types import ExecuteRequestFn
composio = Composio()
class AddTwoNumbersInput(BaseModel):
a: int = Field(
...,
description="The first number to add",
)
b: int = Field(
...,
description="The second number to add",
)
# function name will be used as slug
@composio.tools.custom_tool
def add_two_numbers(request: AddTwoNumbersInput) -> int:
"""Add two numbers."""
return request.a + request.bconst 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 toolstools.Tools<unknown, unknown, OpenAIProvider>.createCustomTool<z.ZodObject<{
number: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
number: number;
}, {
number: number;
}>>(body: CustomToolOptions<z.ZodObject<{
number: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
number: number;
}, {
number: number;
}>>): 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.createCustomTool({
slug: stringslug: 'CALCULATE_SQUARE',
name: stringname: 'Calculate Square',
description?: string | undefineddescription: 'Calculates the square of a number',
inputParams: z.ZodObject<{
number: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
number: number;
}, {
number: number;
}>
inputParams: import zz.object<{
number: z.ZodNumber;
}>(shape: {
number: z.ZodNumber;
}, params?: z.RawCreateParams): z.ZodObject<{
number: z.ZodNumber;
}, "strip", z.ZodTypeAny, {
number: number;
}, {
number: number;
}>
export object
object({
number: z.ZodNumbernumber: import zz.function number(params?: z.RawCreateParams & {
coerce?: boolean;
}): z.ZodNumber
export number
number().ZodType<number, ZodNumberDef, number>.describe(description: string): z.ZodNumberdescribe('The number to calculate the square of'),
}),
execute: (input: {
number: number;
}) => Promise<{
data: {
result: number;
};
error: null;
successful: true;
}>
execute: async input: {
number: number;
}
input => {
const { const number: numbernumber } = input: {
number: number;
}
input;
return {
ToolExecuteResponse.data: {
[key: string]: unknown;
}
Tool execution output data that varies based on the specific tooldata: { result: numberresult: const number: numbernumber * const number: numbernumber },
ToolExecuteResponse.error: string | nullError message if the tool execution was not successful (null if successful)error: null,
ToolExecuteResponse.successful: booleanIndicates if the tool execution was successfulsuccessful: true,
};
},
});Toolkit-based Tool
A toolkit-based tool has access to two ways of making authenticated requests:
1. Using executeToolRequest - The recommended way to make authenticated requests to the toolkit's API endpoints. Composio automatically handles credential injection and baseURL resolution:
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}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 toolstools.Tools<unknown, unknown, OpenAIProvider>.createCustomTool<z.ZodObject<{
repository: z.ZodString;
page: z.ZodOptional<z.ZodNumber>;
customHeader: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}>>(body: CustomToolOptions<z.ZodObject<{
repository: z.ZodString;
page: z.ZodOptional<z.ZodNumber>;
customHeader: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}>>): 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.createCustomTool({
slug: stringslug: 'GITHUB_STAR_COMPOSIOHQ_REPOSITORY',
name: stringname: 'Github star composio repositories',
toolkitSlug: stringtoolkitSlug: 'github',
description?: string | undefineddescription: 'Star any specified repo of `composiohq` user',
inputParams: z.ZodObject<{
repository: z.ZodString;
page: z.ZodOptional<z.ZodNumber>;
customHeader: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}>
inputParams: import zz.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>;
}, params?: z.RawCreateParams): z.ZodObject<{
repository: z.ZodString;
page: z.ZodOptional<z.ZodNumber>;
customHeader: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}, {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}>
export object
object({
repository: z.ZodStringrepository: import zz.function string(params?: z.RawCreateParams & {
coerce?: true;
}): z.ZodString
export string
string().ZodType<string, ZodStringDef, string>.describe(description: string): z.ZodStringdescribe('The repository to star'),
page: z.ZodOptional<z.ZodNumber>page: import zz.function number(params?: z.RawCreateParams & {
coerce?: boolean;
}): z.ZodNumber
export number
number().ZodType<number, ZodNumberDef, number>.optional(): z.ZodOptional<z.ZodNumber>optional().ZodType<number | undefined, ZodOptionalDef<ZodNumber>, number | undefined>.describe(description: string): z.ZodOptional<z.ZodNumber>describe('Pagination page number'),
customHeader: z.ZodOptional<z.ZodString>customHeader: import zz.function string(params?: z.RawCreateParams & {
coerce?: true;
}): z.ZodString
export string
string().ZodType<string, ZodStringDef, string>.optional(): z.ZodOptional<z.ZodString>optional().ZodType<string | undefined, ZodOptionalDef<ZodString>, string | undefined>.describe(description: string): z.ZodOptional<z.ZodString>describe('Custom header'),
}),
execute: (input: {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}, connectionConfig: ConnectionData | null, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>) => Promise<ToolExecuteResponse>
execute: async (input: {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}
input, connectionConfig: {
authScheme: "OAUTH1";
val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIALIZING">;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIATED">;
authUri: z.ZodString;
oauth_token: z.ZodString;
oauth_token_secret: z.ZodString;
redirectUrl: z.ZodString;
callbackUrl: z.ZodOptional<z.ZodString>;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional ...
connectionConfig, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest) => {
// This method makes authenticated requests to the relevant API
// You can use relative paths!
// Composio will automatically inject the baseURL
const const result: ToolExecuteResponseresult = await executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest({
endpoint: stringendpoint: `/user/starred/composiohq/${input: {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}
input.repository: stringrepository}`,
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"method: 'PUT',
body?: unknownbody: {},
// Add custom headers or query parameters
parameters?: {
name: string;
value: string | number;
in: "query" | "header";
}[] | undefined
parameters: [
// Add query parameters
{
name: stringname: 'page',
value: string | numbervalue: input: {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}
input.page?: number | undefinedpage?.Number.toString(radix?: number): stringReturns a string representation of an object.toString() || '1',
in: "query" | "header"in: 'query',
},
// Add custom headers
{
name: stringname: 'x-custom-header',
value: string | numbervalue: input: {
repository: string;
page?: number | undefined;
customHeader?: string | undefined;
}
input.customHeader?: string | undefinedcustomHeader || 'default-value',
in: "query" | "header"in: 'header',
},
],
});
return const result: ToolExecuteResponseresult;
},
});2. Using connectionConfig - For making direct API calls when needed:
import requests
@composio.tools.custom_tool(toolkit="github")
def get_issue_info_direct(
request: GetIssueInfoInput,
execute_request: ExecuteRequestFn,
auth_credentials: dict,
) -> dict:
"""Get information about a GitHub issue."""
response = requests.get(
f"https://api.github.com/repos/composiohq/composio/issues/{request.issue_number}",
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"Bearer {auth_credentials['access_token']}",
},
)
return {"data": response.json()}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 toolstools.Tools<unknown, unknown, OpenAIProvider>.createCustomTool<z.ZodObject<{
repo: z.ZodString;
}, "strip", z.ZodTypeAny, {
repo: string;
}, {
repo: string;
}>>(body: CustomToolOptions<z.ZodObject<{
repo: z.ZodString;
}, "strip", z.ZodTypeAny, {
repo: string;
}, {
repo: string;
}>>): 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.createCustomTool({
slug: stringslug: 'GITHUB_DIRECT_API',
name: stringname: 'Direct GitHub API Call',
description?: string | undefineddescription: 'Makes direct calls to GitHub API',
toolkitSlug: stringtoolkitSlug: 'github',
inputParams: z.ZodObject<{
repo: z.ZodString;
}, "strip", z.ZodTypeAny, {
repo: string;
}, {
repo: string;
}>
inputParams: import zz.object<{
repo: z.ZodString;
}>(shape: {
repo: z.ZodString;
}, params?: z.RawCreateParams): z.ZodObject<{
repo: z.ZodString;
}, "strip", z.ZodTypeAny, {
repo: string;
}, {
repo: string;
}>
export object
object({
repo: z.ZodStringrepo: import zz.function string(params?: z.RawCreateParams & {
coerce?: true;
}): z.ZodString
export string
string().ZodType<string, ZodStringDef, string>.describe(description: string): z.ZodStringdescribe('Repository name'),
}),
execute: (input: {
repo: string;
}, connectionConfig: ConnectionData | null, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>) => Promise<ToolExecuteResponse>
execute: async (input: {
repo: string;
}
input, connectionConfig: {
authScheme: "OAUTH1";
val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIALIZING">;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIATED">;
authUri: z.ZodString;
oauth_token: z.ZodString;
oauth_token_secret: z.ZodString;
redirectUrl: z.ZodString;
callbackUrl: z.ZodOptional<z.ZodString>;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional ...
connectionConfig, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest) => {
// Use connectionConfig for direct API calls
if (!connectionConfig: {
authScheme: "OAUTH1";
val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIALIZING">;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIATED">;
authUri: z.ZodString;
oauth_token: z.ZodString;
oauth_token_secret: z.ZodString;
redirectUrl: z.ZodString;
callbackUrl: z.ZodOptional<z.ZodString>;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional ...
connectionConfig || connectionConfig: {
authScheme: "OAUTH1";
val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIALIZING">;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIATED">;
authUri: z.ZodString;
oauth_token: z.ZodString;
oauth_token_secret: z.ZodString;
redirectUrl: z.ZodString;
callbackUrl: z.ZodOptional<z.ZodString>;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional ...
connectionConfig.authScheme: "OAUTH1" | "OAUTH2" | "API_KEY" | "BASIC" | "BEARER_TOKEN" | "GOOGLE_SERVICE_ACCOUNT" | "NO_AUTH" | "CALCOM_AUTH" | "BILLCOM_AUTH" | "BASIC_WITH_JWT" | "SERVICE_ACCOUNT" | "SAML" | "DCR_OAUTH"authScheme !== 'OAUTH2') {
throw new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error('OAuth2 connection required');
}
const const result: Responseresult = await function fetch(input: string | URL | Request, init?: RequestInit): Promise<Response> (+1 overload)[MDN Reference](https://developer.mozilla.org/docs/Web/API/Window/fetch)fetch(`https://api.github.com/repos/${input: {
repo: string;
}
input.repo: stringrepo}`, {
RequestInit.headers?: HeadersInit | undefinedA Headers object, an object literal, or an array of two-item arrays to set request's headers.headers: {
type Authorization: stringAuthorization: `Bearer ${connectionConfig: {
authScheme: "OAUTH2";
val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIALIZING">;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIATED">;
code_verifier: z.ZodOptional<z.ZodString>;
redirectUrl: z.ZodString;
callback_url: z.ZodOptional<z.ZodString>;
finalRedirectUri: z.ZodOptional<z.ZodString>;
webhook_signature: z.ZodOptional<z.ZodString>;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional< ...
connectionConfig.val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
... 23 more ...;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
...;
}, z.ZodUnknown, "strip"> | ... 4 more ... | z.objectOutputType<...>
val.access_token: unknownaccess_token}`,
},
});
return {
ToolExecuteResponse.data: {
[key: string]: unknown;
}
Tool execution output data that varies based on the specific tooldata: await const result: Responseresult.Body.json(): Promise<any>[MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/json)json(),
ToolExecuteResponse.error: string | nullError message if the tool execution was not successful (null if successful)error: null,
ToolExecuteResponse.successful: booleanIndicates if the tool execution was successfulsuccessful: true,
};
},
});Using Custom Headers and Query Parameters
You can add custom headers and query parameters to your toolkit-based tools using the parameters option in executeToolRequest:
@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",
},
{
"name": 'X-Custom-Header',
"value": 'custom-value',
"type": 'header',
},
],
)
return {"data": response.data}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 toolstools.Tools<unknown, unknown, OpenAIProvider>.createCustomTool<z.ZodObject<{
query: z.ZodString;
perPage: z.ZodOptional<z.ZodNumber>;
acceptType: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}>>(body: CustomToolOptions<z.ZodObject<{
query: z.ZodString;
perPage: z.ZodOptional<z.ZodNumber>;
acceptType: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}>>): 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.createCustomTool({
slug: stringslug: 'GITHUB_SEARCH_REPOSITORIES',
name: stringname: 'Search GitHub Repositories',
description?: string | undefineddescription: 'Search for repositories with custom parameters',
toolkitSlug: stringtoolkitSlug: 'github',
inputParams: z.ZodObject<{
query: z.ZodString;
perPage: z.ZodOptional<z.ZodNumber>;
acceptType: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}>
inputParams: import zz.object<{
query: z.ZodString;
perPage: z.ZodOptional<z.ZodNumber>;
acceptType: z.ZodOptional<z.ZodString>;
}>(shape: {
query: z.ZodString;
perPage: z.ZodOptional<z.ZodNumber>;
acceptType: z.ZodOptional<z.ZodString>;
}, params?: z.RawCreateParams): z.ZodObject<{
query: z.ZodString;
perPage: z.ZodOptional<z.ZodNumber>;
acceptType: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}, {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}>
export object
object({
query: z.ZodStringquery: import zz.function string(params?: z.RawCreateParams & {
coerce?: true;
}): z.ZodString
export string
string().ZodType<string, ZodStringDef, string>.describe(description: string): z.ZodStringdescribe('Search query'),
perPage: z.ZodOptional<z.ZodNumber>perPage: import zz.function number(params?: z.RawCreateParams & {
coerce?: boolean;
}): z.ZodNumber
export number
number().ZodType<number, ZodNumberDef, number>.optional(): z.ZodOptional<z.ZodNumber>optional().ZodType<number | undefined, ZodOptionalDef<ZodNumber>, number | undefined>.describe(description: string): z.ZodOptional<z.ZodNumber>describe('Results per page'),
acceptType: z.ZodOptional<z.ZodString>acceptType: import zz.function string(params?: z.RawCreateParams & {
coerce?: true;
}): z.ZodString
export string
string().ZodType<string, ZodStringDef, string>.optional(): z.ZodOptional<z.ZodString>optional().ZodType<string | undefined, ZodOptionalDef<ZodString>, string | undefined>.describe(description: string): z.ZodOptional<z.ZodString>describe('Custom accept header'),
}),
execute: (input: {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}, connectionConfig: ConnectionData | null, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>) => Promise<ToolExecuteResponse>
execute: async (input: {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}
input, connectionConfig: {
authScheme: "OAUTH1";
val: z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIALIZING">;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional<z.ZodString>;
registration_client_uri: z.ZodOptional<z.ZodString>;
composio_link_redirect_url: z.ZodOptional<z.ZodString>;
} & {
status: z.ZodLiteral<"INITIATED">;
authUri: z.ZodString;
oauth_token: z.ZodString;
oauth_token_secret: z.ZodString;
redirectUrl: z.ZodString;
callbackUrl: z.ZodOptional<z.ZodString>;
}, z.ZodUnknown, "strip"> | z.objectOutputType<{
subdomain: z.ZodOptional<z.ZodString>;
"your-domain": z.ZodOptional<z.ZodString>;
region: z.ZodOptional<z.ZodString>;
shop: z.ZodOptional<z.ZodString>;
account_url: z.ZodOptional<z.ZodString>;
COMPANYDOMAIN: z.ZodOptional<z.ZodString>;
extension: z.ZodOptional<z.ZodString>;
form_api_base_url: z.ZodOptional<z.ZodString>;
instanceEndpoint: z.ZodOptional<z.ZodString>;
api_url: z.ZodOptional<z.ZodString>;
borneo_dashboard_url: z.ZodOptional<z.ZodString>;
proxy_username: z.ZodOptional<z.ZodString>;
proxy_password: z.ZodOptional<z.ZodString>;
domain: z.ZodOptional<z.ZodString>;
version: z.ZodOptional<z.ZodString>;
dc: z.ZodOptional<z.ZodString>;
site_name: z.ZodOptional<z.ZodString>;
instanceName: z.ZodOptional<z.ZodString>;
account_id: z.ZodOptional<z.ZodString>;
your_server: z.ZodOptional<z.ZodString>;
server_location: z.ZodOptional<z.ZodString>;
base_url: z.ZodOptional<z.ZodString>;
api_key: z.ZodOptional<z.ZodString>;
generic_api_key: z.ZodOptional<z.ZodString>;
bearer_token: z.ZodOptional<z.ZodString>;
basic_encoded: z.ZodOptional<z.ZodString>;
long_redirect_url: z.ZodOptional<z.ZodBoolean>;
state_prefix: z.ZodOptional<z.ZodString>;
registration_access_token: z.ZodOptional ...
connectionConfig, executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest) => {
const const result: ToolExecuteResponseresult = await executeToolRequest: (data: ToolProxyParams) => Promise<ToolExecuteResponse>executeToolRequest({
endpoint: stringendpoint: '/search/repositories',
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"method: 'GET',
parameters?: {
name: string;
value: string | number;
in: "query" | "header";
}[] | undefined
parameters: [
// Add query parameters for pagination
{
name: stringname: 'q',
value: string | numbervalue: input: {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}
input.query: stringquery,
in: "query" | "header"in: 'query',
},
{
name: stringname: 'per_page',
value: string | numbervalue: (input: {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}
input.perPage?: number | undefinedperPage || 30).Number.toString(radix?: number): stringReturns a string representation of an object.toString(),
in: "query" | "header"in: 'query',
},
// Add custom headers
{
name: stringname: 'Accept',
value: string | numbervalue: input: {
query: string;
perPage?: number | undefined;
acceptType?: string | undefined;
}
input.acceptType?: string | undefinedacceptType || 'application/vnd.github.v3+json',
in: "query" | "header"in: 'header',
},
{
name: stringname: 'X-Custom-Header',
value: string | numbervalue: 'custom-value',
in: "query" | "header"in: 'header',
},
],
});
return const result: ToolExecuteResponseresult;
},
});Executing Custom Tools
You can execute custom tools just like any other tool:
response = composio.tools.execute(
user_id="default",
slug="TOOL_SLUG", # For the tool above you can use `get_issue_info.slug`
arguments={"issue_number": 1},
)const const result: {
error: string | null;
data: Record<string, unknown>;
successful: boolean;
logId?: string | undefined;
sessionInfo?: unknown;
}
result = await const composio: Composio<OpenAIProvider>composio.Composio<OpenAIProvider>.tools: Tools<unknown, unknown, OpenAIProvider>List, retrieve, and execute toolstools.Tools<unknown, unknown, OpenAIProvider>.execute(slug: string, body: ToolExecuteParams, modifiers?: ExecuteToolModifiers): Promise<ToolExecuteResponse>Executes a given tool with the provided parameters.
This method calls the Composio API or a custom tool handler to execute the tool and returns the response.
It automatically determines whether to use a custom tool or a Composio API tool based on the slug.
**Version Control:**
By default, manual tool execution requires a specific toolkit version. If the version resolves to "latest",
the execution will throw a `ComposioToolVersionRequiredError` unless `dangerouslySkipVersionCheck` is set to `true`.
This helps prevent unexpected behavior when new toolkit versions are released.execute('TOOL_SLUG', {
arguments?: Record<string, unknown> | undefinedarguments: {
// Tool input parameters
},
userId?: string | undefineduserId: 'user-id',
connectedAccountId?: string | undefinedconnectedAccountId: 'optional-account-id', // Required for toolkit-based tools
});Best Practices
- Use descriptive names and slugs for your tools
- Always provide descriptions for input parameters using
describe() - Handle errors gracefully in your execute function
- For toolkit-based tools:
- Prefer
executeToolRequestover direct API calls when possible - Use relative paths with
executeToolRequest- Composio will automatically inject the correct baseURL - Use the
parametersoption to add custom headers or query parameters:parameters: [ {name: stringname: 'page',value: stringvalue: '1',in: stringin: 'query' }, // Adds ?page=1 to URL {name: stringname: 'x-custom',value: stringvalue: 'value',in: stringin: 'header' }, // Adds header ]; - Remember that
executeToolRequestcan only call tools from the same toolkit - Use
executeToolRequestto leverage Composio's automatic credential handling - Only use
connectionConfigwhen you need to make direct API calls or interact with different services
- Prefer
- Chain multiple toolkit operations using
executeToolRequestfor better maintainability
Limitations
- Custom tools are stored in memory and are not persisted
- They need to be recreated when the application restarts
- Toolkit-based tools require a valid connected account with the specified toolkit
executeToolRequestcan only execute tools from the same toolkit that the custom tool belongs to- Each toolkit-based tool can only use one connected account at a time