Skip to content

fix: Hermes agent cache token-mismatch#581

Open
vestigecounty wants to merge 1 commit into
antirez:mainfrom
vestigecounty:fix/thinking-visible-tool-cache
Open

fix: Hermes agent cache token-mismatch#581
vestigecounty wants to merge 1 commit into
antirez:mainfrom
vestigecounty:fix/thinking-visible-tool-cache

Conversation

@vestigecounty

Copy link
Copy Markdown

This fixes some of the continuous cache misses when using with the Hermes agent.

NOT fixed:

  • title generation cache thrashing - the workaround is to turn it off with auxiliary.title_generation.enabled: false
  • concurrent children - turn off with delegation.max_concurrent_children: 1, delegation.max_async_children: 1

Reuse live KV across thinking tool-call turns (thinking-visible)

A thinking model that emits tool calls (or a final answer) leaves its hidden reasoning in the live KV, but the next request re-renders that turn with an empty because clients replay the tool-call bytes without the reasoning. The live checkpoint therefore diverged from the next prompt at the first reasoning token, so every follow-up turn missed the cache (memory_miss_reason token-mismatch, cached_tokens 0) and re-prefilled the whole conversation.

Remember a reasoning-stripped visible key for the live frontier after a tool-call turn (both the exact-DSML-replay and canonicalize paths) and after a tools-enabled thinking final answer, mirroring the existing tool-less thinking_live mechanism. thinking_live_visible_prefix_prompt then reuses the verbatim live KV while tokenizing only the new suffix.

The final-answer path deliberately does not gate on prompt_preserves_reasoning: that flag is really "history uses tools" (always true for the agent workload) and would disable the path entirely. Reuse stays gated by an exact byte-prefix match, so a client that genuinely replays reasoning simply no-ops.

Adds server unit tests covering the tool-call and final-answer reasoning-stripped roundtrips and the build_tool_checkpoint_suffix empty-reasoning contract.

A thinking model that emits tool calls (or a final answer) leaves its
hidden <think> reasoning in the live KV, but the next request re-renders
that turn with an empty <think></think> because clients replay the
tool-call bytes without the reasoning. The live checkpoint therefore
diverged from the next prompt at the first reasoning token, so every
follow-up turn missed the cache (memory_miss_reason token-mismatch,
cached_tokens 0) and re-prefilled the whole conversation.

Remember a reasoning-stripped visible key for the live frontier after a
tool-call turn (both the exact-DSML-replay and canonicalize paths) and
after a tools-enabled thinking final answer, mirroring the existing
tool-less thinking_live mechanism. thinking_live_visible_prefix_prompt
then reuses the verbatim live KV while tokenizing only the new suffix.

The final-answer path deliberately does not gate on
prompt_preserves_reasoning: that flag is really "history uses tools"
(always true for the agent workload) and would disable the path
entirely. Reuse stays gated by an exact byte-prefix match, so a client
that genuinely replays reasoning simply no-ops.

Adds server unit tests covering the tool-call and final-answer
reasoning-stripped roundtrips and the build_tool_checkpoint_suffix
empty-reasoning contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant