fix(agent): repair transcript pairing after compaction and truncation#1470
Open
daotri wants to merge 1 commit into
Open
fix(agent): repair transcript pairing after compaction and truncation#1470daotri wants to merge 1 commit into
daotri wants to merge 1 commit into
Conversation
Mid-loop compaction output now runs through sanitizeHistory so orphaned tool messages never reach the provider (OpenAI rejects role:tool without a preceding assistant tool_calls). Background summarization truncates on tool-chain boundaries via the shared toolChainSplitIndex helper so the kept tail never starts mid tool-chain.
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.
Problem
When a conversation is compacted mid-loop or truncated by the background
summarizer, the split point could land in the middle of a tool-chain,
leaving an orphaned
role:"tool"message with no precedingassistantmessage carryingtool_calls. Providers reject this — OpenAIreturns a 400 on the next request.
Fix
Repair transcript pairing at both truncation points, addressing the
root cause rather than a single call site:
history) now runs through
sanitizeHistory, so orphaned tool messagesnever reach the provider. A
slog.Warn("post_compaction_sanitize", ...)surfaces when a repair happens.
tool-chain boundary via a shared
toolChainSplitIndexhelper, so the kepttail never starts mid tool-chain.
The backward-walk logic (previously inlined in compaction) is extracted into
toolChainSplitIndexand reused by both paths, with an added bounds guard(
splitIdx < len(messages)) that also fixes a latent out-of-range access whenthe split index equals the message count.
Changes
internal/agent/loop_compact.gotoolChainSplitIndexhelperinternal/agent/loop_history_sanitize.gointernal/agent/loop_pipeline_callbacks.gointernal/agent/loop_compact_boundary_test.goTesting
go build ./internal/agent/✅go vet ./internal/agent/✅go test ./internal/agent/ -run 'TestToolChainSplitIndex|TestMakeCompactMessages_SanitizesOrphanTool|TestMaybeSummarize_ToolChainBoundary'✅New unit tests cover: clean boundary stays put, split on tool result walks
back before
assistant(tool_calls), consecutive tool results walk the wholechain, compaction callback sanitizes orphans, and summarizer truncates on the
tool-chain boundary.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Eeg3HGEWSqhPxsSQKAbe2x