Skip to content

fix(agents): oldest-first tool result compaction with configurable ratios#726

Open
Cstewart-HC wants to merge 5 commits intomoltis-org:mainfrom
Cstewart-HC:fix/oldest-first-tool-result-compaction
Open

fix(agents): oldest-first tool result compaction with configurable ratios#726
Cstewart-HC wants to merge 5 commits intomoltis-org:mainfrom
Cstewart-HC:fix/oldest-first-tool-result-compaction

Conversation

@Cstewart-HC
Copy link
Copy Markdown
Contributor

Summary

Fix for Issue #1 from the stream investigation report — per-iteration tool-result compaction was destroying agent context in long loops.

Changes

A) Reverse compaction direction: Compact oldest results first instead of newest. The model needs its most recent tool outputs to maintain coherent operation in long agent loops.

B) Configurable ratios via ToolsConfig:

  • tool_result_compaction_ratio (default 75, set to 0 to disable)
  • preemptive_overflow_ratio (default 90)

C) Minimum iteration guard: compaction_min_iterations (default 3) — skip compaction for the first N iterations to prevent premature context destruction in short loops.

Behavior

All defaults match the previous hardcoded values for backward compatibility. No moltis.toml changes required for existing deploys.

Files changed (7 files, +71 −20)

  • crates/agents/src/runner/mod.rs — reverse iteration order, read config values
  • crates/agents/src/runner/streaming.rs — pass config through
  • crates/agents/src/runner/non_streaming.rs — pass config through
  • crates/agents/src/runner/tests/helpers.rs — test helper update
  • crates/config/src/schema/tools.rs — 3 new config fields with defaults
  • crates/config/src/template.rs — template comments
  • crates/config/src/validate/schema_map.rs — schema key registration

Validation

  • cargo fmt --check
  • cargo clippy --workspace --all-targets -- -D warnings
  • cargo test --workspace ✅ (344 passed, 1 timing-flaky unrelated failure)

Session context

Built during an extended investigation session into stream compaction issues. Redacted — no secrets or tokens in session.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 15, 2026

Greptile Summary

This PR resolves the oldest-first compaction direction bug in long agent loops, makes the compaction and overflow thresholds configurable via ToolsConfig, and adds a minimum-iteration guard that correctly delegates overflow checking even when compaction is suppressed. All five previously flagged issues (ratio=0 disable, off-by-one semantics, missing validation, test coverage, overflow suppression in early iterations) are addressed in this revision. Remaining findings are all P2: a literal newline inside the diagnostic format string, a misleading "compaction disabled" message that fires during the early-iteration suppression window, and missing upper-bound (>100) validation for the two percentage fields.

Confidence Score: 5/5

Safe to merge — all previously flagged blockers are resolved; only P2 polish items remain.

All five P0/P1 findings from prior review rounds have been correctly addressed: ratio=0 disable path, off-by-one in min-iterations semantics, ordering validation in check_semantic_warnings, oldest-first test coverage, and overflow still firing during the early-iteration window. Remaining findings are three P2 issues (diagnostic format string, misleading error message text, missing >100 validation) that do not affect correctness or safety.

crates/config/src/validate/semantic.rs (format string), crates/config/src/schema/tools.rs (upper-bound validation)

Important Files Changed

