DEV Community

Cover image for My AI Agent Didn’t Break. Its Tool Did.
Michael Neang
Michael Neang

Posted on

My AI Agent Didn’t Break. Its Tool Did.

I created this piece of content for the purposes of entering the All Things Agentic Hackathon.

A lot of agent demos assume the world around the agent stays still.

The prompt is the same. The tools are the same. The API behaves the same way every time.

Real systems do not get that luxury.

A provider can rename a field, restructure a response, change an enum, switch units, or change the behavior behind an operation. The agent itself may be completely fine, but suddenly it can no longer complete the job it completed yesterday.

That was the idea I kept coming back to while building ToolSuture:

What if I repaired compatibility around the deployed agent instead of rewriting the agent itself?

That became the project.

ToolSuture — APIs change. Your agent shouldn't have to.

The failure I wanted to reproduce

Most discussions about agent reliability start inside the model:

  • Did it hallucinate?
  • Did it call the wrong tool?
  • Did it plan badly?
  • Should it retry?

Those are important problems, but I wanted to look at a different one.

What happens when the agent is still correct and the tool changes underneath it?

For the main ToolSuture scenario, I froze a Google ADK shipment agent that expects a v1 provider contract.

Then I changed the provider.

The v2 tool still represents the same underlying shipment capability, but the contract is different enough that the original agent no longer understands it correctly.

The usual answer would be to update the integration and redeploy the agent.

I wanted ToolSuture to try something else.

Recover the capability, not the agent

ToolSuture runs a recovery loop:

Observe → Diagnose → Policy → Plan → Validate → Repair → Replay → Verify

It starts with the original mission, the old tool contract, the new tool contract, provider semantics, and runtime evidence.

Then Gemini 3.6 Flash through Vertex AI handles the part I did not want to reduce to a pile of string comparisons:

Do these two contracts still mean the same thing for this mission?

That matters because schema similarity and semantic equivalence are not the same thing.

If the migration is still semantically equivalent, ToolSuture creates a bounded compatibility repair around the frozen agent.

It does not rewrite the agent.

It then replays the original mission against the changed provider and checks whether the recovered workflow actually worked.

The primary demo ends with:

MISSION COMPLETED AND VERIFIED
CAPABILITY_LOST → CAPABILITY_RESTORED
0 BYTES CHANGED
Enter fullscreen mode Exit fullscreen mode

The original deployed agent completes the mission again against Provider V2 without being rewritten.

The part I care about most there is not the green UI.

It is 0 BYTES CHANGED.

The same deployed agent is still there. ToolSuture repaired the compatibility around it.

The harder case was knowing when to stop

Once I had the safe recovery working, I did not want the demo to imply that every API change should be repaired automatically.

That would be reckless.

So I built a second scenario where the change looks superficially manageable but the meaning is different.

The original tool moves a draft into recoverable trash with a 30-day recovery window.

The new provider changes that behavior into irreversible permanent deletion.

At a schema level, those operations can still look related.

Operationally, they are not the same action.

ToolSuture refuses:

REFUSE
CRITICAL
BLOCKED
SAFE_HOLD
0 EXECUTION ATTEMPTS
Enter fullscreen mode Exit fullscreen mode

The red path is intentional. ToolSuture stops before external execution when the semantics become more destructive.

I actually like this result as much as the successful recovery.

The safe case says:

this changed, but it still means the same thing — act.

The dangerous case says:

this looks related, but it no longer means the same thing — stop.

That is a much more useful definition of autonomy than simply giving an agent permission to do more.

The architecture decision that made the project click

The biggest improvement came when I stopped treating recovery as one big AI step.

ToolSuture separates three jobs.

Semantic reasoning

Gemini 3.6 Flash on Vertex AI interprets whether the old and new tool contracts preserve the meaning required by the original mission.

Execution authority

Gemini does not get unrestricted authority to execute arbitrary generated fixes.

A deterministic policy and validation layer decides whether the proposed migration stays inside the allowed repair envelope.

Verification

The recovery path is not allowed to declare itself successful just because the replay looked convincing.

A separate verifier checks fresh provider evidence tied to that specific replay.

That led to the design principle I kept using throughout the project:

The component that performs recovery does not get to certify that recovery succeeded.

ToolSuture separates semantic reasoning, execution authority, and independent verification.

The rest of the stack is intentionally straightforward:

  • Google Agent Development Kit (ADK) for the frozen deployed agent
  • Google GenAI SDK
  • Google Cloud Run for the public application
  • FastAPI
  • MCP
  • Python

I built ToolSuture for the All Things Agentic Hackathon, so I also wanted the Google stack to be doing real work rather than appearing in the architecture diagram as decoration.

Gemini is responsible for semantic reasoning.

ADK is the framework used by the frozen agent.

Cloud Run hosts the live application.

I wanted evidence, not just a nice result screen

One thing I have become increasingly skeptical of in agent demos is the phrase:

“The agent says it succeeded.”

That is not the same as proving the external task succeeded.

So ToolSuture records and verifies evidence from the current replay instead of trusting the agent's own success message.

The current evaluation includes:

  • 3 / 3 repeated verified Cloud recoveries
  • 16 / 16 independent checks on the primary safe replay
  • 5 / 5 blind evaluation scenarios using the frozen recovery engine
  • 0 bytes changed to the deployed agent
  • 0 execution attempts in the dangerous migration

Those numbers are less flashy than adding another feature, but they made me trust the system more.

The goal was never:

“Generate a plausible migration plan.”

It was:

Restore the original capability and prove that it works again.

What I learned

The biggest lesson for me was that AI reasoning is more useful when its authority has clear boundaries.

Gemini is good at interpreting semantic relationships that would be painful to encode as static rules.

But interpreting something, authorizing it, executing it, and verifying it are four different responsibilities.

Separating those responsibilities made ToolSuture much easier to reason about.

I also came away thinking differently about agent reliability.

Before this project, I mostly thought about whether the agent itself could complete a task.

Now I think the better question is:

Can the capability survive changes outside the agent, and can the system prove that it still works afterward?

That is what ToolSuture is testing.

Try ToolSuture

Live demo:

https://toolsuture-fx7bbo3mpq-wl.a.run.app/

Source code:

https://github.com/mneang/toolsuture

Hackathon:

https://allthingsagentichackathon.devpost.com/

APIs change. Your agent shouldn't have to.

Top comments (0)