{"record":{"id":"fc204b935cb41801","repo":"siyuan-note/siyuan","slug":"agent-context-cannot-be-compacted-enough-recent-m","errorCode":null,"errorMessage":"agent context cannot be compacted enough: recent messages exceed the input budget","messagePattern":"agent context cannot be compacted enough: recent messages exceed the input budget","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/agent/agent.go","lineNumber":808,"sourceCode":"\n\t\t\tnativeResponsesCompaction := util.IsOpenAIResponsesProtocol(protocol) &&\n\t\t\t\tutil.SupportsOpenAIResponsesCompaction(ctx)\n\t\t\t// 原生 compact 无法限制输出长度，覆盖所有已完成轮次，避免 opaque window 返回后仍超出预算。\n\t\t\tselectedCandidateIndex := len(candidates) - 1\n\t\t\tif !nativeResponsesCompaction {\n\t\t\t\tselectedCandidateIndex = sort.Search(len(candidates), func(i int) bool {\n\t\t\t\t\tcandidate := candidates[i]\n\t\t\t\t\tcandidateCheckpointMsgs := checkpointMessagesAfterCompaction(sessionEntries, candidate, tail)\n\t\t\t\t\tcandidateMessages := checkpointMessagesToOpenAIWithSummary(\n\t\t\t\t\t\tcandidateCheckpointMsgs, language, capabilities, nil)\n\t\t\t\t\tcandidateMessages, _ = projectImageMessages(candidateMessages)\n\t\t\t\t\tbaseTokens := estimateProtocolRequestTokens(model, protocol, candidateMessages,\n\t\t\t\t\t\tcandidateCheckpointMsgs, nil, requestTools)\n\t\t\t\t\treturn compactionSummaryMinTokens <= inputBudget-baseTokens-compactionSummaryOverhead\n\t\t\t\t})\n\t\t\t}\n\t\t\tif selectedCandidateIndex == len(candidates) {\n\t\t\t\treturn false, fmt.Errorf(\"%w: recent messages exceed the input budget\", errContextCannotBeCompacted)\n\t\t\t}\n\t\t\tselectedEntryCount := candidates[selectedCandidateIndex]\n\t\t\tselectedCheckpointMsgs := checkpointMessagesAfterCompaction(sessionEntries, selectedEntryCount, tail)\n\t\t\tselectedMessages := checkpointMessagesToOpenAIWithSummary(\n\t\t\t\tselectedCheckpointMsgs, language, capabilities, nil)\n\t\t\testimatedSelectedMessages, _ := projectImageMessages(selectedMessages)\n\t\t\tbaseTokens := estimateProtocolRequestTokens(model, protocol, estimatedSelectedMessages,\n\t\t\t\tselectedCheckpointMsgs, nil, requestTools)\n\t\t\tsummaryMaxTokens := min(\n\t\t\t\tcompactionSummaryMaxTokens, inputBudget-baseTokens-compactionSummaryOverhead)\n\n\t\t\tsourceMessages := entriesToAgentMessages(sessionEntries[coveredEntryCount:selectedEntryCount])\n\n\t\t\tsendEvent(ch, AgentEvent{Type: \"thinking\", Reasoning: \"compacting context\"})\n\t\t\tvar nextCompaction *runtimeCompaction\n\t\t\tvar compactionStateErr error\n\t\t\tif nativeResponsesCompaction {\n\t\t\t\tresponseSource := entriesToAgentMessages(sessionEntries[coveredEntryCount:selectedEntryCount])","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/agent/agent.go#L790-L826","documentation":"After walking candidate entry counts to find the largest prefix of old entries that can be compacted while leaving enough room for the compaction summary, selectedCandidateIndex equals len(candidates) — no candidate fits. compactContext returns errContextCannotBeCompacted with \"recent messages exceed the input budget\": even the most aggressive compaction leaves a too-large remainder, so the summary request would exceed the model context.","triggerScenarios":"The tail messages that must be kept after compacting all candidates (current turn tail plus remaining checkpoint messages) still exceed inputBudget minus the minimum summary token reserve (compactionSummaryMinTokens + overhead). Happens when the kept recent messages alone are huge.","commonSituations":"Very large tool results in the recent (uncompactable) window; a small-context model combined with oversized recent turns; repeated huge attachments that keep re-appearing after each compaction.","solutions":["Move large tool outputs out of the message history (summarize or truncate them before they enter the tail window)","Use a model with a larger context window or reduce maxCompletionTokens to enlarge the input budget","Start a fresh session; if the tail is genuinely that large, compaction cannot save it","Reduce per-tool-call output limits configured for the agent's tools"],"exampleFix":"// before\ntool := agent.RegisterTool(readFile, outputLimit: 100000) // results dominate the tail\n// after\ntool := agent.RegisterTool(readFile, outputLimit: 8000) // cap tool output so the tail fits","handlingStrategy":"fallback","validationCode":"tailTokens := estimateProtocolRequestTokens(model, protocol, tailMessages, tailCheckpointMsgs, nil, requestTools)\nreserve := compactionSummaryMinTokens + compactionSummaryOverhead\nif tailTokens+reserve > contextInputBudget(contextLimit, maxCompletionTokens) {\n    return fmt.Errorf(\"recent messages (~%d tokens) exceed the compactable budget; trim the tail first\", tailTokens)\n}","typeGuard":null,"tryCatchPattern":"if err := agent.Send(ctx, msg); errors.Is(err, errContextCannotBeCompacted) &&\n    strings.Contains(err.Error(), \"recent messages exceed the input budget\") {\n    // start a new session or move to a larger-context model; retry is not useful as-is\n}","preventionTips":["Cap tool result sizes so the kept tail window stays small","Compact proactively after each huge turn instead of waiting until forced","Use a larger-context model for tool-heavy workloads","Avoid re-sending the same huge attachment after a failed turn"],"tags":["agent","compaction","context-window","token-budget"],"backgroundTag":"payload-too-large","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}