Filename Overview
crates/agents/src/runner/helpers.rs Reverses compaction direction to oldest-first, adds configurable ratio/overflow params, handles ratio=0 disable path, and retains post-compaction overflow guard — all correct.
crates/agents/src/runner/non_streaming.rs Wires in new config fields; effective_ratio=0 during early iterations correctly delegates overflow checking to enforce_tool_result_context_budget without skipping it.
crates/agents/src/runner/streaming.rs Mirrors non_streaming.rs changes exactly; same effective_ratio guard pattern, no issues.
crates/config/src/schema/tools.rs Adds three config fields with correct defaults; missing upper-bound (>100) validation for the two percentage fields.
crates/config/src/validate/semantic.rs Adds ordering constraint (overflow_ratio > compaction_ratio); diagnostic message has a literal newline/indentation inside the format string.
crates/agents/src/runner/tests/basic.rs Adds 12 new unit tests covering oldest-first direction, edge cases (already-compacted, too-small, zero tokens, zero context window), and enforce_budget path (ratio=0, overflow, compaction fire, no tool results).
crates/config/src/validate/schema_map.rs Registers the three new config keys; straightforward and correct.
crates/config/src/template.rs Template comments added for all three new fields with correct defaults; no issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["enforce_tool_result_context_budget\n(messages, tool_schemas, context_window,\ncompaction_ratio, overflow_ratio)"] --> B{context_window == 0\nor no tool results?}
    B -- Yes --> C[return Ok]
    B -- No --> D{compaction_ratio == 0?}
    D -- Yes --> E[compute overflow_budget\ncheck current_tokens]
    E --> F{current_tokens >\noverflow_budget?}
    F -- Yes --> G[return Err\nContextWindowExceeded\n'compaction disabled']
    F -- No --> C
    D -- No --> H[compute compaction_budget\nand overflow_budget]
    H --> I{current_tokens >\ncompaction_budget?}
    I -- Yes --> J["compact_tool_results_oldest_first_in_place\n(oldest → newest order)"]
    J --> K[log debug]
    I -- No --> L[re-estimate post_compaction_tokens]
    K --> L
    L --> M{post_compaction_tokens >\noverflow_budget?}
    M -- Yes --> N[return Err\nContextWindowExceeded\n'after compaction']
    M -- No --> C

    subgraph Callers["Callers (non_streaming / streaming)"]
        R["iterations > compaction_min_iterations?"]
        R -- Yes --> S["effective_ratio = compaction_ratio"]
        R -- No --> T["effective_ratio = 0\n(overflow still checked)"]
    end
    S --> A
    T --> A
Loading

Reviews (5): Last reviewed commit: "fix(agents): don't skip overflow check d..." | Re-trigger Greptile

Comment thread crates/agents/src/runner/mod.rs Outdated
Comment thread crates/agents/src/runner/non_streaming.rs Outdated
Comment thread crates/config/src/schema/tools.rs
@Cstewart-HC
Copy link
Copy Markdown
Contributor Author

@greptileai review

Comment thread crates/agents/src/runner/tests/helpers.rs Outdated
Cstewart-HC added a commit to Cstewart-HC/moltis that referenced this pull request Apr 15, 2026
P1: compaction_ratio=0 now truly disables compaction instead of
clamping to 1%. Early-return with overflow-only guard when ratio is 0.

P2: streaming.rs min-iterations guard changed from >= to > to match
non_streaming.rs - consistent skip first N iterations semantics.

P2: added config validation warning when preemptive_overflow_ratio
<= tool_result_compaction_ratio (prevents infinite error loops).

Refs: moltis-org#726
@Cstewart-HC Cstewart-HC force-pushed the fix/oldest-first-tool-result-compaction branch from 48b7325 to 3dd6b92 Compare April 15, 2026 21:49
Cstewart-HC added a commit to Cstewart-HC/moltis that referenced this pull request Apr 15, 2026
…et enforcement

Addresses PR moltis-org#726 review feedback: core behavioral change had no test
coverage. 11 new tests covering:

- Oldest-first compaction direction (not newest)
- Already-compacted results are skipped
- Results below TOOL_RESULT_COMPACTION_MIN_BYTES are skipped
- Zero tokens_needed early return
- Compaction stops once budget freed
- compaction_ratio=0 disables compaction (overflow-only guard)
- compaction_ratio=0 still errors on overflow
- Compaction fires when over compaction threshold
- ContextWindowExceeded when overflow unreachable after compaction
- Noop when no tool results present
- Noop when context_window is zero

Also fixes function rename: compact_tool_results_newest_first_in_place
→ compact_tool_results_oldest_first_in_place (name was stale after
rebase conflict resolution changed iteration direction to forward).
@Cstewart-HC
Copy link
Copy Markdown
Contributor Author

@greptileai review

Cstewart-HC and others added 4 commits April 15, 2026 19:30
…tios

Issue moltis-org#1 from moltis-stream-issues investigation.

Three changes to per-iteration tool-result compaction:

A) Reverse compaction direction: compact oldest results first instead of
   newest. The model needs its most recent tool outputs to maintain
   coherent operation in long agent loops.

