perf: improve prompt-prefix caching for the agentic model#100
Open
DavertMik wants to merge 1 commit into
Open
Conversation
Planner and Pilot ran at a 9% prompt cache rate while the default-model agents sat at 75%. The gap was three missing properties: a stable byte-identical prefix, an unchanging tool list, and append-only history. - Pilot: system, verdict and reset prompts now open with their static bodies and close with the per-test task block. Extract buildTaskContext() for the dynamic part; drop the request type from the verdict opener since the user message already carries it. - Pilot: always send the same tool set and gate it with toolChoice 'auto'/'none' instead of flipping the tool list between calls, which invalidated the whole conversation's cache. - Pilot: stop rewriting history via cleanupTag. Pilot conversations are light by design; the trimmed KBs cost more re-tokenized than they save. - Planner: order messages system -> static rules -> static output format -> page research -> approach + URL context, so re-plans of the same page reuse the research prefix. - Route the click disambiguator off the agentic model: ~350-token one-shot prompts can never cache and don't need the expensive model. Prompts are reordered, not rewritten. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Explorbot Self-RegressionCommit
Attempt details
Session analysis — basic (native): Session AnalysisThe Issues module core functionality is operational: creating, searching, viewing details, and filtering issues by label or status all work as expected. An automation sequencing issue in one test did not prevent successful verification. Coverage
What works
Execution Issues
|
DenysKuchma
approved these changes
Jul 17, 2026
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.
Implements
plans/025-agentic-prompt-prefix-caching.md.Problem
In a recent session the two models diverged sharply on prompt cache reuse:
The 66-point gap is exactly the three properties the default-model agents already have and the agentic ones lacked: a byte-identical prefix, an unchanging tool list, and append-only history.
Changes
Pilot — static-first prompts.
getSystemPrompt,buildVerdictSystemPromptandbuildResetSystemPromptnow open with their static supervisor/evidence/decision bodies and close with the per-test task block. The dynamic parts ofbuildSharedEvidenceRules(scenario, deletion scope, expected results) moved into a newbuildTaskContext(task)that both verdict and reset prompts append last. The verdict opener no longer embedsTester requested ${type}— the user message already states it.Pilot — constant tool set.
sendToPilotalways buildspickPlanningTools() + buildPreconditionTool(task)and gates calls withtoolChoice: 'auto' | 'none'. PreviouslyplanTestsent tools,reviewNewPagesent none, andanalyzeProgresssent them only on failures; tool definitions are part of the cached prefix, so every flip invalidated the whole conversation.reviewNewPagenow passestask, sotaskbecame required on the options object.Pilot — append-only history. Dropped the three
cleanupTagcalls. Pilot conversations are light by design (tool summaries, no HTML) and bounded by the tester iteration cap.Planner — stable prefix order. Messages now run system → static rules → static output format → page research → approach + URL context → the rest. The output-format block became
getTasksMessage(), and itshasCurrentPlanconditional collapsed into one sentence covering both fresh and expanding plans.Disambiguator routing.
getAgenticModel()→getModelForAgent(). These ~350-token one-shot prompts are below the 1024-token cache floor and don't need the expensive model. Cost fix, not a cache fix — the one commit-separable piece here.Prompts are reordered, not rewritten; total length is unchanged. No
provider.tschange was needed:buildGenerateConfigspreads...optionsafter thetoolChoice: 'auto'default. Per the plan, this stays provider-agnostic — noproviderOptions, nopromptCacheKey.Trade-offs
generateObject's schema still constrains output shape, but adherence to the prose rules could weaken on some models.cleanupTag, pilot conversations grow by the trimmed blocks (~1-3K tokens on long tests), traded for cache hits across the conversation.tool_choice: nonecould still emit a tool call on review-only turns;maxToolRoundtrips: 0keeps that bounded to one roundtrip.Testing
bun test tests/unit/ tests/integration/— 871 pass, 0 fail. The planner integration tests needed no updates: they assert against the concatenated prompt rather than message order.Not yet done, and the real gate on this change:
pilot.analyzecalls show growing cached-token counts instead of resets to 0.🤖 Generated with Claude Code