DEV Community

Cover image for I built agent-inspect to debug TypeScript AI agent trajectories

I built agent-inspect to debug TypeScript AI agent trajectories

Raju Dandigam on August 25, 2026

Your AI agent failed. Again. The final answer is wrong, but the logs look fine: tool call started model call started tool call completed model...
Collapse
 
mudassirworks profile image
Mudassir Khan

the healthy vs regression trajectory comparison is the clearest framing of this problem I've seen. we had the exact generate_answer before retrieve_policy failure in prod for about six weeks — output quality stayed high enough to pass eval because the model guessed well from context. routing bug was invisible.

the part of agent-inspect I'm most curious about is the deterministic contract layer. are the contracts structural (tool A before tool B) or temporal (A within X ms of B)? the temporal version is where most interesting failures live in practice.

does trajectory diff work across retries, or does each attempt get its own trace root?

Collapse
 
raju_dandigam profile image
Raju Dandigam

@mudassirworks, that six-week example is exactly why I prefer contracts over output-only evals. The useful assertions are primarily structural—required or forbidden operations, causal order, completion, and outcomes—and budget-oriented, such as run or step duration and token ceilings. I’m wary of tight “A within X ms of B” rules because CI jitter can make them brittle; duration SLOs are safer when the threshold has operational meaning. Retries remain under one trace root as distinct step occurrences when they are visible to the instrumentation, so trajectory comparison can reason about the retry shape rather than treating every attempt as a separate run. Internal client retries still need to be surfaced by the adapter.

Collapse
 
mudassirworks profile image
Mudassir Khan

the duration SLO framing makes way more sense than timeout assertions — we burned a couple sprints on flaky tests where the threshold was "fast enough on dev hardware" rather than "signals a real regression."

the retry as distinct step occurrence model is the piece I haven't fully reasoned through. if an adapter surfaces retries, do contract violations during the retry (correct final outcome, wrong causal path) count as failures in your experience?

Thread Thread
 
raju_dandigam profile image
Raju Dandigam

Yes—when the contract is protecting a causal or safety property, I would count the retry-path violation as a failure even if the final answer is correct. A caught retry can leave the overall run successful, but it should not erase the failed tool occurrence or an invalid sequence such as a side effect happening before approval.

The important caveat in the current 6.17.6 behavior is that the default requiredOrder rule uses first-occurrence ordering. It does not automatically mean “this must hold for every retry.” Failure/retry limits and forbidden/max-call rules can evaluate the separate finished tool occurrences, but an every-occurrence ordering guarantee needs a stricter rule.

That gap is exactly what the open causal-ordering contribution is exploring: opt-in happens-before and all-occurrences modes while preserving the compatible default: github.com/rajudandigam/agent-insp...

My practical split is: tolerate and report an expected transient retry, but fail the gate when any attempt crosses an authorization, idempotency, or required-order boundary. Does that match the sort of retry failures that cost you those sprints, or were yours mostly timing variance without a semantic path change?

Thread Thread
 
mudassirworks profile image
Mudassir Khan

mostly timing variance in our case, but the semantic line is exactly the split we missed. we had retries that looked like transient failures but were masking an approval step that had quietly been removed from the standard path a sprint earlier. retry succeeded, output correct, path wrong.

the all occurrences mode sounds like the right default for authorization steps. how’s the opt in designed — at the rule level or the contract level?

Thread Thread
 
raju_dandigam profile image
Raju Dandigam

@mudassirworks, I’d put the opt-in at the individual rule level, then allow a contract-level default only as shorthand. Authorization ordering usually needs all-occurrences semantics, while another rule in the same contract may intentionally care only about the first successful occurrence. A rule such as { order: [...], occurrenceMode: "all" } keeps that intent reviewable; the contract can set defaultOccurrenceMode for safety-heavy suites without removing per-rule overrides. Your removed-approval example is exactly the case that should fail even when the retry recovers.

Collapse
 
reidmarlow profile image
Reid Marlow

This is the level where agent debugging starts to feel sane. A flat log tells you calls happened. A trajectory tree tells you which branch lied to you. I like the Evidence bundle angle too, since CI needs artifacts a reviewer can read without replaying the whole run.

Collapse
 
raju_dandigam profile image
Raju Dandigam

Thanks @reidmarlow really appreciate this. That “calls happened” vs “which branch actually went wrong” distinction is exactly the problem AgentInspect is trying to solve.

And yes, the Evidence bundle is meant to make the trace useful beyond local debugging too something you can hand to a reviewer in CI or a PR without replaying the run or sharing the raw trace.

Glad that part resonated.

Collapse
 
raju_dandigam profile image
Raju Dandigam

Another thank-you round for people whose writing kept pushing me toward better answers around state drift, evaluation, observability, and trustworthy agent behavior.

Shout-out to @dovzhikova @engtwindev @ev3lynx727 @fazal_mansuri_ @gde @googleai @happynood @kgjohnson @kirandeepjassalcrypto @marcossouzadotdev

A lot of the thinking behind agent-inspect came from seeing similar problems show up across different stacks. If you get a chance to read the launch post, I’d really value your thoughts.

Collapse
 
raju_dandigam profile image
Raju Dandigam

