> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runtools.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Execute Tool

> Execute one Tool Hub action

Tool execution endpoints use:

```text theme={null}
https://tools.runtools.ai/v1
```

## Path Parameters

<ParamField path="slug" type="string" required>
  Tool slug.
</ParamField>

## Request Body

<ParamField body="action" type="string" required>
  Tool action name.
</ParamField>

<ParamField body="params" type="object">
  Action parameters.
</ParamField>

<ParamField body="credentialScope" type="string">
  Optional credential isolation mode. Use `end_user` with `endUser` for customer-owned product integrations. In end-user mode, Tool Hub never uses per-request, installed, org, or builder credentials.
</ParamField>

<ParamField body="credentials" type="object">
  Optional per-request credentials. Prefer stored secrets or OAuth connections for production.
</ParamField>

<ParamField body="credentialOverrides" type="object">
  Map tool credential field names to secret names so values stay server-side.
</ParamField>

`credentials` and `credentialOverrides` are accepted only on direct Tool Hub API/SDK calls. Agent-runtime tool calls use an internal signed capability and cannot provide credential fields in request JSON.

<ParamField body="oauth" type="object">
  Optional account selector for OAuth-backed tools. Use `oauth.account` for a human-readable email, username, display name, provider account ID, or connection ID. Use `oauth.connectionId` when you need an exact Connected Apps connection.
</ParamField>

<ParamField body="endUser" type="object">
  App-scoped customer identity for Hosted Connect. Requires `endUser.appId` and `endUser.externalUserId`. When present, `credentialScope` is treated as `end_user`.
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Whether execution succeeded.
</ResponseField>

<ResponseField name="result" type="object">
  Tool-specific result when successful.
</ResponseField>

<ResponseField name="error" type="object">
  Tool-specific error when unsuccessful. Tool failures can return a non-2xx HTTP status.
</ResponseField>

<ResponseField name="durationMs" type="number">
  Server-side execution duration.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://tools.runtools.ai/v1/tools/github/execute \
    -H "X-API-Key: $RUNTOOLS_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "action": "list_repos",
      "params": {
        "owner": "runtools-ai"
      }
    }'
  ```

  ```typescript SDK theme={null}
  const result = await rt.tools.execute('github', {
    action: 'list_repos',
    params: {
      owner: 'runtools-ai',
    },
    oauth: {
      account: 'alfo19972',
    },
  });
  ```

  ```typescript Secret override theme={null}
  const result = await rt.tools.execute('custom-crm', {
    action: 'lookup_customer',
    params: { email: 'person@example.com' },
    credentialOverrides: {
      apiKey: 'CRM_API_KEY',
    },
  });
  ```

  ```typescript Hosted Connect theme={null}
  const result = await rt.tools.execute('gmail', {
    action: 'list_emails',
    params: { max_results: 10 },
    credentialScope: 'end_user',
    endUser: {
      appId: 'atlas',
      externalUserId: 'customer_123',
    },
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "data": {
      "success": true,
      "result": {
        "repositories": []
      },
      "durationMs": 418
    }
  }
  ```

  ```json 500 Internal Server Error theme={null}
  {
    "data": {
      "success": false,
      "error": {
        "code": "execution_error",
        "message": "Provider request failed"
      },
      "durationMs": 292
    }
  }
  ```
</ResponseExample>

<Note>
  Tool calls are billed before execution. If the organization does not have enough credits, the endpoint returns `402 insufficient_credits`. If billing is temporarily unavailable, it returns `503 billing_unavailable`.
</Note>

## Credential Resolution

For org-scoped tool execution, RunTools resolves credentials in this order:

1. Per-request `credentials`
2. `credentialOverrides` that point at stored secrets
3. Stored credentials for the installed tool
4. Matching organization or user secrets
5. Connected OAuth account when the tool declares an OAuth provider

If more than one provider account is connected, the default connection is used unless the request includes `oauth.account` or `oauth.connectionId`.

For end-user execution, RunTools resolves credentials only from the matching Hosted Connect scope:

```text theme={null}
builder org + appId + externalUserId + tool
```

If no matching end-user connection exists, the endpoint returns `409 connect_required`. It does not fall back to builder credentials, org secrets, installed-tool credentials, or another product user's connection.
