#9861: fix(agents): re-run tool_use/tool_result repair after limitHistoryTurns
agents
stale
Cluster:
Error Handling in Agent Tools
## Problem
`limitHistoryTurns()` can break tool_use/tool_result pairs by cutting in the middle of a tool call sequence. For example, if the limit truncates messages such that a tool_use is included but its corresponding tool_result is cut off, the API will reject with:
```
messages.365: tool_use ids were found without tool_result blocks immediately after: edit_1770316263727_26
```
## Root Cause
The order of operations was:
1. `sanitizeToolUseResultPairing()` runs - repairs tool pairs ✅
2. `limitHistoryTurns()` runs - truncates by user turn count
3. **Truncation can break the pairs that were just repaired!** ❌
## Solution
Run `sanitizeToolUseResultPairing()` AFTER `limitHistoryTurns()` to ensure any orphaned tool_use blocks get synthetic error results added.
Applied to both:
- `run/attempt.ts` (main execution path)
- `compact.ts` (compaction execution path)
## Testing
- Build passes ✅
- Simple fix with minimal risk - just reorders existing sanitization logic
## Related
Fixes the root cause of #8525-type issues where model switching after truncation could cause API rejections.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR correctly addresses a real failure mode where `limitHistoryTurns()` can truncate session history mid tool-call sequence, leaving orphaned `tool_use` blocks. The change re-runs `sanitizeToolUseResultPairing()` after truncation in both execution paths (`src/agents/pi-embedded-runner/run/attempt.ts` and `src/agents/pi-embedded-runner/compact.ts`), ensuring transcripts remain acceptable to strict providers.
However, the PR also introduces three new operational/agent helper files (`ecosystem.config.cjs`, `skills/coding-agent/scripts/*`) that are unrelated to the stated fix. Two of these introduce must-fix issues: a PM2 config with hard-coded machine paths and a wrapper script that mutates the user’s project directory by running `git init` when missing.
<h3>Confidence Score: 3/5</h3>
- This PR is not safe to merge as-is due to unrelated operational/script additions with problematic side effects.
- The core agent transcript repair reordering looks correct and consistent with existing sanitization logic, but the PR also adds a machine-specific PM2 config and a helper script that runs `git init` in arbitrary directories, which are changes the repo likely doesn’t want and can break user environments.
- ecosystem.config.cjs, skills/coding-agent/scripts/samantha-code.sh
<!-- greptile_other_comments_section -->
<sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#4852: fix(agents): sanitize tool pairing after compaction and history tru...
by lailoo · 2026-01-30
88.0%
#12487: fix(agents): strip orphaned tool_result when tool_use is sanitized ...
by skylarkoo7 · 2026-02-09
87.3%
#4009: fix(agent): sanitize messages after orphan user repair
by drag88 · 2026-01-29
86.1%
#3647: fix: sanitize tool arguments in session history
by nhangen · 2026-01-29
86.0%
#2557: fix(agents): preserve tool call/result pairing in history limiting
by steve-rodri · 2026-01-27
85.7%
#4844: fix(agents): skip error/aborted assistant messages in transcript re...
by lailoo · 2026-01-30
85.1%
#8345: fix: prevent synthetic error repair from creating tool_result for d...
by vishaltandale00 · 2026-02-03
84.8%
#8312: fix: add logging and markers for tool result repair
by ekson73 · 2026-02-03
84.2%
#21166: fix(agents): sanitize tool names in session transcript repair (#8595)
by dinakars777 · 2026-02-19
83.2%
#19094: Fix empty tool_call_id and function names in provider transcript pa...
by yxshee · 2026-02-17
82.9%