Proxyd host-tools policy

You asked for Fable. The bridge was up. The ROUTE banner still walked you to Grok. That is the host-tools bouncer doing its job too carefully — or the wrong job with a frozen guest list.
Some seats run tools inside the backend (Claude Max CLI on :3456, Gemini AGY on :6543). Others return tool_use / tool_calls for the calling harness to execute (Grok OAuth :4200, OpenRouter, cathedral). Mixing those up is worse than an outage: Max will 200 with confabulated tool narratives and never fall through the ladder (Prime Agent ipython, 2026-08-05).
Detection
Section titled “Detection”A seat is host-tools when:
host_tools: trueinconfig.yaml, orapi_basecontains:3456or:6543(seeModelEntry::is_host_tools_seat)
Grok :4200 is intentionally not host-tools — it returns real tool calls.
Classification (foreign_client_tools)
Section titled “Classification (foreign_client_tools)”Implemented in services/sanctum-proxy/src/translate.rs. Non-empty foreign set → skip every host-tools seat for that attempt and continue the fallback chain.
Host-safe (stay on Max/Fable when requested):
- Anthropic server tools (
bash*,text_editor*,computer*— lowercase prefixes) - MCP tools hosted by the CLI (
mcp__…) - Claude Code built-ins by shape: PascalCase alphanumeric (
Bash,TaskCreate,WebFetch, …) - Small legacy alias set (
bash,str_replace_editor,str_replace_based_edit_tool)
Foreign (divert):
- Explicit denylist:
ipython,python_repl,code_interpreter - Other non-Pascal / snake_case custom names (
my_custom_tool)
Always divert host-tools seats:
- Request header
x-sanctum-tool-owner: client(Prime Agent and custom harnesses)
Operator signals
Section titled “Operator signals”| Header / banner | Meaning |
|---|---|
x-sanctum-seated: claude-fable-5 | Primary (or resolved) seat won |
x-sanctum-route: diverted | Seated ≠ requested |
x-sanctum-route-chain: a > b > c | Ladder walked |
[sanctum-proxy] ROUTE requested → seated (…) | Same divert, in the content stream (fresh user prompts only) |
If the bouncer is wrong, you fix the shape rule — not the seat. If the bouncer is right, you stop blaming Max for a tool that was never allowed through the rope. The clipboard at the door is policy; the ROUTE banner is just the stamp it leaves on the transcript.
Related
Section titled “Related”- Proxyd budget.yaml — USD pool and green/red banners
- Fallback continuity — chain order and context fit
- Config live path:
~/.sanctum/sanctum-proxy/config.yaml(host_tools: trueon Max seats) - 2026-08-07 — Two Dials, One Bridge — when the ROUTE was a queue, not host-tools