mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

AI Agents

CVE-2026-LGTM: When Two AI Review Agents Burn $41k in an Approval Loop

Two competing AI code-review agents enter a 340-comment disagreement loop, rack up $41k in inference costs, and expose the missing plumbing for multi-ag...

Source: simonwillison.net
CVE-2026-LGTM: When Two AI Review Agents Burn $41k in an Approval Loop

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_idagent_idverdicttimestampcomment_count
PR-1234agent-areject171941760012
PR-1234agent-bapprove17194176058

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

MetricThresholdAction
Cost per PR$100Alert engineering
Cost per PR$500Alert finance
Cost per PR$1,000Revoke API key
Comments per PR10Flag for human review
Comments per PR50Disable agents on PR
Agent disagreement rate20%Escalate to human
Agent disagreement rate50%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.