AI Agents Need Rollback More Than They Need Autonomy
I have been thinking about transactions in most agent frameworks.
Consider an agent executing a sequence of five tool calls. If the third tool encounters an error, the resulting state is neither the user's intended outcome nor the system's state before execution began. Consequently, the agent has no systematic way to recover, and even a human operator must reconstruct what happened from incomplete evidence.
This issue is not a problem with the tooling itself; it is a fundamental primitive missing from the stack.
Databases have addressed this problem for 50 years, and distributed systems have been grappling with it for decades. A rich terminology exists to articulate this concept: ACID, sagas, compensating actions, idempotency keys, two-phase commit, and write-ahead logs. Maybe some of these concepts have been incorporated into agent frameworks, but I haven't encountered them in production so far.
Currently, the prevailing pattern is as follows:
- Execute a sequence of tool calls.
- If an error occurs, request the LLM to "figure it out."
- Remain hopeful for a favorable outcome.
- Log "task complete" when the loop concludes.
This approach proves effective when agents perform reversible actions within isolated environments. However, it fails when agents interact with file systems, deployments, external APIs with side effects, payment flows, or databases, all of which a human would expect to behave transactionally rather than leaving partial state behind.
The question is not "How autonomous can we make agents?" but rather "How can agents express their intent over operations that necessitate retries, compensation, or rollbacks?"
Will making the LLM intelligent enough to handle these situations be enough? This is the same mistake distributed systems already made, assuming that the application layer would independently resolve these issues. That assumption proved incorrect, and the infrastructure had to take the lead.
The promising next generation of solutions will likely deviate from the concept of smarter loops and instead focus on the following:
- Establishing explicit transaction boundaries.
- Registering compensating actions for each tool.
- Incorporating idempotency keys into tool calls.
- Utilizing replay logs that extend beyond mere chat history.
- Recognizing approval gates as first-class primitives.
- Implementing partial-failure recovery mechanisms that do not require the LLM to engage in reasoning.
Or am I way off? Let me know your thoughts.