AI agents and automation Assemble manually

How to test an AI agent

AI agent testing isn’t about “works or doesn’t work”—it’s about reliability, security, and predictability in real-world scenarios. We break down tools, pipelines, and common pitfalls.

What to test in an AI agent?

An AI agent isn’t just an API call—it consists of a chain: Intent → Context → Tool Selection → Tool Invocation → Result Processing → User ResponseTesting must cover each stage: intent parsing correctness, proper tool invocation, error handling, fallback logic, and final answer relevance. Lack of testing at this level leads to “silent failures”: the agent doesn’t crash but performs incorrect actions.

Test Pipeline Structure

flowchart TD  
    A[Scenario: “Order Coffee”] --> B[Unit Tests for Tools]  
    B --> C[Mocked LLM Call with Fixed Context]  
    C --> D[Tool Selection Verification]  
    D --> E[Integration Call to Real Tool]  
    E --> F[Result Validation]  
    F --> G[Evals: Relevance, Safety, Usability]  
    G --> H[Fallback: If Tool Is Unavailable]

Unit-test tool (example)

// test/tools/test_order_coffee.js  
test('orderCoffee: returns order ID with valid data', () => {  
  const mockDB = { saveOrder: jest.fn().mockResolvedValue('order_123') };  
  const result = await orderCoffee({  
    user_id: 'u_777',  
    drink: 'latte',  
    size: 'm',  
    mockDB  
  });  
  
  expect(mockDB.saveOrder).toHaveBeenCalledWith({  
    drink: 'latte',  
    size: 'm',  
    status: 'pending'  
  });  
  expect(result).toEqual({ order_id: 'order_123' });  
});

Important: Test tools as pure functions—without LLM, without external dependencies. This ensures the error is not in the tool itself, but in how it’s called.

Mocked LLM Logic Test

Use fixtures to simulate LLM responses. This lets you test how the agent responds to different phrasings and errors.

// test/agent/plan_step.js
test('agent selects orderCoffee when asked to "order a latte"', () => {
  const mockLLM = jest.fn().mockResolvedValue({
    tool_name: 'orderCoffee',
    tool_args: { drink: 'latte', size: 'm' }
  });

  const agent = new Agent({ tools: [orderCoffee], llm: mockLLM });
  const plan = await agent.plan('Please order a medium latte');

  expect(plan.tool_name).toBe('orderCoffee');
  expect(plan.tool_args.drink).toBe('latte');
});

Such tests catch errors in prompts, JSON parsing, and tool selection logic.

Common Mistakes in Testing

  • We’re testing only the “happy path.” — The agent must correctly handle: ambiguous queries, unavailable tools, invalid arguments, and timeouts.
  • Ignore logs — Without structured logs (trace_id, tool_call_id, confidence_score), it’s impossible to pinpoint exactly where the agent “derailed.”
  • Testing only on one LLM — Different models (GPT-4o, Claude 3.5 Sonnet) interpret instructions differently and return JSON. Verify with 2+ models.
  • No fallback tests — If the tool is unavailable, the agent must either re-ask or escalate to a human. This is critical for security.

AI Agent Testing Checklist

  • ✅ Unit tests for all tools (including edge cases: empty ID, negative amount)
  • ✅ Mocked tests for tool selection and JSON parsing
  • ✅ End-to-end scenarios: “Order coffee”, “Cancel order”, “Check status”
  • ✅ Fallback tests: tool unavailable, LLM returned invalid JSON, timeout
  • ✅ Evals: relevance (LLM-as-a-judge), safety (prompt injection), usability (clarity of phrasing)
  • ✅ Logging: trace_id, timestamp, tool_call_id, confidence_score, error_type

Next step: evals pipeline

After unit and integration tests, run automated evals on real or synthetic data:

flowchart LR  
    A[Scenario: 100 requests] --> B[Launch agent]  
    B --> C[Save trace_id + logs]  
    C --> D[Evals engine]  
    D --> E1[Relevance]  
    D --> E2[Security]  
    D --> E3[Tool accuracy]  
    D --> E4[Latency]  
    E1 & E2 & E3 & E4 --> F[Report: score, failure cases]

Example tools: langfuse (traces), ragas (relevance), guardrails-ai (safety), pytest-asyncio (auto-tests).