fix(agent): bundle assistant text with toolUse + document cache hint dormancy #185

Merged
KofTwentyTwo merged 3 commits from fix/agent-cache-text-blocks-23-24 into develop 2026-05-14 11:53:35 +00:00
KofTwentyTwo commented 2026-05-13 21:35:35 +00:00 (Migrated from github.com)

Summary

Two related AgentCore tactical fixes from the 2026-05-12 audit:

#24 — Assistant text dropped alongside tool_use

Opus 4.7 commonly narrates before calling a tool ("Let me check the time for you..." → tool_use(get_time)). The orchestrator previously appended only the toolUse block to the messages array. On the next round-trip the model had no record of its narration — user follow-ups like "what did you say before checking the time?" got a denial.

Fix: introduce assistantTextSinceLastFlush parallel to assistantTextSoFar (cumulative for D-02 vision routing). On every toolUseRequested:

  • Flush the per-flush buffer into a .text(...) block
  • Bundle it with the .toolUse(...) block in the SAME assistant message
  • Trim whitespace-only text to avoid Anthropic 400s on empty text blocks
  • Reset the flush buffer so subsequent tool_uses in the same round get only the text emitted between them
  • D-02 cumulative assistantTextSoFar untouched

#23 — Cache hints dormancy documentation

The MIN_CHARS_FOR_CACHE_BREAKPOINT = 4096 threshold is structurally false on healthy boot (preamble ~700 chars, empty initial context), so eligibleForSystemPrompt returns nil on every turn and the prompt cache is dormant. Not a fix request per the audit — added a paragraph in CacheHints.swift explicitly documenting the dormancy, the intentional cost-acceptance, and the natural recovery once M-4 lands searchFacts-driven hydration.

Test plan

  • 3 new tests in AssistantTextWithToolUseTests:
    • ATU-1 text+toolUse bundled into same assistant message
    • ATU-2 toolUse-alone produces no spurious empty text block
    • ATU-3 whitespace-only text trimmed (no Anthropic 400)
  • Full AgentCore suite: 248 tests, 0 failures, 1 skipped locally
  • CI green on the SPM AgentCore + Harness + Replay jobs (depends on Grogu queue)

Closes #23, #24

🤖 Generated with Claude Code

## Summary Two related AgentCore tactical fixes from the 2026-05-12 audit: ### #24 — Assistant text dropped alongside tool_use Opus 4.7 commonly narrates before calling a tool ("Let me check the time for you..." → `tool_use(get_time)`). The orchestrator previously appended **only the toolUse block** to the messages array. On the next round-trip the model had no record of its narration — user follow-ups like "what did you say before checking the time?" got a denial. **Fix:** introduce `assistantTextSinceLastFlush` parallel to `assistantTextSoFar` (cumulative for D-02 vision routing). On every `toolUseRequested`: - Flush the per-flush buffer into a `.text(...)` block - Bundle it with the `.toolUse(...)` block in the SAME assistant message - Trim whitespace-only text to avoid Anthropic 400s on empty text blocks - Reset the flush buffer so subsequent tool_uses in the same round get only the text emitted between them - D-02 cumulative `assistantTextSoFar` untouched ### #23 — Cache hints dormancy documentation The `MIN_CHARS_FOR_CACHE_BREAKPOINT = 4096` threshold is structurally false on healthy boot (preamble ~700 chars, empty initial context), so `eligibleForSystemPrompt` returns `nil` on every turn and the prompt cache is dormant. **Not a fix request per the audit** — added a paragraph in `CacheHints.swift` explicitly documenting the dormancy, the intentional cost-acceptance, and the natural recovery once M-4 lands `searchFacts`-driven hydration. ## Test plan - [x] 3 new tests in `AssistantTextWithToolUseTests`: - `ATU-1` text+toolUse bundled into same assistant message - `ATU-2` toolUse-alone produces no spurious empty text block - `ATU-3` whitespace-only text trimmed (no Anthropic 400) - [x] Full AgentCore suite: **248 tests, 0 failures, 1 skipped** locally - [ ] CI green on the SPM AgentCore + Harness + Replay jobs (depends on Grogu queue) Closes #23, #24 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.