The Tool-Call Checklist for QA Engineers
Suneet Malhotra
Sep 12, 2026
The fastest way to find an agent bug is to inspect the tool call, not the final sentence.
An agent may answer with perfect grammar after selecting the wrong tool, inventing an argument, or attempting an action that the user never authorized. A text assertion can miss all three failures because the final answer is only a summary of a decision that already happened.
For QA, the useful boundary is the tool invocation: selected tool, arguments, authority, result, and user-visible claim. Test that boundary directly.
A small synthetic example
Imagine a support agent with three tools:
search_orders(customer_id, date_range)reads order history.create_return(order_id, reason)starts a return request.cancel_order(order_id)cancels an order.
The user says, "Find my recent order and tell me whether I can return it." The expected behavior is a search followed by an explanation. A return should not be created. A cancellation is outside the request entirely.
The agent can fail in several ways while still sounding helpful. It can call create_return because the phrase "can I return" was treated as an instruction. It can call search_orders with a different customer ID from the authenticated session. It can call cancel_order after a retry replays an earlier intent. It can return a confident answer after the search failed and no order data was available.
Those are not writing defects. They are decision and authorization defects.
The five assertions
Start with five assertions for every tool-capable workflow.
1. Tool selection
Assert that the selected tool belongs to the set allowed for the user intent. For the synthetic request, search_orders is allowed and the two mutation tools are not. This is more precise than asserting that the answer contains the word "return."
2. Argument integrity
Assert arguments against trusted request state, not only against the model output. The customer ID should come from the authenticated principal. A date range should have a declared default and a bounded format. Reject unknown fields, missing required fields, and values outside the permitted scope.
A useful negative test is to place a second customer ID in retrieved text and verify that the agent cannot substitute it into the tool call. Retrieval is evidence for an answer, not authority to change identity.
3. Authorization before execution
A policy check should run after argument construction and before the side effect. Test that an unauthorized call is refused without contacting the mutation tool. The trace should preserve the attempted tool, policy decision, and refusal reason.
Do not treat a refusal as a failed test. If the request is outside the agent authority, refusal is the passing outcome.
4. Idempotency under retry
Inject a timeout after a mutation is submitted but before the client receives the result. Then retry the workflow. The test should verify one durable intent, not two returns or two cancellations. This requires an idempotency key or an equivalent reconciliation step.
Also test a timeout before submission. The expected behavior is different. A system that cannot distinguish those states cannot safely decide whether retry is allowed.
5. Claim accuracy
The final response must match the observed tool result. If the tool returned no order, the answer must not cite an order number. If the mutation was refused, the answer must not say it completed. If the source is stale, freshness must not be implied.
This is where final-answer evaluation belongs, but it should be the last assertion in the chain rather than the only one.
A compact trace contract
For each decision, record a trace that a test can inspect without parsing prose. A minimal event can contain:
trace_id, intent_id, actor_id, tool_name, arguments, policy_result, attempt, dependency_result, side_effect_id, and claim_state.
The values should make the state transition observable. For example, policy_result=deny should pair with no side_effect_id. A submitted mutation with an unknown transport result should pair with dependency_result=unknown, not failed, until reconciliation completes.
Do not log secrets or complete payment details. Redact sensitive values while retaining enough structure to compare the request with the permitted scope.
Saturday checklist
Before shipping an agent tool, run these cases:
- Happy path: correct tool, trusted arguments, permitted result.
- Wrong intent: mutation wording appears inside a question.
- Prompt injection: retrieved text asks the agent to use a different identity or tool.
- Malformed arguments: missing, extra, or out-of-scope fields.
- Authorization refusal: verify no side effect occurred.
- Timeout before submission and timeout after submission.
- Empty or stale evidence: verify the answer exposes the limitation.
- Replay: same intent arrives twice and produces one mutation.
Branch coverage tells you that each path ran. The trace contract tells you whether each path preserved meaning. For agent QA, that difference is the work.
Share this post
You Might Also Like
Test AI Latency from First Token to Finished Answer
A fast first token can hide a late or invalid answer. Test queueing, streaming, and completion with a synthetic workload before accepting a model-serving change.
AI & AutomationTest the Trace Before You Trust the Dashboard
A correct AI answer can hide a broken trace. Use a synthetic request and a deliberately stripped context header to test whether your debugging evidence survives service boundaries.
Career & Best PracticesThe Cheapest Test Is the One You Run Before You Build
The most expensive engineering mistakes in my systems were not hard bugs. They were reasonable implementations of questions nobody had defined.
Quantitative TradingA Signal Is Not a Decision
A signal says that conditions are interesting. It does not say that the portfolio should trade. The missing layer is the decision record between detection and execution.
Latest Blog Posts
Test AI Latency from First Token to Finished Answer
A fast first token can hide a late or invalid answer. Test queueing, streaming, and completion with a synthetic workload before accepting a model-serving change.
Test the Trace Before You Trust the Dashboard
A correct AI answer can hide a broken trace. Use a synthetic request and a deliberately stripped context header to test whether your debugging evidence survives service boundaries.
The Evaluator Needs an Abstain State
A judge that must choose pass or fail will turn uncertainty into false confidence. Add an abstain state, calibrate it, and test the cases where the evaluator should refuse to decide.
Related Tools & Demos
The QA Field Manual to Language Models
A free 24-chapter book. Start at βwhat is AI, really?β and finish with a small language model you built yourself β one that reads a failing Playwright test and proposes a fix you can run. Read it in your browser, or download the PDF or the Mac app.
View Source Code βMulti-Model LLM Harness
One interface to call any AI model β capability routing, fallback chains, budgets, circuit breakers, and a quality feedback loop. A practical architecture pattern write-up.
Automated Trading System
Multi-engine trading platform with real-time risk management, regime-based strategy selection, and automated order execution.
View Source Code β
Stay in the Loop
Get weekly insights on AI-driven QA, engineering leadership, and automation strategies.
No spam, ever. Unsubscribe anytime.