C) Make compaction/overflow ratios configurable via ToolsConfig:
   - tool_result_compaction_ratio (default 75, set to 0 to disable)
   - preemptive_overflow_ratio (default 90)

D) Add compaction_min_iterations (default 3): skip compaction for the
   first N iterations to prevent premature context destruction in
   short loops.

All defaults match the previous hardcoded values for backward
compatibility. No moltis.toml changes required for existing deploys.
yes

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Signed-off-by: Christopher L Stewart <100775598+Cstewart-HC@users.noreply.github.com>
P1: compaction_ratio=0 now truly disables compaction instead of
clamping to 1%. Early-return with overflow-only guard when ratio is 0.

P2: streaming.rs min-iterations guard changed from >= to > to match
non_streaming.rs - consistent skip first N iterations semantics.

P2: added config validation warning when preemptive_overflow_ratio
<= tool_result_compaction_ratio (prevents infinite error loops).

Refs: moltis-org#726
…et enforcement

Addresses PR moltis-org#726 review feedback: core behavioral change had no test
coverage. 11 new tests covering:

- Oldest-first compaction direction (not newest)
- Already-compacted results are skipped
- Results below TOOL_RESULT_COMPACTION_MIN_BYTES are skipped
- Zero tokens_needed early return
- Compaction stops once budget freed
- compaction_ratio=0 disables compaction (overflow-only guard)
- compaction_ratio=0 still errors on overflow
- Compaction fires when over compaction threshold
- ContextWindowExceeded when overflow unreachable after compaction
- Noop when no tool results present
- Noop when context_window is zero

Also fixes function rename: compact_tool_results_newest_first_in_place
→ compact_tool_results_oldest_first_in_place (name was stale after
rebase conflict resolution changed iteration direction to forward).
@Cstewart-HC Cstewart-HC force-pushed the fix/oldest-first-tool-result-compaction branch from dc1a278 to bbf19d3 Compare April 15, 2026 22:31
Cstewart-HC added a commit to Cstewart-HC/moltis that referenced this pull request Apr 15, 2026
…et enforcement

Addresses PR moltis-org#726 review feedback: core behavioral change had no test
coverage. 11 new tests covering:

- Oldest-first compaction direction (not newest)
- Already-compacted results are skipped
- Results below TOOL_RESULT_COMPACTION_MIN_BYTES are skipped
- Zero tokens_needed early return
- Compaction stops once budget freed
- compaction_ratio=0 disables compaction (overflow-only guard)
- compaction_ratio=0 still errors on overflow
- Compaction fires when over compaction threshold
- ContextWindowExceeded when overflow unreachable after compaction
- Noop when no tool results present
- Noop when context_window is zero

Also fixes function rename: compact_tool_results_newest_first_in_place
→ compact_tool_results_oldest_first_in_place (name was stale after
rebase conflict resolution changed iteration direction to forward).
@Cstewart-HC
Copy link
Copy Markdown
Contributor Author

@greptileai review

Comment thread crates/agents/src/runner/non_streaming.rs Outdated
…ns guard

Pass ratio=0 (overflow-only path) instead of skipping the call
entirely during the first N iterations. This ensures
ContextWindowExceeded is raised even when compaction is deferred.

Fixes greptile P1 review feedback on moltis-org#726.
@Cstewart-HC
Copy link
Copy Markdown
Contributor Author

@greptileai review

Cstewart-HC added a commit to Cstewart-HC/moltis that referenced this pull request Apr 16, 2026
…tios

Three changes to per-iteration tool-result compaction:

A) Reverse compaction direction: compact oldest results first instead of
   newest. The model needs its most recent tool outputs to maintain
   coherent operation in long agent loops.

B) Make compaction/overflow ratios configurable via ToolsConfig:
   - tool_result_compaction_ratio (default 75, set to 0 to disable)
   - preemptive_overflow_ratio (default 90)

C) Add compaction_min_iterations (default 3): skip compaction for the
   first N iterations to prevent premature context destruction in
   short loops.

All defaults match the previous hardcoded values for backward
compatibility. No moltis.toml changes required for existing deploys.

Refs: moltis-org#726
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant