Skip to content

[BUG] Tool name resolution fails on anthropic_messages requests from custom agents — exclude_tools becomes a no-op; TOIN keys all unknown|unknown #1822

Description

@jimvetter

Summary

On Headroom 0.28.0 (also reproduced on 0.25.0), Hermes agent traffic using the anthropic_messages transport through the Z.ai GLM proxy (:8788) does not resolve tool names for compression routing or TOIN learning. Every pattern in ~/.headroom/toin.json is keyed unknown|unknown|<hash>.

0.28.0 boundary (most useful isolation for maintainers): native Hermes tool exclusion works for built-in tools — proxy logs show router:excluded:tool on read_file and terminal, and the model receives those outputs verbatim. MCP tool results still bypass exclusion (e.g. mcp_CursorTaskRegistry_cursor_list_tasks compressed to ccr: markers). TOIN / name-resolution is unchanged — all 112 patterns remain unknown|unknown|<hash> before and after 0.28.0 tests. So the fix is partial: content-router native-tool path vs MCP anthropic_messages tool path are not aligned.

prefix_cache on :8788 shows zero lifetime cache_read_tokens.

Environment

Item Value
Headroom 0.28.0 (headroom-ai[proxy], macOS arm64, Python 3.13 venv)
Proxy headroom proxy --port 8788 --anthropic-api-url https://api.z.ai/api/anthropic
Client Hermes Agent CLI (hermes -z ... --provider headroom-zai -m glm-5.2)
Transport anthropic_messages (not Claude Code CLI)
Env HEADROOM_EXCLUDE_TOOLS=headroom_retrieve,mcp_HeadroomZai_headroom_retrieve,mcp_Headroom_headroom_retrieve,terminal,execute_code,read_file,search_files

Reproduction

  1. Install headroom-ai[proxy]==0.28.0, start Z.ai proxy on :8788 with exclusions above.
  2. Run Hermes one-shot against headroom-zai / glm-5.2 with file + terminal + MCP tools.
  3. Inspect ~/.headroom/toin.json pattern keys and proxy PERF lines.

Observed (2026-07-03 WS8 session)

0.28.0 vs 0.25.0 — native tools fixed, MCP + TOIN not:

Path 0.25.0 0.28.0
read_file / terminal (native) Compressed despite HEADROOM_EXCLUDE_TOOLS Excluded — router:excluded:tool in proxy log; verbatim to model
MCP tools (e.g. cursor_list_tasks) Compressed to ccr: Still compressed to ccr:
TOIN pattern keys unknown|unknown (112/112) Unchanged unknown|unknown (112/112)

read_file + terminal (0.28.0 pass): Proxy log shows exclusions honored:

content_router: 5 msgs — 3 excluded (Read/Glob), ...
transforms=router:excluded:tool*3

Agent received first line of SOUL.md verbatim (# Pepper — Jim Vetter's Personal Operating Agent) and terminal integer 234 with no ccr: markers.

MCP (fail): cursor_list_tasks result contained compressed summary:

"summary":"<<ccr:888241e845ce,string,603B>>"

TOIN (fail): 112/112 patterns keyed unknown|unknown|<hash> before and after test; no new named keys.

prefix_cache (fail): /stats on :8788 after test:

"prefix_cache": {
  "totals": {
    "cache_read_tokens": 0,
    "requests": 0,
    "hit_rate": 0
  }
}

Proxy PERF lines for GLM requests show cache_read=0 cache_write=0.

Expected

  1. Tool names from Hermes anthropic_messages tool_use blocks resolve to real names (e.g. read_file, mcp_CursorTaskRegistry_cursor_list_tasks) for TOIN keys and HEADROOM_EXCLUDE_TOOLS — including MCP-prefixed names, not only native read_file/terminal.
  2. Excluded tools never emit ccr: markers to the model — same rule for native and MCP tool results.
  3. Stable prefixes on Z.ai path accumulate nonzero cache_read when tool results are not compressed away.

Impact

Custom agents (Hermes, Pepper) on metered GLM cannot use Headroom safely: small outputs may pass, but MCP JSON blobs compress and trigger headroom_retrieve doom loops. Workaround in production: bypass Headroom on GLM lane (zai-glm direct to api.z.ai); keep Headroom only on Sonnet escalation (:8787).

Evidence files (local)

  • Registry task fcbca026 incident log (Fable Window Plan)
  • Proxy log excerpts: ~/.headroom/logs/proxy.log (2026-07-03 18:14–18:15 PT)
  • Test transcripts: /tmp/ws8_headroom_glm_test.log, /tmp/ws8_headroom_mcp_test.log
  • TOIN snapshot: ~/.headroom/toin.json.bak.20260703_pre028

Notes

  • HEADROOM_EXCLUDE_TOOLS is a supported env var (_parse_exclude_tools in proxy); the failure is upstream of exclusion matching.
  • Sonnet lane on :8787 at 0.28.0 passes basic smoke (headroom-claude / claude-sonnet-5 → OK).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions