Calling Tools
Execute named actions on behalf of connected users via the execute endpoint.
Tool calls are named actions executed server-side by Open Connector on behalf of a connected user. When your agent calls GITHUB_CREATE_AN_ISSUE, Open Connector looks up the connected account, decrypts the stored OAuth token, makes the request to the GitHub API with the token injected, and returns the response to your agent. The agent never receives the raw credential.
How it works
Agent → POST /tools/execute/GITHUB_CREATE_AN_ISSUE
│ connected_account_id, arguments
▼
Open Connector
│ 1. Verify agent API key (project scope)
│ 2. Load connected account
│ 3. Decrypt OAuth token from vault
│ 4. Build outbound request to api.github.com
│ 5. Inject Authorization: Bearer <token>
│ 6. Execute request, write audit record
▼
GitHub API → response
▼
Agent ← proxied responseExecute endpoint
POST /composio/api/v3.1/tools/execute/{slug}| Parameter | Description |
|---|---|
slug | The tool slug in TOOLKIT_ACTION_NAME format, e.g. GITHUB_CREATE_AN_ISSUE |
Request shape
Provide exactly one of connected_account_id (the connection to act through) or user_id (let Open Connector resolve the user's connection for this tool). Put the tool's parameters under arguments.
{
"connected_account_id": "conn_01j9xyz789",
"arguments": {
"owner": "my-org",
"repo": "my-repo",
"title": "Bug found by agent",
"body": "The agent detected an anomaly in production."
}
}Response shape
{
"data": {
"id": 1234567890,
"number": 42,
"title": "Bug found by agent",
"html_url": "https://github.com/my-org/my-repo/issues/42",
"state": "open"
},
"error": null,
"successful": true,
"session_info": null,
"log_id": "key_01j9def456"
}On failure:
{
"data": null,
"error": "GitHub API returned 422: Validation Failed",
"successful": false,
"session_info": null,
"log_id": "key_01j9def456"
}Examples
Create a GitHub issue
import { createClient } from "@open-connector/sdk";
const oc = createClient({
apiKey: process.env.OPEN_CONNECTOR_API_KEY!,
baseUrl: "https://api.openconnector.dev",
});
const result = await oc.executeTool({
slug: "GITHUB_CREATE_AN_ISSUE",
connectedAccountId: "conn_01j9xyz789",
arguments: {
owner: "my-org",
repo: "my-repo",
title: "Bug found by agent",
body: "The agent detected an anomaly in production.",
labels: ["bug", "agent-reported"],
},
});
console.log(result.successful, result.data);import Composio from "@composio/client";
const composio = new Composio({
apiKey: process.env.OPEN_CONNECTOR_API_KEY!,
baseURL: "https://api.openconnector.dev/composio",
});
const result = await composio.tools.execute("GITHUB_CREATE_AN_ISSUE", {
connected_account_id: "conn_01j9xyz789",
arguments: {
owner: "my-org",
repo: "my-repo",
title: "Bug found by agent",
body: "The agent detected an anomaly in production.",
labels: ["bug", "agent-reported"],
},
});
if (result.successful) {
console.log("Issue created:", result.data.html_url);
} else {
console.error("Tool call failed:", result.error);
}curl -X POST \
"https://api.openconnector.dev/composio/api/v3.1/tools/execute/GITHUB_CREATE_AN_ISSUE" \
-H "x-api-key: oc_abc123xyz..." \
-H "Content-Type: application/json" \
-d '{
"connected_account_id": "conn_01j9xyz789",
"arguments": {
"owner": "my-org",
"repo": "my-repo",
"title": "Bug found by agent",
"body": "The agent detected an anomaly in production.",
"labels": ["bug", "agent-reported"]
}
}'Send a Telegram message
const result = await oc.executeTool({
slug: "TELEGRAM_SEND_MESSAGE",
connectedAccountId: "conn_telegram_01j9",
arguments: {
chat_id: "123456789",
text: "Agent task complete — results are ready.",
},
});
console.log(result.successful, result.data);const result = await composio.tools.execute("TELEGRAM_SEND_MESSAGE", {
connected_account_id: "conn_telegram_01j9",
arguments: {
chat_id: "123456789",
text: "Agent task complete — results are ready.",
},
});
console.log(result.successful, result.data);curl -X POST \
"https://api.openconnector.dev/composio/api/v3.1/tools/execute/TELEGRAM_SEND_MESSAGE" \
-H "x-api-key: oc_abc123xyz..." \
-H "Content-Type: application/json" \
-d '{
"connected_account_id": "conn_telegram_01j9",
"arguments": {
"chat_id": "123456789",
"text": "Agent task complete — results are ready."
}
}'Discovering available tools
To see what tools are available, query the tool catalog. Filter by toolkit with toolkit_slugs:
curl "https://api.openconnector.dev/composio/api/v3.1/tools?toolkit_slug=github" \
-H "x-api-key: oc_abc123xyz..."The response includes each tool's slug and description; retrieve a single tool for its input schema:
const tools = await oc.listTools({ toolkit: "github", limit: 100 });
for (const tool of tools.items) {
const detail = await oc.getTool({ slug: tool.slug });
console.log(detail.slug, detail.inputParameters);
}const tools = await composio.tools.list({ toolkit_slug: "github" });
for (const tool of tools.items) {
console.log(tool.slug, tool.description);
}Using tool definitions with LLM frameworks
Tool definitions from Open Connector can be passed directly to LLMs that support function calling. Here is an example with the Vercel AI SDK:
import { createClient } from "@open-connector/sdk";
const oc = createClient({
apiKey: process.env.OPEN_CONNECTOR_API_KEY!,
baseUrl: "https://api.openconnector.dev",
});
const catalog = await oc.listTools({ toolkit: "github", limit: 100 });
const definitions = await Promise.all(
catalog.items.map((tool) => oc.getTool({ slug: tool.slug })),
);
// Map definitions into your LLM framework's tool format. In each execute
// callback, call oc.executeTool({ slug, connectedAccountId, arguments }).import Composio from "@composio/client";
const composio = new Composio({
apiKey: process.env.OPEN_CONNECTOR_API_KEY!,
baseURL: "https://api.openconnector.dev/composio",
});
const catalog = await composio.tools.list({ toolkit_slug: "github" });
// Map catalog.items into your LLM framework's tool format. In each execute
// callback, call composio.tools.execute(slug, { connected_account_id, arguments }).Every tool call is written to the tamper-evident audit journal with the connected account ID, tool slug, request timestamp, and response status. See Audit Trail for details.
Error handling
| HTTP status | Meaning |
|---|---|
200 | Tool executed. Check successful in the response body — the third-party API may have returned an error even with HTTP 200. |
400 | Bad request — e.g. missing connected_account_id/user_id, or malformed arguments. |
401 | Invalid or missing x-api-key. |
403 | The tool is not permitted for this connection, or the connection belongs to another project. |
404 | Tool slug not found, or the connection could not be resolved. |
408 | The third-party request timed out. |