Your AI Agent's Tests Are Lying to You — IBM Studied 2,572 of Them

Cover illustration: Your AI Agent's Tests Are Lying to You — IBM Studied 2,572 of Them

Your AI Agent's Tests Are Lying to You — IBM Studied 2,572 of Them

Your AI agent's test suite is green. Every check passes. You ship it — and in production it refunds the wrong order, leaks a tool's internal error to a customer, or quietly hallucinates success while doing nothing at all.

This isn't a hypothetical. Researchers from IBM Research, Georgia Tech, and the University of Georgia just published Tangent at ASE '26 (this week, in Munich): the first large-scale empirical study of how developers actually test LLM-based agent applications. They mined 1,190 Python repositories built on LangChain, LangGraph, and MCP, identified 1,723 agents and 4,111 tools, and manually labeled 2,572 test methods across 240 test modules. Their conclusion is uncomfortable: the way the industry tests agents is narrow, shallow, and blind to exactly the failure modes that bite in production.

What the researchers did

Concept diagram: the Tangent study's taxonomy of 23 agent testing patterns

Rangeet Pan and colleagues built a dataset the hard way. Starting from 1,190 candidate GitHub repos, they used static analysis to find real agent and tool code, filtered down to repos with test suites, then used a panel of labeling agents (Gemini 2.5 Flash) plus an adjudicator (Gemini 2.5 Pro) to find agent-related test modules — and then manually labeled 2,572 test methods along multiple dimensions.

From that, they developed a taxonomy of 23 testing patterns in four categories:

Test fixtures — what gets mocked. 34.4% of tests mock an agent or tool in some form (22.3% mock the entire agent, 21.7% mock selected components like the LLM call or memory). Only 13.4% of mocks are custom test doubles; the rest are stock unittest.mock patches.

Test data — what inputs tests use. 54% use realistic synthetic data, but a striking 39.9% rely on simple dummy data — placeholder inputs like test1, test2 that represent nothing a real user would ever type.

Test objectives — what gets validated. 61.8% of tests are unit-level, exercising individual tools or agents in isolation. About a third target interaction behavior. Only 7.5% address non-functional requirements like security and performance. Just 10% are end-to-end tests.

Test assertions — how correctness is checked. 55.9% assert on output, 51.2% on state. But only 8.7% assert on reasoning-related behavior — and even those mostly check that reasoning exists (e.g., "researcher" appears in the logs), not whether the reasoning was correct or useful.

They complemented the mining with structured interviews of 10 senior industry practitioners building agentic systems. The verdict matched: industry teams emphasize non-functional testing a bit more than open-source projects do, but both sides share the same gaps — no formal testing foundations, unclear test objectives, and chronic trouble generating high-quality test data.

Why it matters

If you build with AI agents, this paper is a mirror — and the reflection isn't flattering. Three findings deserve your attention:

You're testing presence, not correctness. The most damning statistic: tests that check the agent's reasoning verify it happened, not that it was right. An agent that delegates to a subagent, gets garbage back, and cheerfully reports it as success will pass a test that only checks "subagent activity appears in the logs." That's the test equivalent of checking that the fire alarm is mounted on the wall without ever setting off smoke.

Mocks hide the failures you're most afraid of. When you mock the LLM, the tool, and the environment, you're testing your plumbing, not your agent. The paper's finding that developers mock heavily while testing only 10% end-to-end means most agent codebases have never once been exercised the way production exercises them — non-deterministic model in the loop, real tools, real latency, real failures.

Dummy data is a false sense of security. A PII-redaction test with one sample record (name, email, phone) proves nothing about the dozens of other sensitive-data shapes the agent will meet. The authors note agentic systems lack the coverage hierarchies traditional testing takes for granted — so teams default to a handful of illustrative examples and call it done.

The paper cites real stakes: agent failures ranging from embarrassing (a store agent handing out unintended giveaways) to serious (sensitive-data breaches). As agents get more autonomy — and more access to your tools, files, and money — the testing gap between "CI is green" and "it actually works" becomes a liability.

How YOU can use it

Workflow diagram: practical agent testing protocol — golden-path E2E test, trace assertions, fault injection, adversarial fixtures

You don't need a research lab to apply this. Here's a practical testing protocol distilled from the paper's findings — the checks most agent codebases are missing:

1. Write one golden-path E2E test with a REAL model in the loop

The paper's headline gap: only 10% of tests are end-to-end. Pick your most important user flow and test it with an actual LLM call (cached recordings are fine; a mock is not). Assert on five things, not one:

 import pytest  def test_agent_refund_golden_path(real_llm, tmp_db):     # REAL components where it matters: no mocked LLM     agent = SupportAgent(llm=real_llm, tools=[refund_tool, policy_lookup])      trace = agent.run_with_trace("Refund order #48291, it arrived broken")      # 1. Output: did it say the right thing?     assert "refund" in trace.final_answer.lower()      # 2. Reasoning trace: did it call tools in the right ORDER?     tool_calls = [s.tool for s in trace.steps if s.kind == "tool_call"]     assert "policy_lookup" in tool_calls, "agent skipped the policy check!"     assert tool_calls.index("policy_lookup") < tool_calls.index("refund_tool")      # 3. Side effects: did the world actually change?     assert tmp_db.order(48291).status == "refunded"      # 4. Budget: did it stay within cost limits?     assert trace.total_tokens < 4000, f"token burn: {trace.total_tokens}"      # 5. Latency: would a human wait for this?     assert trace.wall_time < 30, f"too slow: {trace.wall_time:.1f}s" 

That single test covers more of what production cares about than fifty unit tests with mocked tools.

2. Assert on the reasoning trace, not just the final text

Only 8.7% of tests in the study check reasoning — be in that minority. Use your framework's trace/observability output (LangSmith, Langfuse, or a simple step log) and assert on the sequence: which tools were called, in what order, with what arguments. An agent that refunds before checking the refund policy is broken even when the final message sounds perfect.

3. Break a tool on purpose (fault injection)

The paper calls for fault-based testing tailored to agents. Implement the cheapest version today: wrap one tool so it always fails, and assert the agent degrades gracefully instead of hallucinating success:

 def test_agent_survives_tool_outage(real_llm):     agent = SupportAgent(llm=real_llm, tools=[always_failing(refund_tool)])      result = agent.run("Refund order #48291, it arrived broken")      # An agent that silently "succeeds" or double-refunds here is a bug.     assert result.needs_human_review or "unable to process" in result.text.lower() 

4. Replace dummy data with adversarial fixtures

Retire test1, test2. For every tool your agent can call, keep a fixture set of the nastiest realistic inputs: ambiguous requests, contradictory instructions, PII-shaped strings, oversized payloads, and unicode edge cases. The study's 39.9% dummy-data figure is your reminder that example inputs test the happy path you already believe works.

Where to start this week

Pick your agent's single highest-stakes flow (refunds, file deletion, sending messages, spending money). Write the golden-path test from step 1 for it. Then add the fault-injection test from step 3. Those two tests alone put you ahead of most of the 1,190 repositories IBM studied — and they take an afternoon.

Key takeaways

  • Agent testing is overwhelmingly unit-level (61.8%) — most codebases never exercise the full loop the way production does.
  • Tests check that reasoning happened, not that it was correct — only 8.7% of assertions touch reasoning behavior.
  • Heavy mocking + dummy data = tested plumbing, untested agent — 34.4% of tests mock the agent or tools; 39.9% use placeholder inputs.
  • Non-functional testing is nearly absent — just 7.5% of tests cover security, performance, or cost.
  • The fix is cheap: one golden-path E2E test with trace assertions, one fault-injection test, and adversarial fixtures close most of the gap.

Read the original paper: "Tangent: An Empirical Study of Testing Practices for LLM-Based Agent Applications" — Rangeet Pan, Tyler Stennett, Divya Sankar, Bridget McGinn, Alessandro Orso, Raju Pavuluri, Saurabh Sinha, Maja Vukovic (IBM T.J. Watson Research Center, Georgia Institute of Technology, University of Georgia) — arXiv:2608.08413 (presented at ASE '26, Munich).

Comments

Popular posts from this blog

3,000 Lines vs 512,000: The Tiny Agent Harness That Nearly Matches Claude Code

Silent AI Video Is Dead: This Open-Source Model Dreams Up Movies and Soundtracks Together

Your AI Agent Works in the Lab and Fails at Your Desk — Training It in 18 Setups Fixes That