Open Connector
Build agents

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 response

Execute endpoint

POST /composio/api/v3.1/tools/execute/{slug}
ParameterDescription
slugThe 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 statusMeaning
200Tool executed. Check successful in the response body — the third-party API may have returned an error even with HTTP 200.
400Bad request — e.g. missing connected_account_id/user_id, or malformed arguments.
401Invalid or missing x-api-key.
403The tool is not permitted for this connection, or the connection belongs to another project.
404Tool slug not found, or the connection could not be resolved.
408The third-party request timed out.

On this page