A big thank-you to a group of folks whose posts and discussions helped sharpen how I think about agent reliability, tool boundaries, observability, and human-debuggable workflows while building agent-inspect.

Really appreciate the ideas and pressure-testing from @aidam @akilahngqueen @anthonymax @bokuwalily @coder11 @curi0us_dev @dailycontenthub @davidloibner @debashish_ghosal @dipankar_sarkar

If agent trajectories, tool-call receipts, and local-first debugging are themes you care about too, I’d genuinely love your feedback on the article and the direction of the project.

Collapse
 
raju_dandigam profile image
Raju Dandigam

I also wanted to thank more builders who’ve been exploring the hard parts of agent systems in public: tool selection, test reliability, memory, failure paths, receipts, and production-safe automation.

Appreciate the signal from @qawalah @sapph1re @shogun_the_grt @swapnanilsaha @trknhr @tsvetang2 @tznthou @vezzu_ruthvik @waxell @webpro255 @wyndev

If this article resonates, I’d love for you to poke holes in it, disagree with it, or suggest where agent-inspect should go next.

Collapse
 
pravesh_sudha_3c2b0c2b5e0 profile image
Pravesh Sudha

Great guide

Collapse
 
raju_dandigam profile image
Raju Dandigam

@pravesh_sudha_3c2b0c2b5e0, thanks for reading. If you try the keyless demo, I’d be especially interested in whether the execution tree, deterministic CI gate, or reviewable evidence bundle is the most useful part of the workflow for you.

Collapse
 
debashish_ghosal profile image
Debashish Ghosal

Great article, Raju!

My Key Takeaways:
Spotting the right answer for the wrong reasons: you have nailed a huge pain point in agent development—an agent can spit out a totally plausible answer while doing horrifying things under the hood (like skipping retrieval, calling the same tool twice, or taking an absurdly expensive fallback path).

Local-first privacy is a huge win: In a space flooded with heavy SaaS observability tools asking for API keys and telemetry subscriptions, keeping this lightweight, local-first, and redacted by default makes it infinitely easier to drop traces directly into PRs without leaking data.

I was thinking about this - how about you add zero-friction wrappers or auto-instrumentation. Having to manually wrap execution blocks in inspectRun and step() adds noticeable boilerplate to codebase routines. Building auto-middleware hooks for standard TypeScript setups—like Vercel AI SDK or standard OpenTelemetry spans—would make the adoption low barrier.

How does it handle legitimate model creativity vs. actual test flakiness in CI? Since non-deterministic LLMs will naturally swap tool order or take alternative valid paths depending on minor prompt tweaks, how do you set tight contract assertions without making the build pipeline fragile?

Thanks again! Looking forward to great things!

Collapse
 
raju_dandigam profile image
Raju Dandigam

Thanks @debashish_ghosal both are important points.

On instrumentation, I agree that asking developers to manually wrap every agent step won’t scale. AgentInspect already supports framework adapters for common paths, and reducing setup friction further is definitely an area I want to keep improving.

For CI, I don’t think the goal should be to force an agent to take the exact same path every time. The better approach is to test behavioral invariants for example, a required tool was used, a forbidden tool was not used, the run completed, or an expected outcome was observed.

That way, different valid trajectories are still allowed, while real regressions remain deterministic to catch.

Thanks for raising these, they’re exactly the kinds of questions that matter for practical agent debugging and testing.

Collapse
 
richard_smith_154156d471ef profile image
Richard Smith

The "right answer for wrong reasons" problem is so real. I've spent way too long assuming an agent worked correctly just because the output looked good.

Collapse
 
raju_dandigam profile image
Raju Dandigam

@richard_smith_154156d471ef, same here—that false confidence is what pushed me toward trajectory checks. The output tells us what the user saw, while the trace can prove whether retrieval, validation, and required tools actually happened before the answer. A plausible result should not erase a broken path.

Collapse
 
rohitnirban profile image
Rohit Yadav

How does AgentInspect handle valid variations in an agent’s trajectory without making CI tests too strict or flaky?

Collapse
 
raju_dandigam profile image
Raju Dandigam

@rohitnirban, the key is to assert invariants rather than one golden path. For example: retrieval happened before generation, no forbidden write ran after a policy block, the run completed, retries stayed within budget, and one of several allowed tool branches was used. Different wording, ordering among independent siblings, or valid alternative branches can still pass. In agent-inspect, I’d use deterministic checks for those structural facts and leave semantic answer quality to a separate evaluation layer.

Collapse
 
trknhr profile image
Teruo Kunihiro

This feels like a very good direction. Testing only the final answer misses a lot of important agent failures, so making tool usage, ordering, retries, and validation steps testable in CI makes a lot of sense.

I especially like that the contracts focus on invariants rather than requiring one exact trajectory that seems like the right balance for nondeterministic agents. The local-first design and evidence bundles are nice touches too. Curious how it handles parallel calls and nested agents, but this looks genuinely useful.

Collapse
 
raju_dandigam profile image
Raju Dandigam

@trknhr, parallel calls are represented as sibling steps under the same parent, while nested agents or tools keep explicit parent-child relationships. Each step retains its own lifecycle and duration, so sibling durations are not incorrectly added as though the work were sequential. The contract layer can assert parentage and required dependencies without forcing one completion order.