Exit codes lie to agents. Verification tells the truth.
Your agent finishes a task and reports success. You check the work — half the files are corrupted, the API endpoints return 500s, and the database migration failed silently. But your agent is celebrating because the exit code was 0.
This happened to us three times last week. Our coding agent would run a deployment script, see exit code 0, and declare victory while our staging environment burned. The problem isn't that agents can't read exit codes — it's that exit codes lie.
Here's what we learned: agents need output verification, not just exit code checking.
Most deployment scripts return 0 even when critical steps fail. Database migrations return success when they skip conflicting changes. API deployments return 0 when the container starts, regardless of whether the endpoints actually work. Your agent sees success. Your users see broken software.
We built a simple verification layer that checks actual outcomes instead of trusting exit codes:
def verify_deployment(deployment_result):
# Don't trust the exit code
if deployment_result.returncode == 0:
# Verify the actual endpoints
health_check = requests.get(f"{base_url}/health")
if health_check.status_code != 200:
return False, "Deployment succeeded but health check failed"
# Check database connectivity
db_check = run_db_ping()
if not db_check.success:
return False, "Deployment succeeded but database unreachable"
return True, "Deployment verified"
return False, f"Deployment failed with exit code {deployment_result.returncode}"The pattern works for any task where exit codes don't tell the full story:
- File operations: Check file size and permissions, not just that the copy command returned 0
- API deployments: Hit the actual endpoints, don't trust that the container started
- Database migrations: Query the schema version, don't trust the migration script's exit code
- Package installations: Try importing the package, don't trust that pip returned 0
We wrapped this into a simple verification protocol for our agents:
1. Execute the task 2. Check exit code (but don't trust it) 3. Run task-specific verification 4. Report based on verification, not exit code
The verification step adds 30 seconds to each task but prevents hours of debugging phantom successes. Our false positive rate dropped from 40% to under 5%.
Your agent should never celebrate based on exit codes alone. Build verification that checks the actual outcome — file sizes, API responses, database state, whatever proves the task actually worked.
Exit codes tell you if the script ran. Verification tells you if the work got done.