> **Building with AI coding agents?** Install the authstack plugin with one command. This equips your agent with accurate Scalekit implementation patterns.
>
> **Recommended**:
> ```bash
> npx @scalekit-inc/cli setup
> ```
>
> Global:
> ```bash
> npm install -g @scalekit-inc/cli
> scalekit setup
> ```
>
> Supports Claude Code, Cursor, GitHub Copilot, Codex + skills for other Agent Skills-compatible agents.
> Skills: integrate-agentkit, implement-saaskit, add-mcp-oauth, implement-sso, implement-scim.
> [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Execute a tool

`POST /api/v1/execute_tool`

Runs one tool as a user, with that user's credentials for the connection. Identify the account with `connector` and `identifier`, or with `connected_account_id`, and pass the tool's inputs in `params`; each connector page lists its tools and their inputs. When the connected account is `EXPIRED`, the call returns `401` with `TOOL_ERROR`; when it's otherwise not `ACTIVE`, `400` with `INVALID_ARGUMENT`. Either way, send the user an [authorization link](https://docs.scalekit.com/agentkit/reference/authorization/get-an-authorization-link/). [Errors and rate limits](https://docs.scalekit.com/agentkit/reference/errors/) explains each tool error code.

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `tool_name` | string | Yes | Name of the tool to execute. |
| `agent_run_id` | string | No | Customer-supplied identifier grouping multiple tool calls into a single agent run. Useful for correlating logs across an agentic workflow. |
| `connected_account_id` | string | No | The unique ID of the connected account. Use this to directly identify the connected account instead of using identifier + connector combination. |
| `connector` | string | No | The connection name, as shown in **AgentKit** > **Connections**. |
| `identifier` | string | No | Your app's ID for the user, the same value you used when the user connected. Use a stable internal ID, not an email address. |
| `organization_id` | string | No | The organization ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple organizations. |
| `params` | object | No | JSON object containing the parameters required for tool execution. The structure depends on the specific tool being executed. |
| `user_id` | string | No | The user ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple users. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `data` | object | The tool's output: the app's response, as JSON. |
| `execution_id` | string | Unique identifier for the tool execution. |

**Errors**

- `400`: Invalid request - error code `INVALID_ARGUMENT` when the tool name is missing, the input doesn't match the tool's schema, the connected account belongs to a different app than the tool, or the account isn't `ACTIVE`. Error code `TOOL_ERROR` when the app rejected the call; `tool_error_info.tool_error_code` is `INVALID_ARGUMENT`, `EXECUTION_ERROR`, `INTERNAL_ERROR` or, for a tool from an app's MCP server, `TOOL_ERROR`, and `tool_error_message` has the app's message.
- `401`: Error code `UNAUTHENTICATED` when your access token is missing, invalid or expired; get a new token and retry. Error code `TOOL_ERROR` with `tool_error_code` `REAUTHENTICATION_NEEDED` or `UNAUTHENTICATED` when the user's access to the app was revoked or expired; send the user a new authorization link.
- `403`: Error code `TOOL_ERROR` with `tool_error_code` `FORBIDDEN` or `PERMISSION_DENIED` - the app refused the call. The account's credentials are valid but lack the scope this tool needs. The connected account stays `ACTIVE`; grant the missing scope on the connection, have the user authorize again, then retry.
- `404`: Not found - the tool or the connected account doesn't exist. Error code `TOOL_ERROR` with `tool_error_code` `RESOURCE_NOT_FOUND` when the app couldn't find what the call refers to, such as an event ID.
- `429`: Error code `TOOL_ERROR` with `tool_error_code` `RATE_LIMITED` - the app rate-limited the call. Back off and retry.
- `500`: Error code `TOOL_ERROR` with `tool_error_code` `INTERNAL_ERROR` when Scalekit couldn't run the tool, for example because the connection's auth type isn't supported for this tool. For a tool from an app's MCP server, `tool_error_code` `TOOL_ERROR` when that server failed, rate-limited the call or couldn't be reached; its status is in `tool_error_message`. A retry can run the tool twice, so retry only tools that are safe to repeat, and quote `execution_id` to support.

**Request**

```bash
curl -sS -X POST \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/execute_tool" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tool_name": "gmail_fetch_mails",
    "connector": "gmail",
    "identifier": "user_123",
    "params": {
      "query": "is:unread",
      "max_results": 5
    }
  }'
```

**Response**

```json
{
  "data": {
    "messages": [
      {
        "id": "19a4f2c8e6b1d037",
        "threadId": "19a4f2c8e6b1d037",
        "labelIds": [
          "UNREAD",
          "IMPORTANT",
          "INBOX"
        ],
        "snippet": "Here are the notes from today's planning call",
        "payload": {
          "mimeType": "multipart/alternative",
          "headers": [
            {
              "name": "From",
              "value": "Dana Lee <dana@example.com>"
            },
            {
              "name": "Subject",
              "value": "Notes from the planning call"
            },
            {
              "name": "Date",
              "value": "Fri, 2 Oct 2026 13:52:10 +0000"
            }
          ]
        },
        "sizeEstimate": 6421,
        "historyId": "2174983",
        "internalDate": "1790949130000"
      }
    ],
    "page_token": ""
  },
  "execution_id": "6f1c2e4a-a0b3-11f1-9c2a-0242ac120002"
}
```

**Python SDK:** `scalekit_client.actions.execute_tool`

Execute a tool with the given parameters.

```python
scalekit_client.actions.execute_tool(
    tool_input: ToolInput,
    tool_name: str,
    identifier: Optional[str] = None,
    tool_request: Optional[ToolRequest] = None,
    connected_account_id: Optional[str] = None,
    connection_name: Optional[str] = None,
) -> ExecuteToolResponse
```

Example:

```python
result = scalekit_client.actions.execute_tool(
    tool_input={"query": "is:unread", "max_results": 5},
    tool_name="gmail_fetch_mails",
    identifier="user_123",
    connection_name="gmail",
)
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `tool_input` | `ToolInput` | Yes | Input data for the tool execution |
| `tool_name` | `str` | Yes | Name of the tool to execute |
| `identifier` | `Optional[str]` | No | Your app's ID for the user, the same value you used when the user connected. Use a stable internal ID, not an email address. |
| `connected_account_id` | `Optional[str]` | No | ID of the connected account to use. Provide this OR the (identifier + connection_name) pair — not both. |
| `connection_name` | `Optional[str]` | No | The connection name, as shown in **AgentKit** > **Connections**. |

Returns `ExecuteToolResponse`: The tool's output in `data`, and the `execution_id`.

**Node.js SDK:** `scalekit.actions.executeTool`

Execute a tool on behalf of a connected account. Identify the account with `connector` and `identifier`, or with `connectedAccountId`.

```ts
scalekit.actions.executeTool(
  params: {
    toolName: string;
    toolInput: Record<string, unknown>;
    identifier?: string;
    connectedAccountId?: string;
    connector?: string;
    organizationId?: string;
    userId?: string;
  },
): Promise<ExecuteToolResponse>
```

Example:

```ts
const result = await scalekit.actions.executeTool({
  toolName: "gmail_fetch_mails",
  toolInput: { query: "is:unread", max_results: 5 },
  identifier: "user_123",
  connector: "gmail",
});
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `toolName` | `string` | Yes | Name of the tool to execute |
| `toolInput` | `Record<string, unknown>` | Yes | JSON object containing the parameters required for tool execution. The structure depends on the specific tool being executed. |
| `identifier` | `string` | No | Your app's ID for the user, the same value you used when the user connected. Use a stable internal ID, not an email address. |
| `connectedAccountId` | `string` | No | The unique ID of the connected account. Use this to directly identify the connected account instead of using identifier + connector combination. |
| `connector` | `string` | No | The connection name, as shown in **AgentKit** > **Connections**. |
| `organizationId` | `string` | No | The organization ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple organizations. |
| `userId` | `string` | No | The user ID to scope the connected account lookup. Use this to narrow down the search when the same identifier exists across multiple users. |

Returns `Promise<ExecuteToolResponse>`.

**Used in**

- [Anthropic](https://docs.scalekit.com/agentkit/examples/anthropic/)
- [Build a daily briefing agent with Vercel AI SDK and Scalekit AgentKit](https://docs.scalekit.com/cookbooks/daily-briefing-agent/)
- [Build a LiveKit voice agent with Scalekit AgentKit tools](https://docs.scalekit.com/cookbooks/livekit-agentkit-voice-tool-calling/)
- [Build a Mastra agent with Scalekit AgentKit tools](https://docs.scalekit.com/cookbooks/mastra-agentkit/)
- [Build a multi-user GitHub PR summarizer agent](https://docs.scalekit.com/cookbooks/render-github-pr-summarizer/)
- [Build an agent that books meetings and drafts emails](https://docs.scalekit.com/cookbooks/schedule-meeting-and-draft-email/)
- [Call your connector](https://docs.scalekit.com/agentkit/bring-your-own-connector/making-tool-calls/)
- [FastRouter + Scalekit tool calling](https://docs.scalekit.com/cookbooks/fastrouter-agentkit-tool-calling/)
- [Migrate from Composio to Scalekit](https://docs.scalekit.com/agentkit/advanced/migrate-from-composio/)
- [OpenAI](https://docs.scalekit.com/agentkit/examples/openai/)
- [Quickstart](https://docs.scalekit.com/agentkit/quickstart/)
- [Use built-in tools](https://docs.scalekit.com/agentkit/tools/scalekit-optimized-tools/)
- [Vercel AI SDK](https://docs.scalekit.com/agentkit/examples/vercel-ai/)

Every [connector page](https://docs.scalekit.com/agentkit/connectors/) shows this call with that connector's tools and their inputs.


Part of [Tools](https://docs.scalekit.com/agentkit/reference/tools/) in the [AgentKit API reference](https://docs.scalekit.com/agentkit/reference/). Authentication: https://docs.scalekit.com/agentkit/reference/authentication.md. Errors and rate limits: https://docs.scalekit.com/agentkit/reference/errors.md. Pagination: https://docs.scalekit.com/agentkit/reference/pagination.md


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
