Each AI Agent tool row has a handler_kind and handler_config JSON object. The dispatcher (ai_agent_tool_dispatch.py) executes tools during LLM turns — Playground, evals, and public embed all use the same path.
Tools created before handler support default to handler_kind "noop" and return a stub note until you wire a real handler on the Tools tab.
Studio UI
- Open /app/agents/{slug}/tools.
- Expand Handler on a tool row.
- Choose handler kind and edit JSON config (templates provided per kind).
- Save handler — PATCH /v1/ai-agents/{slug}/tools/{tool_id}.
- Test dispatch — POST .../tools/{tool_id}/test with JSON tool_args (does not call the LLM).
Handler kinds
| Kind | Use case | Required config |
|---|---|---|
| noop | Placeholder / dev | {} |
| http_post | REST call with JSON body = tool_args | url; optional method (POST/PUT/PATCH), headers, timeout_seconds, max_retries |
| webhook | Signed outbound POST (HMAC-SHA256) | url; signing_secret or secret (supports {{secret:NAME}}); optional method, headers |
| python_callable | In-process function | module_path as package.module:function_name |
Secrets in handler config
Use {{secret:NAME}} anywhere in handler_config (URL, headers, signing_secret). Values resolve from the workspace encrypted secret store (GET/POST /v1/secrets) — never returned by the API after write.
{
"url": "https://api.bank.com/v1/balance",
"headers": { "Authorization": "Bearer {{secret:CORE_API_KEY}}" },
"timeout_seconds": 15
}Webhook signing
When signing_secret (or secret) is set, Convoship sends header X-Convoship-Signature: sha256=<hex> over the raw JSON body {"tool":"...","args":{...}}. Verify on your receiver with the same secret.
Runtime behavior
- Task allowlist — only tools listed on the matched Task are sent to the LLM schema.
- SENSITIVE tools require an active AUTH guardrail on the agent.
- Failures return ok: false to the model with error detail — dispatch never raises HTTP 500.
- Retries — http_post/webhook honor max_retries in config (default 1).
- Trace — tool events in playground/public traces show name, args, output, duration_ms.
API
PATCH /v1/ai-agents/{slug}/tools/{tool_id}
{ "handler_kind": "http_post", "handler_config": { ... } }
POST /v1/ai-agents/{slug}/tools/{tool_id}/test
{ "tool_args": { "account_id": "123" } }