> **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/)

---

# Tools

Find the tools your agent can use and call them as a user. [Use built-in tools](https://docs.scalekit.com/agentkit/tools/scalekit-optimized-tools/) shows the whole flow, and each [connector](https://docs.scalekit.com/agentkit/connectors/) lists its tools and their inputs. To call an endpoint of the app's API that no tool covers, send it through the API proxy at `/proxy/<path>`, as [Call any API](https://docs.scalekit.com/agentkit/tools/custom-tools/) shows.

One page per endpoint, each with its own markdown copy:

| Endpoint | Request | What it does | Python SDK | Node.js SDK |
| --- | --- | --- | --- | --- |
| [Execute a tool](https://docs.scalekit.com/agentkit/reference/tools/execute-a-tool.md) | `POST /api/v1/execute_tool` | Run one tool as a user, with that user's credentials. | `actions.execute_tool` | `actions.executeTool` |
| [List tools](https://docs.scalekit.com/agentkit/reference/tools/list-tools.md) | `GET /api/v1/tools` | List the tools in your environment, filtered by connection, provider or name. | `actions.list_tools` | `actions.listTools` |
| [List a user's scoped tools (beta)](https://docs.scalekit.com/agentkit/reference/tools/list-scoped-tools.md) | `GET /api/v1/tools/scoped` | List the tools one user can call, by connection, provider or tool name. | `tools.list_scoped_tools` | `tools.listScopedTools` |
| [List tools available to a user (beta)](https://docs.scalekit.com/agentkit/reference/tools/list-available-tools.md) | `GET /api/v1/tools/available` | List every tool a user's connected accounts can call. | REST only | `tools.listAvailableTools` |
| [Search tools (beta)](https://docs.scalekit.com/agentkit/reference/tools/search-tools.md) | `POST /api/v1/tools:search` | Rank tools by how well they fit a task described in plain language. | `tools.search_tools` | `tools.searchTools` |


## 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.

## List tools

`GET /api/v1/tools`

Lists the tools in your environment, filtered by connection, provider, tool name or a text query. Use it for every tool in the environment; for the tools one user can call, use [List a user's scoped tools](https://docs.scalekit.com/agentkit/reference/tools/list-scoped-tools/). With `filter.summary` set to `true`, the response has only `tool_names`.

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `filter.connected_account_id` | string | No | Connected account ID. Alternative to filter.identifier + filter.connector for directly identifying the connected account whose custom MCP tools should be included. |
| `filter.connector` | string | No | The connection name, as shown in **AgentKit** > **Connections**. |
| `filter.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. |
| `filter.organization_id` | string | No | Organization ID to scope the connected account lookup. |
| `filter.provider` | string | No | The app, such as `GMAIL`. |
| `filter.query` | string | No | Full-text search query to match tools by name or description (e.g., "gmail get attachment"). |
| `filter.summary` | boolean | No | Return only tool names instead of full tool details. |
| `filter.tool_name` | array of string | No | Filter by one or more tool names. |
| `filter.user_id` | string | No | User ID to scope the connected account lookup. |
| `page_size` | integer | No | Maximum number of tools to return per page. |
| `page_token` | string | No | Token from a previous response for pagination. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `next_page_token` | string | Token for fetching the next page of tools. |
| `prev_page_token` | string | Token for fetching the previous page of tools. |
| `tool_names` | array of string | List of tool names, returned when filter.summary is true. |
| `tools` | array of object | List of tools, returned when filter.summary is false or omitted. |
| `tools.definition` | object | Tool definition in structured format. |
| `tools.id` | string | Unique ID of the tool. Immutable and read-only. |
| `tools.is_default` | boolean | Marks this tool as the default version for the combination. Read-only. |
| `tools.metadata` | object | Additional metadata about the tool. |
| `tools.provider` | string | Provider name (e.g. GOOGLE). Read-only. |
| `tools.tags` | array of string | Tags for categorization or filtering. |
| `tools.updated_at` | string | Timestamp when the tool was last updated. Read-only. |
| `total_size` | integer | Total number of tools matching the query. |

**Errors**

- `400`: Invalid request - malformed filter or pagination parameters
- `401`: Authentication required - missing or invalid access token

**Request**

```bash
curl -sS -G -X GET \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/tools" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "filter.connector=gmail" \
  --data-urlencode "filter.summary=true" \
  --data-urlencode "page_size=5"
```

**Response**

```json
{
  "tool_names": [
    "gmail_batch_delete_messages",
    "gmail_batch_modify_messages",
    "gmail_create_draft",
    "gmail_create_filter",
    "gmail_create_label"
  ],
  "next_page_token": "eyJhZnRlciI6InRvbF84NjE0NzQwMzI5MTU4MzMyNyJ9",
  "prev_page_token": "",
  "total_size": 48
}
```

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

Lists the tools in your environment. Pass `connection_name` and `identifier`, or `connected_account_id`, to include the custom MCP tools of that connected account.

```python
scalekit_client.actions.list_tools(
    connection_name: Optional[str] = None,
    identifier: Optional[str] = None,
    provider: Optional[str] = None,
    tool_name: Optional[List[str]] = None,
    query: Optional[str] = None,
    organization_id: Optional[str] = None,
    user_id: Optional[str] = None,
    connected_account_id: Optional[str] = None,
    summary: Optional[bool] = None,
    page_size: Optional[int] = None,
    page_token: Optional[str] = None,
) -> ListToolsResponse
```

Example:

```python
result = scalekit_client.actions.list_tools(
    connection_name="gmail",
    summary=True,
    page_size=5,
)
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `connection_name` | `Optional[str]` | No | The connection name, as shown in **AgentKit** > **Connections**. |
| `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. |
| `provider` | `Optional[str]` | No | The app, such as `GMAIL`. |
| `tool_name` | `Optional[List[str]]` | No | Filter to specific tool names |
| `query` | `Optional[str]` | No | Free-form search query across tool metadata |
| `organization_id` | `Optional[str]` | No | Organization ID to scope the connected-account lookup |
| `user_id` | `Optional[str]` | No | User ID to scope the connected-account lookup |
| `connected_account_id` | `Optional[str]` | No | Direct connected account ID, as an alternative to identifier + connection_name |
| `summary` | `Optional[bool]` | No | Set to `True` to return only tool names, in `tool_names`. |
| `page_size` | `Optional[int]` | No | Maximum number of tools to return per page |
| `page_token` | `Optional[str]` | No | Token from a previous response for pagination |

Returns `ListToolsResponse`: A page of tools, or of tool names with `summary`.

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

Lists the tools in your environment. Pass `connectionName` and `identifier`, or `connectedAccountId`, to include the custom MCP tools of that connected account.

```ts
scalekit.actions.listTools(
  params?: {
    connectionName?: string;
    identifier?: string;
    provider?: string;
    toolName?: string[];
    query?: string;
    organizationId?: string;
    userId?: string;
    connectedAccountId?: string;
    summary?: boolean;
    pageSize?: number;
    pageToken?: string;
  },
): Promise<ListToolsResult>
```

Example:

```ts
const result = await scalekit.actions.listTools({
  connectionName: "gmail",
  summary: true,
  pageSize: 5,
});
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `connectionName` | `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. |
| `provider` | `string` | No | The app, such as `GMAIL`. |
| `toolName` | `string[]` | No | Filter by one or more tool names |
| `query` | `string` | No | Full-text search query to match tools by name or description (e.g., "gmail get attachment") |
| `organizationId` | `string` | No | Organization ID to scope the connected account lookup |
| `userId` | `string` | No | User ID to scope the connected account lookup |
| `connectedAccountId` | `string` | No | Connected account ID. Alternative to filter.identifier + filter.connector for directly identifying the connected account whose custom MCP tools should be included. |
| `summary` | `boolean` | No | Set to `true` to return only tool names, in `toolNames`. |
| `pageSize` | `number` | No | Maximum number of tools to return per page |
| `pageToken` | `string` | No | Token from a previous response for pagination |

Returns `Promise<ListToolsResult>`.

**Used in**

- [Build a Mastra agent with Scalekit AgentKit tools](https://docs.scalekit.com/cookbooks/mastra-agentkit/)
- [Mint session tokens](https://docs.scalekit.com/agentkit/mcp/session-tokens/)

## List a user's scoped tools (beta)

`GET /api/v1/tools/scoped`

This endpoint is in beta. Its request and response may change.

Tools already bound to one connected-account identifier. Use this when you need the list a user or agent is authorized to call (the list you pass to an LLM). `identifier` is required, and so is at least one `filter.*` field (provider, tool name or connection name): without one the API returns `INVALID_ARGUMENT`.

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | string | Yes | 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. |
| `filter.connection_names` | array of string | No | Filter by one or more connection names. |
| `filter.providers` | array of string | No | Filter by one or more tool providers. |
| `filter.tool_names` | array of string | No | Filter by one or more tool names. |
| `page_size` | integer | No | Maximum number of tools to return per page. |
| `page_token` | string | No | Token from a previous response for pagination. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `next_page_token` | string | Token for fetching the next page of tools. |
| `prev_page_token` | string | Token for fetching the previous page of tools. |
| `tools` | array of object | List of tools scoped to the given connected account identifier. |
| `tools.connected_account_id` | string | ID of the connected account for this scoped tool. |
| `tools.identifier` | string | Your app's ID for the user, the value passed when the account was created. |
| `tools.tool` | object | The underlying tool definition. |
| `tools.tool.definition` | object | Tool definition in structured format. |
| `tools.tool.id` | string | Unique ID of the tool. Immutable and read-only. |
| `tools.tool.is_default` | boolean | Marks this tool as the default version for the combination. Read-only. |
| `tools.tool.metadata` | object | Additional metadata about the tool. |
| `tools.tool.provider` | string | Provider name (e.g. GOOGLE). Read-only. |
| `tools.tool.tags` | array of string | Tags for categorization or filtering. |
| `tools.tool.updated_at` | string | Timestamp when the tool was last updated. Read-only. |
| `total_size` | integer | Total number of tools matching the query. |

**Errors**

- `400`: Invalid request - missing identifier or malformed filter/pagination parameters
- `401`: Authentication required - missing or invalid access token

**Request**

```bash
curl -sS -G -X GET \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/tools/scoped" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "identifier=user_123" \
  --data-urlencode "filter.connection_names=gmail" \
  --data-urlencode "page_size=2"
```

**Response**

```json
{
  "tools": [
    {
      "connected_account_id": "ca_24834495392086178",
      "identifier": "user_123",
      "tool": {
        "id": "tol_86147403291582051",
        "provider": "GMAIL",
        "definition": {
          "name": "gmail_fetch_mails",
          "description": "Fetch emails from a connected Gmail account using search filters. Requires a valid Gmail OAuth2 connection.",
          "schema_version": "1",
          "tool_version": "1",
          "input_schema": {
            "type": "object",
            "properties": {
              "query": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Search query string using Gmail's search syntax (e.g., 'is:unread from:user@example.com')"
              },
              "max_results": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Maximum number of emails to fetch"
              }
            }
          }
        },
        "is_default": true,
        "metadata": {},
        "tags": []
      }
    },
    {
      "connected_account_id": "ca_24834495392086178",
      "identifier": "user_123",
      "tool": {
        "id": "tol_86147403291583327",
        "provider": "GMAIL",
        "definition": {
          "name": "gmail_send_message",
          "description": "Send an email message immediately from the authenticated Gmail account. Constructs a MIME message and sends it via the Gmail API.",
          "schema_version": "1",
          "tool_version": "1",
          "input_schema": {
            "type": "object",
            "properties": {
              "to": {
                "type": "string",
                "description": "The recipient email address(es) for the message."
              },
              "subject": {
                "type": "string",
                "description": "The subject line of the email."
              },
              "body": {
                "type": "string",
                "description": "The body content of the email."
              }
            },
            "required": [
              "to",
              "subject",
              "body"
            ]
          }
        },
        "is_default": true,
        "metadata": {},
        "tags": []
      }
    }
  ],
  "next_page_token": "eyJhZnRlciI6InRvbF84NjE0NzQwMzI5MTU4MzMyNyJ9",
  "prev_page_token": "",
  "total_size": 48
}
```

**Python SDK:** `scalekit_client.tools.list_scoped_tools`

Lists the tools a user can call, narrowed by the filter.

```python
scalekit_client.tools.list_scoped_tools(
    identifier: str,
    filter: Optional[ScopedToolFilter] = None,
    page_size: Optional[int] = None,
    page_token: Optional[str] = None,
) -> Tuple[ListScopedToolsResponse, grpc.Call]
```

Example:

```python
page, _ = scalekit_client.tools.list_scoped_tools(
    identifier="user_123",
    filter={"connection_names": ["gmail"]},
    page_size=2,
)
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | `str` | Yes | 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. |
| `filter` | `Optional[ScopedToolFilter]` | Yes | Filter parameters for scoped tools |
| `page_size` | `Optional[int]` | No | Maximum number of tools to return per page |
| `page_token` | `Optional[str]` | No | Token from a previous response for pagination |

Returns `Tuple[ListScopedToolsResponse, grpc.Call]`: The response and the gRPC call. Unpack it as `page, _ = ...`.

**Node.js SDK:** `scalekit.tools.listScopedTools`

Lists tools that are scoped to a specific connected account identifier.

```ts
scalekit.tools.listScopedTools(
  identifier: string,
  options: {
    filter: MessageInitShape<typeof ScopedToolFilterSchema>;
    pageSize?: number;
    pageToken?: string;
  },
): Promise<ListScopedToolsResponse>
```

Example:

```ts
const result = await scalekit.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["gmail"] },
  pageSize: 2,
});
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | `string` | Yes | 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. |
| `filter` | `MessageInitShape<typeof ScopedToolFilterSchema>` | Yes | Filter configuration for scoped tools (providers, tool names, connection names). Required. |
| `pageSize` | `number` | No | Maximum number of tools to return per page. |
| `pageToken` | `string` | No | Token from a previous `listScopedTools` response for pagination. |

Returns `Promise<ListScopedToolsResponse>`.

**Used in**

- [Anthropic](https://docs.scalekit.com/agentkit/examples/anthropic/)
- [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/)
- [Use built-in tools](https://docs.scalekit.com/agentkit/tools/scalekit-optimized-tools/)
- [Vercel AI SDK](https://docs.scalekit.com/agentkit/examples/vercel-ai/)

## List tools available to a user (beta)

`GET /api/v1/tools/available`

This endpoint is in beta. Its request and response may change.

Lists every tool that a user's connected accounts can call, across all their connections. `identifier` is required. To narrow the list to chosen connections, providers or tools, use [List a user's scoped tools](https://docs.scalekit.com/agentkit/reference/tools/list-scoped-tools/).

**Query parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | string | Yes | 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. |
| `page_size` | integer | No | Maximum number of tools to return per page. |
| `page_token` | string | No | Token from a previous response for pagination. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `next_page_token` | string | Token for fetching the next page of tools. |
| `prev_page_token` | string | Token for fetching the previous page of tools. |
| `tools` | array of object | List of tools available for the identifier. |
| `tools.definition` | object | Tool definition in structured format. |
| `tools.id` | string | Unique ID of the tool. Immutable and read-only. |
| `tools.is_default` | boolean | Marks this tool as the default version for the combination. Read-only. |
| `tools.metadata` | object | Additional metadata about the tool. |
| `tools.provider` | string | Provider name (e.g. GOOGLE). Read-only. |
| `tools.tags` | array of string | Tags for categorization or filtering. |
| `tools.updated_at` | string | Timestamp when the tool was last updated. Read-only. |
| `total_size` | integer | Total number of available tools matching the query. |

**Errors**

- `400`: Invalid request - missing or malformed identifier
- `401`: Authentication required - missing or invalid access token
- `404`: Identifier not found

**Request**

```bash
curl -sS -G -X GET \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/tools/available" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "identifier=user_123" \
  --data-urlencode "page_size=2"
```

**Response**

```json
{
  "tools": [
    {
      "id": "tol_86147403291582051",
      "provider": "GMAIL",
      "definition": {
        "name": "gmail_fetch_mails",
        "description": "Fetch emails from a connected Gmail account using search filters. Requires a valid Gmail OAuth2 connection.",
        "schema_version": "1",
        "tool_version": "1",
        "input_schema": {
          "type": "object",
          "properties": {
            "query": {
              "type": [
                "string",
                "null"
              ],
              "description": "Search query string using Gmail's search syntax (e.g., 'is:unread from:user@example.com')"
            },
            "max_results": {
              "type": [
                "integer",
                "null"
              ],
              "description": "Maximum number of emails to fetch"
            }
          }
        }
      },
      "is_default": true,
      "metadata": {},
      "tags": []
    },
    {
      "id": "tol_86147403291583327",
      "provider": "GMAIL",
      "definition": {
        "name": "gmail_send_message",
        "description": "Send an email message immediately from the authenticated Gmail account. Constructs a MIME message and sends it via the Gmail API.",
        "schema_version": "1",
        "tool_version": "1",
        "input_schema": {
          "type": "object",
          "properties": {
            "to": {
              "type": "string",
              "description": "The recipient email address(es) for the message."
            },
            "subject": {
              "type": "string",
              "description": "The subject line of the email."
            },
            "body": {
              "type": "string",
              "description": "The body content of the email."
            }
          },
          "required": [
            "to",
            "subject",
            "body"
          ]
        }
      },
      "is_default": true,
      "metadata": {},
      "tags": []
    }
  ],
  "next_page_token": "eyJhZnRlciI6InRvbF84NjE0NzQwMzI5MTU4MzMyNyJ9",
  "prev_page_token": "",
  "total_size": 48
}
```

**Python:** Call this endpoint over REST, as the example shows.

```python
import os

import requests

env_url = os.environ["SCALEKIT_ENVIRONMENT_URL"]
token = requests.post(
    f"{env_url}/oauth/token",
    data={
        "grant_type": "client_credentials",
        "client_id": os.environ["SCALEKIT_CLIENT_ID"],
        "client_secret": os.environ["SCALEKIT_CLIENT_SECRET"],
    },
).json()["access_token"]

response = requests.get(
    f"{env_url}/api/v1/tools/available",
    headers={"Authorization": f"Bearer {token}"},
    params={"identifier": "user_123", "page_size": 2},
)
response.raise_for_status()
result = response.json()
```

**Node.js SDK:** `scalekit.tools.listAvailableTools`

Lists tools that are available for a specific connected account identifier. Returns every tool the user's connected accounts can call, not only the ones you pass to your agent.

```ts
scalekit.tools.listAvailableTools(
  identifier: string,
  options?: {
    pageSize?: number;
    pageToken?: string;
  },
): Promise<ListAvailableToolsResponse>
```

Example:

```ts
const result = await scalekit.tools.listAvailableTools("user_123", {
  pageSize: 2,
});
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `identifier` | `string` | Yes | 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. |
| `pageSize` | `number` | No | Maximum number of tools to return per page. |
| `pageToken` | `string` | No | Token from a previous `listAvailableTools` response for pagination. |

Returns `Promise<ListAvailableToolsResponse>`.

## Search tools (beta)

`POST /api/v1/tools:search`

This endpoint is in beta. Its request and response may change.

Ranks the tools in your environment against a plain-language query, such as `send an email`, and returns the best matches from every connection. Pass `identifier` to see, for each result, whether that user can call it now: each entry in `connections` has a `readiness_state` of `TOOL_READINESS_STATE_READY`, `TOOL_READINESS_STATE_NEEDS_CONNECTION` (the account exists but isn't active) or `TOOL_READINESS_STATE_NEEDS_REAUTH`. Check it before you [execute the tool](https://docs.scalekit.com/agentkit/reference/tools/execute-a-tool/). An empty `connections` list means the user has no account on any connection for that tool's provider; it isn't an error.

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `query` | string | Yes | Natural-language query or keywords describing the job to be done. Ranked against tool names, descriptions, and providers. 1-256 characters. |
| `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. |
| `top_k` | integer | No | Maximum number of ranked results to return. Defaults to 10, capped at 50. |

**Response (200)**

| Name | Type | Description |
| --- | --- | --- |
| `tools` | array of object | Tools matching the query, ordered by descending relevance score. |
| `tools.connections` | array of object | The connections for this tool's provider where the user has a connected account, each with its own `readiness_state`. Returned only when the request has `identifier`. Empty when the user has no account on any of them. More than one entry means the user has accounts on several connections, such as two Slack workspaces. |
| `tools.connections.connected_account_id` | string | The user's connected account on this connection, whatever its readiness. Pass it to Execute a tool only when `readiness_state` is `TOOL_READINESS_STATE_READY`. |
| `tools.connections.connection_name` | string | Name of this connection. |
| `tools.connections.readiness_state` | string (enum) | Whether this specific connection is usable right now for the supplied identifier, independent of every other connection listed for this provider. One of: `TOOL_READINESS_STATE_READY`, `TOOL_READINESS_STATE_NEEDS_CONNECTION`, `TOOL_READINESS_STATE_NEEDS_REAUTH`. |
| `tools.description` | string | Human-readable description of what the tool does. |
| `tools.name` | string | The tool's name, to pass as `tool_name` when you [execute it](https://docs.scalekit.com/agentkit/reference/tools/execute-a-tool/). |
| `tools.provider` | string | Provider the tool belongs to. |
| `tools.score` | number | Relevance score for this result. Higher is better; comparable only within a single response. |

**Errors**

- `400`: Invalid request - the query is empty or exceeds the maximum length
- `401`: Authentication required - missing or invalid access token

**Request**

```bash
curl -sS -X POST \
  "$SCALEKIT_ENVIRONMENT_URL/api/v1/tools:search" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "send an email",
    "identifier": "user_123",
    "top_k": 5
  }'
```

**Response**

```json
{
  "tools": [
    {
      "name": "gmail_send_message",
      "description": "Send an email message immediately from the authenticated Gmail account. Constructs a MIME message and sends it via the Gmail API.",
      "provider": "GMAIL",
      "score": 0.87,
      "connections": [
        {
          "connection_name": "gmail",
          "connected_account_id": "ca_24834495392086178",
          "readiness_state": "TOOL_READINESS_STATE_READY"
        }
      ]
    },
    {
      "name": "slack_send_message",
      "description": "Send plain text to a Slack channel or DM, optionally in a thread. Returns channel and message timestamp.",
      "provider": "SLACK",
      "score": 0.61,
      "connections": []
    }
  ]
}
```

**Python SDK:** `scalekit_client.tools.search_tools`

Ranks the tools a user can call by how well they match a plain-language query. Each result's `score` is a relevance score where higher is better; it is only comparable within the results of a single response, not across separate calls. `connections` on each result is populated only when `identifier` is set: an empty list means the identifier has no connection at all for that tool's provider (not an error, and different from `NEEDS_CONNECTION`, which means a connected account row exists but is inactive); more than one entry means the identifier has accounts on multiple connections for that provider (for example, two Slack workspaces) -- inspect each entry's own `readiness_state` rather than assuming one answer for the whole tool.

```python
scalekit_client.tools.search_tools(
    query: str,
    identifier: Optional[str] = None,
    top_k: Optional[int] = None,
) -> Tuple[SearchToolsResponse, grpc.Call]
```

Example:

```python
results, _ = scalekit_client.tools.search_tools(
    query="send an email",
    identifier="user_123",
    top_k=5,
)
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `query` | `str` | Yes | Natural-language query or keywords describing the job to be done |
| `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. |
| `top_k` | `Optional[int]` | No | Maximum number of ranked results to return (default 10, capped at 50) |

Returns `Tuple[SearchToolsResponse, grpc.Call]`: The response and the gRPC call. Unpack it as `results, _ = ...`.

**Node.js SDK:** `scalekit.tools.searchTools`

Searches tools ranked by relevance to a natural-language query — the job to be done, not an exact tool name. Each result's `score` is a relevance score where higher is better; it is only comparable within the results of a single response, not across separate calls. Pass `identifier` to also get per-connection readiness (usable now, needs a new connection, or needs re-auth) on each result's `connections`. `connections` is populated only when `identifier` is set: an empty array means the identifier has no connection at all for that tool's provider (not an error, and different from `NEEDS_CONNECTION`, which means a connected-account row exists but is inactive); more than one entry means the identifier has accounts on multiple connections for that provider (for example, two Slack workspaces) — inspect each entry's own `readinessState` rather than assuming one answer for the whole tool.

```ts
scalekit.tools.searchTools(
  query: string,
  options?: {
    identifier?: string;
    topK?: number;
  },
): Promise<SearchToolsResponse>
```

Example:

```ts
const result = await scalekit.tools.searchTools("send an email", {
  identifier: "user_123",
  topK: 5,
});
```

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `query` | `string` | Yes | Natural-language query or keywords describing the job to be done. 1-256 characters. |
| `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. |
| `topK` | `number` | No | Maximum number of ranked results to return. Defaults to 10, capped at 50. |

Returns `Promise<SearchToolsResponse>`.

**Used in**

- [Use built-in tools](https://docs.scalekit.com/agentkit/tools/scalekit-optimized-tools/)


---

## 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 |
