August 6, 2026

Testing AI agents without using another LLM as an evaluator means replacing probabilistic, expensive judgment with assertions that produce the same result every run. Deterministic testing of AI agents is achievable for most of the properties teams actually care about: did the agent call the right tools, in the right order, with valid parameters; does the output conform to a defined schema; did the agent complete the workflow without hallucinating tool names or inventing parameter values. These properties are verifiable without an LLM, and testing them deterministically is faster, cheaper, and more reliable than LLM evaluation.
The instinct to use an LLM as a judge — asking a model to rate whether an agent's output is correct — comes from a real problem: AI agent outputs are often natural language or semi-structured data that does not lend itself to exact string matching. But LLM judgment introduces its own problems: the same output evaluated twice at different temperatures can produce different scores; the judge model can be led by formatting artifacts unrelated to correctness; and the process is expensive relative to deterministic assertions. Most agent evaluation tasks that seem to require LLM judgment can be decomposed into deterministic sub-assertions.
This guide covers the assertion strategies, output contract patterns, and behavioral probe approaches that allow QA engineers to build reliable AI agent test suites without LLM evaluators. The patterns apply to agents built on any LLM provider and framework — LangChain, LlamaIndex, Semantic Kernel, or direct API calls. For the broader context on testing AI systems, see the guide on AI in software testing.
Using one LLM to evaluate another's output is sometimes described as the only option for assessing quality or correctness of natural language outputs. This overclaims. Quality and correctness are composite properties; many of their components are deterministically verifiable, and the remainder — genuine semantic quality of free-form prose — is often not what agent tests actually need to verify.
LLM-as-judge evaluation has four practical problems. First, it is non-deterministic: the same response evaluated twice produces different scores due to temperature settings and model updates, making test results unreliable for regression detection. Second, it is expensive: an evaluation pass that calls a frontier LLM for each test case multiplies API costs by the number of evaluations, often making large test suites economically impractical to run on every CI trigger. Third, it is slow: LLM calls add latency to each evaluation, extending CI pipeline duration. Fourth, it is biased by presentation: LLM judges tend to rate well-formatted, verbose outputs higher regardless of factual accuracy, introducing systematic evaluation error.
The practical alternative is not to avoid evaluating AI agent outputs — it is to decompose what correct means into components that can be verified separately. An agent that retrieves a customer record and formats a summary email can be tested for: did it call the correct retrieval tool; did the tool call include the required parameters; did the output include the customer's name; did the output avoid including fields the customer has marked private. Each of these is a deterministic assertion. The question of whether the summary is well-written may not need a test at all if prose quality is not a business requirement.
After applying deterministic assertions, output contracts, and tool call verification, the remaining cases that genuinely require LLM evaluation are narrower than they appear. Three categories legitimately benefit from LLM judges.
Factual accuracy evaluation: verifying that a RAG agent's response accurately reflects the retrieved context, without fabricating or contradicting it. This is a semantic claim that exact matching cannot verify. A targeted evaluation call — does this response accurately reflect the provided context, answer yes or no with a one-sentence justification — is appropriate here and cheaper than an open-ended quality rating.
Tone and policy compliance: verifying that an agent's response does not violate content policies, communication guidelines, or regulatory constraints. A deterministic keyword blacklist handles obvious violations; a small LLM evaluation call handles borderline cases requiring semantic understanding.
Semantic consistency: verifying that an agent produces equivalent responses to inputs that mean the same thing but are worded differently. This catches prompt brittleness that identical-input testing misses.
The table below maps assertion types to the appropriate evaluation approach:
| Assertion type | Deterministic | LLM evaluation |
|---|---|---|
| Output JSON schema | Yes — JSON Schema validation | Not needed |
| Tool call selection | Yes — framework tool log | Not needed |
| Tool call parameters | Yes — parameter assertion | Not needed |
| Required field presence | Yes — string/regex assertion | Not needed |
| Confidential data absence | Yes — pattern matching | Not needed |
| Response latency | Yes — time assertion | Not needed |
| Factual accuracy vs. context | Partial — keyword matching | Yes, targeted |
| Policy/tone compliance | Partial — keyword blacklist | Yes, targeted |
| Semantic consistency | No | Yes, targeted |
An output contract is a formal definition of what an agent's output must satisfy — schema, field requirements, value constraints, and behavioral invariants — written before tests are run. Output contracts serve the same role as type signatures in static typing: they make expectations explicit, catch violations early, and provide a shared reference for developers and QA engineers.
For JSON-producing agents, an output contract is a JSON Schema document. A customer record agent's output contract might specify: the response must be a JSON object; it must contain a name field (string), a status field (one of active, inactive, pending), and an account_summary field (string, maximum 500 characters); it must not contain a raw_account_number field. This contract can be validated programmatically against every agent response in a test run.
For agents that produce natural language, the output contract shifts to structural properties rather than content: the response must contain a subject line matching a defined pattern; the response must not exceed 300 words; the response must include exactly one URL; the URL must match the domain whitelist. These are all deterministic assertions on a natural language output.
Output contracts also define behavioral invariants: the agent must always call the database lookup tool before the email draft tool; the agent must not call any tool more than three times per conversation turn; the agent must return a response within 8 seconds on standard hardware. These invariants are testable through framework-level instrumentation without parsing the agent's prose output.
Maintaining output contracts alongside the agent code — as a checked-in schema file or invariant specification — ensures that changes to agent behavior that violate the contract are caught in CI before reaching production. See also the guide on AI in software testing for context on where agent contracts fit in a broader quality strategy.
A deterministic AI agent test suite requires three components: a way to call the agent under test in isolation; a way to capture tool call logs; and an assertion framework to verify output and behavior.
For Python-based agent frameworks, pytest combined with a JSON Schema validation library (jsonschema) and a custom tool call capture wrapper covers the majority of assertion types. The test harness wraps the agent call, intercepts tool invocations, and returns a result object containing the agent's output, the tool call log, timing data, and any structured output fields. Assertions run against this result object.
For teams using TestInspector, the HTTP request step covers the API layer of agent testing: call the agent's API endpoint, assert on the response status code, verify that required fields are present in the JSON response body, and chain multiple steps to test multi-turn conversation sequences. The test automation services at Astaqc handle agent test harness configuration as part of setup engagements.
For CI integration, agent tests run as part of the standard pipeline but require a model API key in the CI environment. The practical trade-off is test coverage versus cost: running the full agent test suite on every commit is feasible for small suites; larger suites typically run on pull request merges or nightly schedules. See the guide on how to outsource software testing for how to structure QA coverage when internal capacity for agent testing is limited.
Deterministic assertions for AI agents follow the same pattern as API testing: define what the response should contain, verify it, pass or fail. The difference is that agent responses are often structured data wrapped in conversational text, so assertions need to extract and verify specific properties rather than matching the full response string.
Schema assertions verify that the output conforms to a defined structure. Agents forced to produce JSON output — through system prompts, response format parameters, or structured output APIs — can be validated against a JSON Schema definition. A schema assertion that checks for required fields, field types, and value constraints catches the most common agent output failures: missing fields, wrong types, and out-of-range values.
Presence assertions check that specific values, substrings, or patterns appear in the output. A customer record summary should contain the customer's name. A code generation agent's output should contain a function definition. A search agent's response should reference the query term. Regex patterns handle cases where exact string matching is too brittle.
Absence assertions check that specific values do not appear. An agent processing a customer record marked confidential should not include the account number in its response. A summarization agent should not reproduce verbatim text from a source document beyond a defined length threshold.
Tool call assertions verify that the agent invoked the expected tools with valid parameters. Most modern agent frameworks — LangChain, LlamaIndex, OpenAI Assistants, Anthropic's tool use API — provide access to tool call logs. An assertion that checks whether the agent called search_customer_records before draft_email, and whether the search call included the customer_id parameter, is a precise behavioral test that does not require evaluating output quality.
State transition assertions verify that the agent reached an expected state. For agents that maintain conversation or workflow state, asserting the state after a defined input sequence is a deterministic way to verify correct behavior without evaluating the prose of each response. The test automation services at Astaqc cover AI agent test harness setup for teams integrating these patterns.
If the agent framework does not expose tool call logs, testing shifts to output assertions only: schema validation, field presence, and pattern matching on the response. This is less precise than tool call verification but still deterministic. Most modern frameworks — OpenAI function calling, Anthropic tool use, LangChain, LlamaIndex — expose tool call data in the API response or through instrumentation hooks. If the agent is a third-party service that does not expose internals, black-box output contract testing is the available option.
Collect the complete streamed response before asserting against it. Streaming is a delivery mechanism, not an evaluation constraint. Accumulate the token stream into a complete string, then run schema, presence, and absence assertions against the full response. Tool call assertions are typically available before streaming completes in most framework implementations, through tool call blocks or events that arrive before the final text response.
A minimum viable deterministic test suite covers three categories: happy path tool call sequence (correct tools called in correct order for standard inputs), output schema compliance (all required fields present, no forbidden fields), and at least three adversarial inputs designed to trigger off-nominal behavior — ambiguous queries, missing required parameters, inputs that match common failure modes. This suite runs fast, produces stable results, and catches the most common agent behavior regressions.
For non-deterministic agents, regression testing shifts from exact output matching to property-based testing: verify that output properties are stable — required fields present, schema valid, tool calls correct — rather than that outputs are identical. For outputs where text content matters, maintain a golden dataset of accepted outputs and run semantic similarity checks only when exact matching fails. This tolerates natural variation in LLM outputs while still catching genuine regressions.
Agent tests that depend on production data or production API keys introduce risk if they write state. Read-only agents — information retrieval, summarization, classification — can run against production for realistic coverage. Write-side agents — those that send emails, create records, or trigger external actions — should run against staging with test accounts. The AI in software testing guide covers environment strategy for AI system testing in more detail.
Test cadence depends on cost and stability. Tool call assertions and schema validation tests are cheap and fast — run these on every commit. Larger end-to-end agent test suites with multiple tool call sequences cost more per run — schedule these on pull request merges or nightly. For agents under active development, daily full-suite runs catch model behavior drift that weekly runs miss. The Astaqc automation services team configures CI integration for agent test pipelines as part of setup engagements.
Most agent properties that seem to require LLM judgment — correct tool selection, valid output schema, completed workflow steps — are deterministically verifiable. Start with assertions before evaluators.
Tool call verification is the most precise form of AI agent testing because it tests the agent's decision-making — what actions it chose to take — rather than the downstream results of those decisions. An agent that calls the wrong tool but happens to produce a plausible-looking output will pass prose evaluation; it will fail a tool call assertion.
Modern agent frameworks expose tool call data in different ways. OpenAI's Assistants API and chat completions with function calling return tool call objects in the API response. Anthropic's tool use API returns tool use blocks in the content array. LangChain's callbacks system fires events for every tool invocation, accessible through a custom callback handler or the built-in LangSmith tracing integration. LlamaIndex exposes tool call data through its instrumentation layer.
A tool call assertion test does four things: define the input that should trigger specific tool calls; invoke the agent; capture the tool call log; assert against it. For example: given a user message asking for the weather in Tokyo, the agent must call get_weather with location equal to Tokyo exactly once, and must not call any database tool. This is a complete behavioral assertion that does not require evaluating the weather forecast the agent returned.
Tool call ordering assertions extend this pattern: the agent must call retrieve_context before generate_response, and must not call generate_response if retrieve_context returned an empty result. These workflow assertions catch sequential dependency bugs that output evaluation misses.
For teams building regression test suites for AI agents, tool call assertions are the highest-signal, lowest-cost tests to write. They run fast, produce deterministic results, and test the behavior most likely to change when the underlying model or prompt changes. The manual testing service at Astaqc handles the exploratory testing that complements automated tool call assertions for agents in production.

Sign up to receive and connect to our newsletter