# Tool Testing

The tool testing endpoints let you execute and inspect context graph tools (world tools, skills, integrations) from the Developer Console or API without making a phone call. This is useful during development for verifying tool behavior, debugging input/output schemas, and validating write operations before wiring tools into a live conversation flow.

{% hint style="warning" %}
**Admin/owner only** - Tool testing requires the `tools:test` scope, which is restricted to admin and owner roles.
{% endhint %}

{% @mermaid/diagram content="%%{init: {"flowchart": {"useMaxWidth": true, "nodeSpacing": 20, "rankSpacing": 30}, "theme": "base", "themeVariables": {"primaryColor": "#D4E2E7", "primaryTextColor": "#100F0F", "primaryBorderColor": "#083241", "lineColor": "#575452", "textColor": "#100F0F", "clusterBkg": "#F1EAE7", "clusterBorder": "#D7D2D0"}}}%%
flowchart LR
R\[Resolve tools<br/>for service] --> S\[Select tool &<br/>provide inputs]
S --> E\[Execute tool<br/>source=tool\_test]
E -->|dry\_run=true| D\[Simulate only<br/>no persistence]
E -->|dry\_run=false| W\[Write with<br/>source isolation]
D --> V\[Inspect result<br/>+ sub-tool logs]
W --> V

```
style R fill:#D4E2E7,stroke:#083241,color:#100F0F,stroke-width:2px
style S fill:#D4E2E7,stroke:#083241,color:#100F0F,stroke-width:2px
style E fill:#F0DDD9,stroke:#AA412A,color:#100F0F,stroke-width:2px
style D fill:#DDE3DB,stroke:#2c3827,color:#100F0F,stroke-width:2px
style W fill:#DDE3DB,stroke:#2c3827,color:#100F0F,stroke-width:2px
style V fill:#E8E2EB,stroke:#C5BACE,color:#100F0F,stroke-width:2px" %}
```

## Safety Guardrails

Tool test executions are isolated from production side effects:

* **Source isolation** - All writes are tagged `source="tool_test"`, which is excluded from the outbound sync allowlist. No real EHR syncs or SMS deliveries happen.
* **Surface delivery blocking** - Surfaces created during tool tests are blocked from delivery.
* **Dry run mode** - Write tools can simulate execution without persisting results.

## Resolve Available Tools

Retrieve the full list of tools available for a given service, including their input schemas, types, tiers, and write classification.

|            |                                                          |
| ---------- | -------------------------------------------------------- |
| **Method** | `GET`                                                    |
| **Path**   | `/v1/{workspace_id}/services/{service_id}/tools/resolve` |
| **Auth**   | Workspace API key (admin/owner)                          |

### Response

Returns a `ToolResolveResponse` with the list of resolved tools:

| Field                  | Type    | Description                                                 |
| ---------------------- | ------- | ----------------------------------------------------------- |
| `tools`                | array   | List of resolved tool definitions                           |
| `tools[].tool_name`    | string  | Fully qualified tool name                                   |
| `tools[].tool_type`    | string  | `world_tool`, `skill`, or `integration`                     |
| `tools[].description`  | string  | Human-readable description                                  |
| `tools[].input_schema` | object  | JSON Schema for the tool's input parameters                 |
| `tools[].states`       | array   | Context graph states where this tool is available           |
| `tools[].tier`         | string  | Execution tier: `world`, `companion`, `direct`, or `lambda` |
| `tools[].is_write`     | boolean | Whether this tool performs write operations                 |

## Execute a Tool

Execute a single tool in isolation with custom input parameters.

|            |                                    |
| ---------- | ---------------------------------- |
| **Method** | `POST`                             |
| **Path**   | `/v1/{workspace_id}/tools/execute` |
| **Auth**   | Workspace API key (admin/owner)    |

### Request Body

| Field          | Type    | Required | Description                                         |
| -------------- | ------- | -------- | --------------------------------------------------- |
| `tool_type`    | string  | Yes      | `world_tool`, `skill`, or `integration`             |
| `tool_name`    | string  | Yes      | Fully qualified tool name (from resolve response)   |
| `service_id`   | string  | Yes      | Service ID that owns the context graph              |
| `input_params` | object  | No       | Parameters to pass to the tool handler              |
| `entity_id`    | string  | No       | Entity ID for world model context                   |
| `dry_run`      | boolean | No       | If `true`, write tools simulate without persistence |

### Response

| Field                         | Type           | Description                                                                    |
| ----------------------------- | -------------- | ------------------------------------------------------------------------------ |
| `result`                      | any            | Tool execution output                                                          |
| `duration_ms`                 | number         | Execution time in milliseconds                                                 |
| `dry_run`                     | boolean        | Whether this was a dry run                                                     |
| `source`                      | string         | Always `"tool_test"`                                                           |
| `tool_type`                   | string         | Echo of the requested tool type                                                |
| `tier`                        | string         | Execution tier used                                                            |
| `sub_tool_logs`               | array          | Log of any sub-tool calls made during execution                                |
| `sub_tool_logs[].tool_name`   | string         | Sub-tool name                                                                  |
| `sub_tool_logs[].input`       | object         | Input passed to sub-tool                                                       |
| `sub_tool_logs[].output`      | string         | Sub-tool output                                                                |
| `sub_tool_logs[].duration_ms` | number         | Sub-tool execution time                                                        |
| `sub_tool_logs[].succeeded`   | boolean        | Whether the sub-tool succeeded                                                 |
| `blocked_side_effects`        | array          | List of side effects that were blocked (e.g., surface delivery, outbound sync) |
| `error`                       | string or null | Error message if execution failed                                              |

### Routing

The execute endpoint routes differently by tool type:

* **Skills** are executed in-process via the skill test executor
* **World tools** and **integrations** are proxied to the voice agent's internal execution endpoint

{% hint style="info" %}
**Rate limited** - Tool execute is subject to write rate limits. Use resolve to inspect tools before executing.
{% endhint %}
