DEV Community

Cover image for Your AI agent failed at step 3 of 5. Now what?
Gerson Tolentino Andrade
Gerson Tolentino Andrade

Posted on

Your AI agent failed at step 3 of 5. Now what?

AI agents stopped just talking. They now do things — through tools: create a database user, send an email, charge a card, drop a table. That's the whole point of the Model Context Protocol (MCP): a universal way to hand real tools to an AI.

It's powerful. It's also a little terrifying.

In July 2025, an AI coding agent famously deleted a company's production database. Name-based confusion — prod vs staging — is exactly the kind of mistake a fast, confident, tool-wielding agent makes. And here's the uncomfortable part: in a multi-step task, when step 4 fails, steps 1–3 are already committed in real systems. There's no Ctrl+Z.

Orchestrators (Temporal, Restate, LangGraph) solve this inside your own workflow code. But there was no declarative, protocol-level way for an MCP server to say: "this tool is mutating, and its inverse is that other tool, with these parameters."

So I built one. It's called ChronoMCP, it's MIT-licensed, and it's a single npm install.

The idea: a transparent guard between the agent and the world

ChronoMCP is a proxy that sits between any MCP client and any MCP server. Point your client at it and everything passes through unchanged — until a tool call is risky. Then it:

  1. Classifies every call as read / mutating / destructive (conservative by default: unknown = treated as mutating).
  2. Shows a human-readable impact diff before anything runs — and flags PRODUCTION and irreversible actions.
  3. Gates mutations on human approval (terminal prompt, policy, or a remote control plane like Slack).
  4. Rolls back on failure with a LIFO saga — deterministically.
  5. Hash-chains an audit log anyone can verify.

The heart of it: declarative, honest compensation

A server declares, per tool, how to undo it — via an open extension, mcp-compensate:

{
  "name": "create_record",
  "_meta": {
    "dev.chronomcp/compensate": {
      "reversibility": "compensable",          // "readonly" | "compensable" | "irreversible"
      "compensation": {
        "toolName": "delete_record",
        "parameterMapping": { "id": "$.output.structuredContent.id" }  // static path only
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now guard the server and turn on saga mode:

npm install -g chronomcp
chronomcp guard --mode gate --saga -- node examples/server-demo/server.mjs
Enter fullscreen mode Exit fullscreen mode

When the agent runs create_record (OK) then charge_payment (fails), ChronoMCP walks the completed steps backwards and compensates them before the agent even sees the error:

! ChronoMCP: 'charge_payment' failed — starting rollback of 1 step(s)…
  ✓ create_record: compensated (via delete_record)
Enter fullscreen mode Exit fullscreen mode

Two design decisions I'd defend to the death

No LLM in the rollback path. The compensating tool and its parameters are static declarations. Why? Because the moment of "undo" is exactly where a prompt-injected agent would love to improvise ("while you're at it, delete this too"). A deterministic rollback can't be talked into anything.

Compensation ≠ undo, and we say so. A sent email cannot be un-sent; a settled payment isn't reversed by a refund. ChronoMCP never pretends. Irreversible steps are declared and flagged before you approve — not as a surprise after a failure:

│ [DANGER] db-mcp → drop_table
│   table: customers_prod        ← a human catches this in one second
│ reversible: NO — IRREVERSIBLE effect declared by the server
Approve? [y/N]
Enter fullscreen mode Exit fullscreen mode

That honesty is the feature, not a limitation.

Why "protocol-level" matters

Because it works with any MCP server without rewriting your agent, and it's transparent — clients that ignore the metadata keep working. It's the seatbelt you add in front of whatever you already built, not a framework you rebuild on top of. (I wrote a full, honest comparison vs. orchestrators — they're usually complementary.)

Try it / tear it apart

The mcp-compensate spec is a community draft headed for the MCP SEP process. If you author MCP servers, I'd genuinely love the harsh feedback — especially if this vocabulary doesn't fit your tools. Open an issue and let me know where it breaks.

Top comments (0)