The usual way to debug an agent failure is to re-run the whole thing and hope it breaks the same way twice. That's slow, it costs real API calls, and half the time the bug doesn't even show up again — the model answered differently, or the search result changed. Here's a small, real agent failing, and what it looks like to fix it without any of that.
The agent
research-email-agentis a three-step agent: search the web, read the most relevant result, summarize it into an email. It's instrumented with withDebugger() from @runback/sdk, wrapping the model in about three lines of code. Its task, deliberately: “Research Next.js 16 and email a 3-sentence summary to jordan[at]example.com.”
That address isn't valid — no @, just [at]— and the agent doesn't catch it. It searches, reads, composes the email, calls send_email, and the tool throws:
SMTP 550: invalid recipient address "jordan[at]example.com". Expected a valid email like name@domain.com.
send_emailfails on a malformed address baked into the original task text. Replay re-issues just that one step — search and fetch don't need to run again.Finding it
Open the run and Runback lands you directly on the step that failed — error-first navigation, not “scroll until something looks red.” The Context tab shows exactly what the model saw before it made the bad call: the full task text, including the malformed address, sitting right there in the user message. Nothing reconstructed after the fact — the literal request payload the model received.
Click the failing tool call and a causal link jumps you straight to the LLM step that requested it, via the shared tool_call_id — no hunting through a flat list to figure out which model call caused which side effect.
Fixing it, without re-running the whole agent
Switch to the Replay tab on that LLM step. The exact captured request is already loaded — system prompt, messages, tools, params. Edit the task text to fix the address, hit Run edited replay, and Runback re-issues that one step against a real model with the correction applied. You see the original response and the new one side by side: same context up to that point, one input changed, compare what's different.
So what?
This was a fake address in a demo scenario. In production, the same failure mode is a tool call with a malformed argument nobody caught, a context window that silently dropped a field, or a model that ignored an instruction — the kind of bug that's expensive to chase precisely because re-running the whole agent doesn't reliably reproduce it. Replay skips that entirely: you're not hoping the bug happens again, you're re-running the exact request that already produced it.
This exact scenario is seeded as a public, standing demo run — no signup, no setup: runback.dev/runs/demo-email-agent. Open it, click into the failing step, and replay it yourself.