fix(caching): robust trajectory auto-detection & resume; cache format 0.3 - #310
Closed
philipph-askui wants to merge 1 commit into
Closed
fix(caching): robust trajectory auto-detection & resume; cache format 0.3#310philipph-askui wants to merge 1 commit into
philipph-askui wants to merge 1 commit into
Conversation
… format to 0.3 Fixes two reported trajectory-caching bugs and several logic bugs surfaced by an adversarial review of the caching subsystem. Reported bugs: - Resuming after the last (non-cacheable) step crashed with "Invalid start_from_step_index". `start_from_step_index == len(trajectory)` now means "already complete" and flows into the COMPLETED/verification path; only truly out-of-range indices raise. Empty/all-non-cacheable trajectories are handled too. The non-cacheable pause message now tells the agent the exact resume index, or that the step was the final one (verify instead of resume). - Replaced the "list available trajectories" workflow with automatic detection: in execute/auto mode the SDK looks up <cache_dir>/<filename> and, if a usable trajectory exists, injects its details (path + parameters) into the first user message so the agent can switch to the CacheExecutor immediately. In auto mode with no usable trajectory the agent is told none exists and the run is recorded. Removed retrieve_available_trajectories_tool and updated CACHE_USE_PROMPT. Cache format version bumped 0.2 -> 0.3. Additional bugs fixed (found during review): - CachingSettings.filename was silently ignored (no such field); added it as a top-level field used for both lookup and recording. - execute-only mode passed cache_manager=None, causing CacheExecutor to raise RuntimeError; a CacheManager is now always created when executing. - verify_cache_execution(success=False) now actually invalidates the cache, and success=True records the completion (execution_attempts/last_executed_at). - CACHE_USE prompt and CacheExecutor speaker no longer leak across act() calls; per-call caching tools no longer accumulate on the persistent tool collection (which could persist a later run's result to a previous run's trajectory). - LLM-identified parameters with invalid names or empty values are dropped (empty values previously corrupted every string in the trajectory). - Recording no longer writes/overwrites a cache with no cacheable steps. - finish_recording errors in teardown are logged instead of masking the run result. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
philipph-askui
marked this pull request as draft
August 27, 2026 12:51
Contributor
Author
|
Consolidated into a single PR: #311 now targets main and contains all of this branch's commits plus the parameter/observability work. Closing to avoid a stacked/duplicate PR. |
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
Fixes the two reported trajectory-caching bugs and, per request, includes an adversarial review of the whole caching subsystem with the resulting logic bugs fixed. Cache format version is bumped 0.2 → 0.3.
Reported bugs
1. Crash when the last trajectory step is not cacheable
Resuming after the final (non-cacheable) step raised
ValueError: Invalid start_from_step_index: 6. Trajectory has 6 steps.... Root cause: the executor rejectedstart_from_step_index == len(trajectory).start_from_step_index == len(trajectory)is now valid and means "already complete" — it flows into the COMPLETED/verification path instead of crashing. Only genuinely out-of-range values raise. Empty / all-non-cacheable trajectories are handled too.start_from_step_indexto resume with, or that the step was the final one (in which case: verify, don't resume).2. Auto-detect the trajectory instead of asking the agent to list them
Previously the agent had to call
retrieve_available_trajectories_toolfirst and be told in the prompt which caches to use.CachingSettings.filename(the test-case name). Inexecute/automode the SDK looks up<cache_dir>/<filename>automatically.CacheExecutor+verify_cache_executionare wired up, so the agent can hand off immediately.executeruns normally;autotells the agent none exists and records the run. An existing invalid cache is re-recorded (self-heal) rather than replayed.retrieve_available_trajectories_tooland rewroteCACHE_USE_PROMPTaccordingly.Additional bugs fixed (surfaced by the adversarial review)
CachingSettings.filenamewas silently ignored — the field didn't exist, so docstring/e2e examples that passedfilename=never actually set it. Now a real top-level field used for both lookup and recording.execute-only mode crashed — it passedcache_manager=None, butCacheExecutor.handle_stepraises if it'sNone. ACacheManageris now always created when executing.verify_cache_execution(success=False)was a no-op — it now actually invalidates the cache;success=Truerecords the completion (execution_attempts/last_executed_at), which was never updated before.act()calls — theCACHE_USEprompt (mutated on shared settings), theCacheExecutorspeaker, and per-call caching tools all persisted into later runs. The wiredVerifyCacheExecutionleak could even persist a later run's result to a previous run's trajectory file. All now scoped per-call.str.replace("", ...)); invalid names silently broke validation/substitution. Such entries are now dropped.finish_recordingerrors are logged instead of masking the real run outcome.Known limitations (documented follow-ups, intentionally not in this PR)
These are deeper design changes with real regression risk; flagging rather than rushing them:
AutomationErrorduring replay still terminates the run (same as normal mode) rather than routing to the executor's self-heal/invalidate path;is_errortool results during replay aren't inspected.max_stepsbudget one per action.Testing
tests/unit/speaker/test_cache_executor.py,tests/unit/test_caching_agent_helpers.py,tests/unit/utils/caching/test_cache_manager.py,tests/unit/utils/caching/test_cache_parameter_handler.py; updatedtests/unit/tools/test_caching_tools.pyand the caching e2e test.pdm run qa:fixclean (typecheck + format + lint); full unit suite green (763 passed).docs/06_caching.md) rewritten for the newfilename-based flow.🤖 Generated with Claude Code