Skip to content

Own tool-call dialect recovery in the proxy for self-hosted backends — 91% of fleet tool-call leaks are nimbus; OpenRouter/Anthropic are clean #95

Description

@cboettig

Re-sliced the S3 request/response logs by provider (the design-doc analysis in geo-agent#300 cut it by model, which is a confound — a model served on only one route is really measuring that route's parser). July corpus, ~26k responses. Leak = has_tool_calls=false but assistant content carries a tool-call marker (<tool_call, <function=, <invoke, <model_calls, <tool_code, <parameter[ =]).

provider tool attempts leaked rate
nimbus 8,487 180 2.12%
nrp 12,338 16 0.13%
openrouter 2,332 2 0.09%
anthropic 144 0 0.00%

Same model, different route (proves it's the parser, not the model): qwen 2.4% on nimbus vs 0.6% on nrp; glm-5.2 0/1038 on OpenRouter; glm-5 0/1950 on nrp.

Conclusion: every route that leaks (nimbus, nrp) passes through this proxy; every route that's clean (OpenRouter, Anthropic) does its own dialect→tool_calls normalization. Nimbus can't be fixed further at the vLLM layer (qwen3_xml_patched is already patched ahead of the model-card recipe; the ~2% is the inherent single-parser limit for a model that emits both XML and Hermes-JSON shapes). So recovery must live downstream of the parser — here, not in the geo-agent harness where it can't help any other client.

Proposal: add a response-normalization step for the self-hosted backends (nimbus, nrp) that lifts the buffered assistant content into tool_calls when the parser missed it — porting geo-agent's parseEmbeddedToolCalls/_normalizeCall logic (non-streaming; the message is fully buffered), optionally backed by jsonrepair + dialect-extraction from @ai-sdk-tool/parser. Leave OpenRouter/Anthropic pass-through untouched. Keep logging the raw provider response alongside the normalized one so the leak rate stays measurable and we can prove the harness net has gone quiet before geo-agent removes it.

Sequencing (not a one-shot): this proxy change lands → verify the leak rate drops in the logs → then a geo-agent PR trims parseEmbeddedToolCalls to a thin tail-catch (the ~0.1% residual on clean routes + BYO apps pointed straight at a raw vLLM endpoint that bypass this proxy).

Refs: geo-agent#300, geo-agent docs/design/tool-call-parsing.md, closed #85.

Measurement is reproducible: ./sync-logs.sh then group the leak predicate above by the provider column over consolidated/**/*.parquet.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions