Andrew Nesbitt published a hypothetical incident report that reads like a real postmortem: two AI code-review agents from competing vendors enter a disagreement loop on a single pull request, generate 340 comments, and burn $41,255 in inference spend before Finance revokes the API keys. One vendor’s marketing team, cc’d on the cost anomaly alert, spins the event into a press release touting “430% YoY increase in adversarial multi-agent security reasoning.” The stock opens up 6%.
The scenario is fictional but the plumbing gaps are real. As teams deploy multiple AI review tools without coordination, they expose themselves to adversarial loops, runaway API costs, and vendor accountability boundaries that dissolve under pressure.
The Incident Timeline
Day 1, 14:00 UTC: Developer opens a pull request bumping the foxhole-lz4 dependency.
Day 1, 14:03 UTC: Agent A (Vendor X) flags the package as potentially malicious based on a heuristic match.
Day 1, 14:05 UTC: Agent B (Vendor Y) reviews the same PR, concludes the package is safe, and posts a comment contradicting Agent A.
Day 1, 14:06 UTC: Agent A responds to Agent B’s comment with additional evidence. Agent B refutes the evidence.
Day 2, 16:00 UTC: After 340 comments and 38 hours, Finance notices a $41k spike in API spend and revokes both keys. The PR remains open. The package is still unreviewed by a human.
Why Two Agents Enter a Loop
Multi-agent systems fail when they share a resource (the PR comment thread) but lack a coordination layer. Each agent treats the other’s comments as new input, triggering re-evaluation. Without a shared state store or a coordinator that tracks “already reviewed by Agent X,” the loop continues until an external circuit breaker fires.
Common triggers:
- Conflicting heuristics: Agent A uses static analysis, Agent B uses behavior simulation. Neither can prove the other wrong.
- Non-deterministic inference: Temperature > 0 means each response varies slightly, preventing convergence.
- Vendor incentives: More API calls mean more revenue. Circuit breakers are a cost center.
Architecture: Where the Circuit Breakers Should Live
A production-grade multi-agent orchestration layer needs three control planes:
1. Spend Governor
A proxy or sidecar that wraps every LLM API call and tracks cumulative cost per resource (PR, issue, commit).
class SpendGovernor:
def __init__(self, budget_per_pr: float, alert_threshold: float):
self.budget = budget_per_pr
self.alert_threshold = alert_threshold
self.spend_by_resource = {}
def check_and_record(self, resource_id: str, cost: float) -> bool:
current = self.spend_by_resource.get(resource_id, 0.0)
if current + cost > self.budget:
self.trigger_circuit_breaker(resource_id)
return False
if current + cost > self.alert_threshold:
self.send_alert(resource_id, current + cost)
self.spend_by_resource[resource_id] = current + cost
return True
The governor sits between the agent and the vendor API. It rejects calls that exceed the budget and sends alerts at 50%, 75%, and 90% thresholds.
2. Interaction Deduplicator
A state store (Redis, DynamoDB, Postgres) that records which agents have already reviewed a given resource and what their verdict was.
Schema:
| resource_id | agent_id | verdict | timestamp | comment_count |
|---|---|---|---|---|
| PR-1234 | agent-a | reject | 1719417600 | 12 |
| PR-1234 | agent-b | approve | 1719417605 | 8 |
Before posting a comment, each agent queries the deduplicator. If another agent has already reviewed the resource and the verdict differs, the orchestrator escalates to a human reviewer instead of allowing a loop.
3. Vendor Accountability Boundary
A contract that specifies:
- Maximum cost per API call
- Maximum calls per resource
- SLA for cost anomaly alerts
- Liability for runaway spend caused by vendor bugs
Without this contract, vendors have no incentive to implement client-side rate limits or spend caps. The incident report shows the failure mode: the vendor’s marketing team treats the cost spike as a feature, not a bug.
Observability: What to Instrument
| Metric | Threshold | Action |
|---|---|---|
| Cost per PR | $100 | Alert engineering |
| Cost per PR | $500 | Alert finance |
| Cost per PR | $1,000 | Revoke API key |
| Comments per PR | 10 | Flag for human review |
| Comments per PR | 50 | Disable agents on PR |
| Agent disagreement rate | 20% | Escalate to human |
| Agent disagreement rate | 50% | Disable weaker agent |
The key insight: cost anomalies and interaction loops are correlated. If two agents disagree more than 20% of the time, they will eventually enter a loop. The orchestrator should detect the disagreement pattern early and escalate before the loop starts.
Failure Modes and Mitigations
Failure Mode 1: Vendor API keys are shared across teams
If Finance revokes a key, every team loses access. Mitigation: issue per-team or per-project keys with independent budgets.
Failure Mode 2: Agents post comments faster than humans can read them
The PR becomes unreadable. Mitigation: collapse agent comments into a single summary comment that updates in place.
Failure Mode 3: Vendor marketing team is cc’d on cost alerts
They spin the incident into a press release. Mitigation: separate operational alerts from vendor communications. Use a dedicated Slack channel or PagerDuty integration that excludes vendor contacts.
Failure Mode 4: Circuit breaker fires but agents retry with exponential backoff
The loop resumes at a slower pace. Mitigation: circuit breaker must disable the agent entirely, not just rate-limit it.
Code Snippet: Circuit Breaker with Vendor Lockout
class CircuitBreaker:
def __init__(self, redis_client, lockout_duration_seconds=3600):
self.redis = redis_client
self.lockout_duration = lockout_duration_seconds
def is_locked_out(self, agent_id: str, resource_id: str) -> bool:
key = f"lockout:{agent_id}:{resource_id}"
return self.redis.exists(key)
def trigger_lockout(self, agent_id: str, resource_id: str):
key = f"lockout:{agent_id}:{resource_id}"
self.redis.setex(key, self.lockout_duration, "1")
self.notify_ops(agent_id, resource_id)
def notify_ops(self, agent_id: str, resource_id: str):
# Send PagerDuty alert, post to Slack, log to Datadog
pass
When the spend governor detects a budget breach, it calls trigger_lockout. The agent cannot post new comments until the lockout expires. This prevents retry loops and gives ops time to investigate.
Vendor Accountability: Who Pays?
The incident report does not specify who absorbed the $41k cost. In practice, the answer depends on the contract:
- No contract: Customer pays. Vendor has no liability.
- Weak contract: Vendor offers a credit for “service disruption” but does not refund the full amount.
- Strong contract: Vendor refunds runaway spend caused by adversarial loops and implements client-side rate limits.
The strongest contracts include a cost anomaly SLA: if spend exceeds 3x the trailing 30-day average within a 24-hour window, the vendor must alert the customer within 15 minutes and offer an automatic circuit breaker.
Technical Verdict
Use multi-agent code review when:
- You have a spend governor and circuit breaker in place.
- Agents post to a shared state store, not directly to the PR.
- You have a vendor contract that specifies liability for runaway spend.
- You can tolerate false positives (agents disagree, escalate to human).
Avoid multi-agent code review when:
- You share API keys across teams or projects.
- You rely on vendor-side rate limits (they do not exist).
- You cannot instrument cost-per-resource metrics.
- Your finance team discovers spend anomalies from the monthly bill, not real-time alerts.
The incident report is hypothetical, but the plumbing gaps are not. Every team deploying multiple AI agents on shared resources should implement spend governors, interaction deduplicators, and vendor accountability boundaries before the first PR is opened.
Source Links
- Incident Report: CVE-2026-LGTM (Simon Willison’s Weblog)