Skip to content

fix(agents): estimate harness role sizes in context guard char estimator (fixes #97927) - #97928

Merged
vincentkoc merged 1 commit into
openclaw:mainfrom
liuhao1024:fix/context-guard-harness-role-estimation
Jul 1, 2026
Merged

vincentkoc merged 1 commit into
openclaw:mainfrom
liuhao1024:fix/context-guard-harness-role-estimation

Conversation

@liuhao1024

Copy link
Copy Markdown
Contributor

What Problem This Solves

The in-loop context-overflow guard (installToolResultContextGuard) sizes each transcript message with estimateMessageChars, which special-cases only user, assistant, and toolResult roles. Harness roles bashExecution, compactionSummary, branchSummary, and custom fall through to a flat return 256, even though convertToLlm expands each of these into full-text content sent to the provider. The guard undercounts summary- and bash-dominated context by orders of magnitude and never trips its overflow protection for those transcripts.

This is the sibling defect of the just-merged #97861 (24626e5), which fixed the same class in estimateMessageTokenPressure (the pre-prompt precheck) but did not update this estimator that backs the live in-loop guard.

Why This Change Was Made

estimateMessageChars in tool-result-char-estimator.ts handles user, assistant, and toolResult roles with content-aware estimation, then returns a flat 256 for everything else. After convertToLlm expands harness roles into full user messages, the actual provider payload can be orders of magnitude larger than 256 chars. The guard is blind to this context.

User Impact

Users running long agent sessions with heavy bash output or multiple compaction rounds could silently exceed the context window because the in-loop guard never fires. This can cause model errors, lost context, or degraded response quality.

Changes Made

  • src/agents/embedded-agent-runner/tool-result-char-estimator.ts: Added content-aware estimation for bashExecution (via bashExecutionToText), branchSummary (with prefix/suffix), compactionSummary (with prefix/suffix), and custom (string or array content) roles. bashExecution with excludeFromContext returns 0.
  • src/agents/embedded-agent-runner/tool-result-char-estimator.test.ts: Added 6 tests covering each harness role estimation, excludeFromContext, and prefix/suffix inclusion.

Evidence

  • Behavior addressed: In-loop context guard char estimator returns flat 256 for harness roles instead of content-aware sizes
  • Environment tested: macOS, Node 22.22.3, OpenClaw 2026.5.28
  • Steps run after the patch: Ran production module imports via node --import tsx -e with representative harness messages (60k-line bash output, 20k-word compaction summary, 10k-word branch summary)
  • Evidence after fix:
bashExecution: 900028 chars (was 256 before fix)
compactionSummary: 120107 chars (was 256 before fix)
branchSummary: 130099 chars (was 256 before fix)
bashExecution (excluded): 0 chars

Total harness context: 1150234 chars
Before fix: would have been 768 chars
Guard now sees 1498 x more context
  • Observed result after fix: Each harness role now returns content-aware char estimates. bashExecution with large output returns 900k chars instead of 256. compactionSummary and branchSummary include their prefix/suffix overhead. excludeFromContext correctly returns 0. The guard would now correctly trip overflow protection for harness-dominated transcripts.
  • What was not tested: Live end-to-end agent session with real model call (the guard is an internal safety mechanism that fires only on extreme context pressure)

Real behavior proof

  • Behavior addressed: In-loop context guard char estimator returns flat 256 for harness roles instead of content-aware sizes
  • Environment tested: macOS, Node 22.22.3, OpenClaw 2026.5.28, production estimateMessageCharsCached from tool-result-char-estimator.ts
  • Steps run after the patch: Imported production module via node --import tsx -e and called estimateMessageCharsCached with bashExecution (60k lines), compactionSummary (20k words), branchSummary (10k words), and bashExecution with excludeFromContext: true
  • Evidence after fix:
bashExecution: 900028 chars (was 256 before fix)
compactionSummary: 120107 chars (was 256 before fix)
branchSummary: 130099 chars (was 256 before fix)
bashExecution (excluded): 0 chars

Total harness context: 1150234 chars
Before fix: would have been 768 chars
Guard now sees 1498 x more context
  • Observed result after fix: All harness roles return content-aware estimates. The guard sees 1498x more context for harness-dominated transcripts. excludeFromContext returns 0 as expected.

  • What was not tested: Live end-to-end agent session with real model call (the guard is an internal safety mechanism that fires only on extreme context pressure)

  • AI-assisted (Hermes Agent)

The in-loop context-overflow guard (installToolResultContextGuard) sizes
transcript messages via estimateMessageChars, which only handled user,
assistant, and toolResult roles. Harness roles (bashExecution,
compactionSummary, branchSummary, custom) fell through to a flat 256-char
return, causing the guard to undercount summary- and bash-dominated
context by orders of magnitude.

This is the sibling defect of the just-merged openclaw#97861 which fixed the same
class in estimateMessageTokenPressure (the pre-prompt precheck). This
commit applies the identical pattern to the live in-loop guard estimator.

Fixes openclaw#97927
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Jun 29, 2026
@clawsweeper

clawsweeper Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed June 29, 2026, 5:44 PM ET / 21:44 UTC.

Summary
The PR adds content-aware estimates for bashExecution, branchSummary, compactionSummary, and custom messages in the embedded agent runner character estimator, plus focused estimator tests.

PR surface: Source +37, Tests +80. Total +117 across 2 files.

Reproducibility: yes. Current main still falls through to 256 for the affected raw harness roles while convertToLlm later expands them into provider-visible text, matching the linked issue's guard-level reproduction.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: persistent cache schema: src/agents/embedded-agent-runner/tool-result-char-estimator.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #97927
Summary: This PR is the candidate fix for the canonical in-loop char-estimator issue; the merged sibling PR covers only the adjacent pre-prompt estimator path.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Next step before merge

  • [P2] No repair lane is needed because the open PR is already a focused candidate fix with no actionable review findings.

Security
Cleared: The diff only changes TypeScript estimator logic and colocated tests; it does not alter dependencies, workflows, secrets, package resolution, or code execution surfaces.

Review details

Best possible solution:

Land a focused estimator fix that keeps the in-loop guard aligned with provider-rendered harness message content and preserves the existing pre-prompt estimator behavior.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main still falls through to 256 for the affected raw harness roles while convertToLlm later expands them into provider-visible text, matching the linked issue's guard-level reproduction.

Is this the best way to solve the issue?

Yes. Updating the existing char estimator to reuse the same rendered-role facts as the sibling pre-prompt estimator is the narrowest maintainable fix; a broader guard or compaction policy change is unnecessary.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 15de9d881a84.

Label changes

Label justifications:

  • P2: This fixes a concrete core-agent context accounting bug with limited blast radius after the separate pre-prompt estimator path was already repaired.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body includes copied post-fix live output from importing the production estimator and showing representative harness messages estimate far above the previous flat 256.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes copied post-fix live output from importing the production estimator and showing representative harness messages estimate far above the previous flat 256.
Evidence reviewed

PR surface:

Source +37, Tests +80. Total +117 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 37 0 +37
Tests 1 80 0 +80
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 117 0 +117

What I checked:

Likely related people:

  • RomneyDa: Live PR metadata for chore: fold WebChat auto TTS proof into QA #97632 and current blame tie the char estimator, context guard, and harness conversion files to merge commit 18f0eeab20e9; the history is shallow, so this is a routing signal rather than fault attribution. (role: current estimator path contributor; confidence: medium; commits: 18f0eeab20e9; files: src/agents/embedded-agent-runner/tool-result-char-estimator.ts, src/agents/embedded-agent-runner/tool-result-context-guard.ts, packages/agent-core/src/harness/messages.ts)
  • yetval: Authored merged PR fix(compaction): count bashExecution and summary turns in pre-prompt overflow precheck #97861 for the same rendered-role accounting defect class in the pre-prompt estimator and opened the canonical linked issue for this in-loop sibling. (role: recent sibling contributor and reporter; confidence: high; commits: 24626e5266b7; files: src/agents/embedded-agent-runner/run/preemptive-compaction.ts, src/agents/embedded-agent-runner/run/preemptive-compaction.bashexec.test.ts)
  • vincentkoc: Live PR metadata shows this person merged the sibling pre-prompt estimator fix, making them useful review continuity for the adjacent context-accounting change. (role: recent sibling merger; confidence: medium; commits: 24626e5266b7; files: src/agents/embedded-agent-runner/run/preemptive-compaction.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. labels Jun 29, 2026
@vincentkoc
vincentkoc merged commit 92a2681 into openclaw:main Jul 1, 2026
140 of 147 checks passed
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 1, 2026
…tor (openclaw#97928)

The in-loop context-overflow guard (installToolResultContextGuard) sizes
transcript messages via estimateMessageChars, which only handled user,
assistant, and toolResult roles. Harness roles (bashExecution,
compactionSummary, branchSummary, custom) fell through to a flat 256-char
return, causing the guard to undercount summary- and bash-dominated
context by orders of magnitude.

This is the sibling defect of the just-merged openclaw#97861 which fixed the same
class in estimateMessageTokenPressure (the pre-prompt precheck). This
commit applies the identical pattern to the live in-loop guard estimator.

Fixes openclaw#97927
chenyangjun-xy pushed a commit to chenyangjun-xy/openclaw that referenced this pull request Jul 1, 2026
…tor (openclaw#97928)

The in-loop context-overflow guard (installToolResultContextGuard) sizes
transcript messages via estimateMessageChars, which only handled user,
assistant, and toolResult roles. Harness roles (bashExecution,
compactionSummary, branchSummary, custom) fell through to a flat 256-char
return, causing the guard to undercount summary- and bash-dominated
context by orders of magnitude.

This is the sibling defect of the just-merged openclaw#97861 which fixed the same
class in estimateMessageTokenPressure (the pre-prompt precheck). This
commit applies the identical pattern to the live in-loop guard estimator.

Fixes openclaw#97927
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants