Developer guide
Governing tool calls
The four decisions, approval polling, run correlation and fail-modes.
Governing tool calls
When your agent asks the gateway about a tool call, it gets back one of four decisions. This page explains each one, how to group calls into a run and how failures are handled.
The four decisions
| Decision | What it means and what to do |
|---|---|
| allow | The call passed all checks. Run the tool. |
| deny | A guardrail blocked the call. Do not run the tool. The response includes a reason. |
| approval_required | A human must approve first. The response includes an approval id and a poll endpoint. Wait for approval, then retry. |
| rate_limited | The agent key went over its per-minute limit. Back off and retry later. |
Handling approval
When the decision is approval_required, the gateway has created a request for a human to approve or deny. Poll the status endpoint until you get a final answer.
json
{
"decision": "approval_required",
"approval_id": 42,
"poll_endpoint": "/v1/mcp/approvals/42/status",
"expires_at": "2026-04-20T15:30:00+00:00"
}- Call GET /v1/mcp/approvals/{approval_id}/status with your agent key.
- When the status is approved, run the tool.
- When the status is denied, do not run it.
- When the status is expired, the window passed with no decision; treat it as a block.
On the MCP proxy path the same information comes back as a JSON-RPC error with code -32001, carrying the approval id, poll endpoint and expiry in error.data.
Grouping calls into a run
A run groups one turn of work: the model calls and the tool calls that belong together. They are tied by a shared run id.
- Tool calls: The native hook reuses the agent session id it already sends, so tool calls are grouped automatically.
- Model calls: Send the same id on your model requests using the header x-vw-agent-run-id. The aliases x-session-id and helicone-session-id are also accepted.
Use the same id on every call
A turn only groups correctly when the agent sends the same run id on every call, including sub-calls. A call with no id is still checked and logged; it just will not appear inside a run.
Failures and fail-modes
- Gateway unreachable: With VW_FAIL_MODE=open (the default) the call runs anyway, so an outage never blocks your agent. Set it to closed to block instead.
- Approval timed out: Controlled by VW_APPROVAL_FAIL_MODE (default closed, which blocks). Set it to open to allow on timeout.
- Rate limited: Follows VW_FAIL_MODE. The call is an infra outcome, not a policy block.
PreviousConnect any agent
NextAPI reference