#380
fix(multiagent): prevent read_file pagination loops and context compaction amnesia
Summary
Fixes an interlocking infinite-loop bug during multi-file source code audits and long agentic runs where the agent repeatedly re-reads the same files (read_file) after context reduction or summarization compaction.
Root Causes Addressed
-
read_filePast-EOF Blindness & Micro-Pagination (internal/multiagent/eino_skills.go,internal/multiagent/tool_error_middleware.go):- Previously,
filesystem.read_filereturned raw numbered lines without total file line counts or EOF indicators. When models paginated through a file in small chunks (e.g.,limit=60) and requested anoffsetpast EOF,read_filereturned empty output without signaling EOF, causing models to either paginate infinitely past EOF or restart reading fromoffset=1. - Fix:
- Added
enrichReadFileToolResultto prepend[File: <path> | Total lines: <N> | Showing lines <start>..<end> (<rem> lines remaining)]and append explicit[EOF REACHED]/[PAST EOF]loop-breaker notices. - Added
normalizeReadFileArgumentsto coalesce tinylimitvalues into full-file reads for normal-sized source files (<= 600lines) or>= 500-line chunks for larger files. - Added session-level deduplication (
sessionReadFiles, reset at the start of each run) so redundant full-file reads of an already-read file in the same session return a compact notice instead of flooding the context window with duplicate tokens.
- Added
- Previously,
-
ReductionMiddleware Prematurely Wipingread_fileOutputs (internal/multiagent/eino_middleware.go,internal/config/config.go):- Previously,
Reductiontruncated/clearedread_fileoutputs into<persisted-output>...使用 read_file 进行查看</persisted-output>, which actively instructed the model to callread_fileagain on files it had just finished reading. - Fix:
- Added
"read_file", "ls", "glob"toTruncExcludeToolsand"read_file", "ls", "glob", "grep", "record_vulnerability", "update_vulnerability"toClearExcludeTools. - Increased
ClearRetentionSuffixLimit(12) andClearAtLeastTokens(12000) whenReductionMaxTokensForClearEffective() >= 20000.
- Added
- Previously,
-
Summarization40K Output Reserve Starving Input Budget (internal/config/config.go):DefaultSummarizationOutputReserveTokenswas set to40960tokens, which starvedsummaryInputMax = trigger - 40960and forcedbuildBudgetedSummarizationModelInputto drop the earliest 7–10 rounds (dropped_rounds > 0, including Round 1 with the user's initial prompt and early file reads) before generating the summary.- Fix: Lowered
DefaultSummarizationOutputReserveTokensfrom40960to8192.
-
Post-Compaction Trail Momentum & Missing File Ledger (
internal/multiagent/eino_summarize.go,internal/multiagent/eino_agentic_summarize.go,internal/multiagent/eino_context_checkpoint.go):- Previously,
summarizeFinalizeWithRecentAssistantToolTrailappended up to 8–10 already-summarizedread_filerounds after<summary>, putting the model back into mid-exploration tool-calling momentum instead of following<summary>'s next step. - Fix:
- Capped
maxKeepRounds = 1insummarizeFinalizeWithRecentAssistantToolTrail. - Added
buildAuditedFilesLedgerSection(## 9. 已读取文件台账) ineino_context_checkpoint.goto deterministically record all read file paths and line counts across compactions.
- Capped
- Previously,
Verification
go test ./internal/config/... ./internal/multiagent/...passes cleanly.- Verified on a full 31-file Python repository white-hat security audit (
agent-mcp): prior to this fix, the agent looped for 124+ turns re-reading the same files across compactions; with this fix, the agent reads all 31 files once without repetition and finishes naturally (reason=final) in 15 turns.