fix(cache): content-address prompt_cache_key so recurring cron jobs reuse the warm prefix - #52295
Merged
Merged
Conversation
…euse the warm prefix Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes #51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-attribute |
2 |
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`
run_agent.py:2984: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`
✅ Fixed issues (1):
| Rule | Count |
|---|---|
invalid-assignment |
1 |
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`
Unchanged: 5940 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
tonydwb
approved these changes
Jun 25, 2026
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved
Clean fix for content-addressed prompt cache key in cron jobs. The solution correctly hashes the static prefix (instructions + tools) to produce a stable cache key across fires, while preserving session_id for transcript isolation. Good test coverage.
Changes:
agent/transports/codex.py: New_content_cache_keyfunction, updatedbuild_kwargsto use content-addressed keytests/agent/transports/test_codex_transport.py: Updated tests for new cache key behavior
Well-documented with clear before/after table. LGTM.
Reviewed by Hermes Agent
This was referenced Jun 25, 2026
This was referenced Jun 27, 2026
pai-scaffolde
pushed a commit
to pai-scaffolde/hermes-agent
that referenced
this pull request
Jun 28, 2026
…euse the warm prefix (NousResearch#52295) Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes NousResearch#51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
teddyjfpender
added a commit
to teddyjfpender/superforecasting-agent
that referenced
this pull request
Jun 30, 2026
…the warm prefix Port of NousResearch/hermes-agent 7a65800 (NousResearch#52295). Every cron fire (cron_{job}_{ts}) and parallel quorum panelist got a unique session_id prompt_cache_key, defeating provider prefix-cache reuse of the large static soul/protocol/tool prefix. Now the key is _content_cache_key(instructions, tools) = pck_<sha256[:24]> so runs sharing the prefix warm each other (xAI extra_body path too); codex-backend headers keep session_id for per-fire identity. 52 codex-transport tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
waefrebeorn
pushed a commit
to waefrebeorn/slermes
that referenced
this pull request
Jul 2, 2026
…euse the warm prefix (NousResearch#52295) Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes NousResearch#51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
habarmc1223-sudo
pushed a commit
to habarmc1223-sudo/hermes-agent-fluxmem
that referenced
this pull request
Jul 8, 2026
…euse the warm prefix (NousResearch#52295) Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes NousResearch#51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
This was referenced Jul 11, 2026
Codex/ChatGPT backend rejects requests when session_id > 64 chars (prompt_cache_key HTTP 400)
#62063
Closed
santhreal
pushed a commit
to santhreal/hermes-agent
that referenced
this pull request
Jul 13, 2026
…euse the warm prefix (NousResearch#52295) Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes NousResearch#51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
…euse the warm prefix (NousResearch#52295) Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes NousResearch#51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
5 tasks
JoaoMarcos44
added a commit
to JoaoMarcos44/hermes-agent
that referenced
this pull request
Aug 5, 2026
…ing key Nous Portal and OpenRouter provider profiles pin every turn of a session to the same upstream endpoint (body["session_id"]) so Anthropic/Vertex/Bedrock cache_control breakpoints stay warm. That key came straight from get_conversation_context() or session_id with no normalization, so cron re-fires (cron_<job_id>_<timestamp>, no parent_session_id to walk) got a fresh key every run and never pinned to the same endpoint -- the same NousResearch#51395/NousResearch#52295 class of bug the original prompt_cache_key fix addressed, just on a route NousResearch#78959 didn't touch. Reuses _cache_scope_from_session_id() (no new logic) and leaves the Portal's conversation= analytics tag and the xAI x-grok-conv-id header untouched, since those need per-fire identity, not cache affinity.
leewenjie
pushed a commit
to leewenjie/hermes-agent
that referenced
this pull request
Aug 7, 2026
…euse the warm prefix (NousResearch#52295) Recurring cron jobs were prompt-cache-cold on every fire. session_id is built as cron_<job_id>_<timestamp>, and the Codex/Responses transport used session_id directly as prompt_cache_key — so the timestamp changed the cache key on every run and the static prefix (agent identity + tool schemas) was re-paid each tick. Derive prompt_cache_key from a SHA-256 of the static prefix (instructions + sorted tool schemas) instead. Repeated fires of the same job share one content-addressed key (pck_<hash>) and reuse the warm prefix within the provider's cache TTL. The key changes exactly when the prefix changes — edit the job's prompt or toolset and it re-keys; leave it alone and it stays stable. session_id is left untouched for transcript isolation, log correlation, and the Codex/xAI session-scope routing headers (session_id, x-client-request-id, x-grok-conv-id) — those are the per-fire identity, not the cache key. Only the prompt_cache_key body field (standard OpenAI/Codex path and the xAI extra_body field) is content-addressed. Closes NousResearch#51395. Co-authored-by: spiky02plateau <spiky02plateau@users.noreply.github.com> Co-authored-by: JoaoMarcos44 <JoaoMarcos44@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Recurring cron jobs now share one stable, content-addressed
prompt_cache_keyacross fires instead of going cache-cold every tick.Root cause: cron builds
session_idascron_<job_id>_<timestamp>, and the Codex/Responses transport usedsession_iddirectly asprompt_cache_key. The timestamp changed the key on every fire, so the static prefix (agent identity + tool schemas) was re-tokenised cold each run. Closes #51395.Changes
agent/transports/codex.py: new_content_cache_key(instructions, tools)returningpck_<sha256[:24]>of the static prefix (tools sorted by name;\x00separator avoids instruction/tool boundary collisions).prompt_cache_key(standard body field + xAIextra_body) now uses it, falling back tosession_idonly when there is no static content.session_idis unchanged for transcript isolation, logs, and the session-scope routing headers (session_id/x-client-request-id/x-grok-conv-id) — those keep their per-fire identity. Only the cache key is content-addressed.Scope note
This is the minimal version. The cache key is a routing hint, never a correctness boundary — a stale/shared key can only cause a miss, never a wrong result. The win is real but bounded by provider cache TTL (~5-60 min), so it primarily helps sub-TTL-interval jobs; longer cadences are cold by the next fire regardless. Kept deliberately small for that reason.
Validation
pck_key, warmsession_idsession_idsession_id(unchanged)E2E-verified with real transport imports;
tests/agent/transports/test_codex_transport.py60/60 green.Credit
Closes the cluster on #51395. Fix scoped by @spiky02plateau (#51396, issue author); content-hash key naming from @JoaoMarcos44 (#51585). Both credited as co-authors.
Infographic