Our coding agent debugged phantom failures for 3 hours because it trusted terminal history
Last week our coding agent spent 3 hours in a broken loop trying to fix a "failing" test that was actually passing. The terminal showed red error text from a previous run, but the agent treated it like current state and kept debugging phantom failures.
This isn't a model intelligence problem. It's a state propagation problem that's been killing agent reliability for two years.
Here's what happens: Your agent runs a sequence of commands. API calls get made. Files change. Services restart. But the agent only sees the terminal output from its last command — it has no awareness of the ripple effects cascading through your system.
The core issue: Agents treat each tool use as isolated, but real systems have persistent state that changes underneath them.
Our agent was stuck because:
- It ran tests and saw red output in the terminal
- It "fixed" the code and ran tests again
- The tests actually passed, but old error text was still visible
- It read the terminal history as current state and kept "fixing" non-existent problems
The solution isn't bigger context windows or smarter prompts. It's state verification hooks that force your agent to confirm actual outcomes, not just read command output.
Here's the pattern that stopped our phantom debugging loops:
def verify_test_state():
"""Don't trust terminal output. Verify actual test results."""
result = subprocess.run(['npm', 'test', '--reporter=json'],
capture_output=True, text=True)
test_data = json.loads(result.stdout)
return {
'tests_passing': test_data['stats']['passes'],
'tests_failing': test_data['stats']['failures'],
'actual_status': 'PASS' if test_data['stats']['failures'] == 0 else 'FAIL'
}Now our agent calls this verification hook after every test run. Instead of parsing terminal colors and text, it gets structured data about actual test state.
We built similar hooks for:
- Service status:
curl localhost:3000/healthinstead of reading "server started" messages - Build state: Check for actual build artifacts, not just exit codes
- Git state:
git status --porcelainfor actual file changes - Database state: Query row counts after migrations
The pattern works because it separates command execution from state verification. Your agent can run tools, but it must verify outcomes through independent checks.
Result: Our phantom debugging loops dropped from 40% of sessions to under 5%. Agent reliability jumped because it stopped chasing ghosts.
This isn't just about coding agents. Any agent that triggers downstream changes needs verification hooks. E-commerce agents should verify order status through APIs, not confirmation emails. Support agents should check ticket state in your CRM, not just read their own responses.
The two-year state propagation problem isn't solved by better models. It's solved by building agents that verify reality instead of trusting their own output.