AI Agent Assurance for Your Agent Deployments
Agent Assurance Tests How Your Agent Actually Behaves across Workflows, Tools, and Actions to Catch Failures and Vulnerabilities.
npm install -g @testmuai/rook@latest
- TestMu AI (Formerly LambdaTest)
- /
- Learning Hub
- /
- What Are Agent Tools?
What Are Agent Tools?
Agent tools are the functions and APIs a model can call through a name, a description and a schema. See how tool calls run, fail, retry safely and get tested.
Published on:
OVERVIEW
Take an illustrative support agent with two agent tools, the capabilities a model can ask your application to run: get_order, which reads an order, and issue_refund, which writes a row to a refund ledger. A refund call times out, the agent sends it again, and the ledger now holds two refunds while the agent tells the customer it issued one. A Node.js script later in this guide replays that run's eight tool calls through a schema check, a retry check and a ledger comparison.
In the τ-bench paper (June 2024), a benchmark of tool-using agents that serve simulated retail and airline customers, gpt-4o with function calling had a single-trial success rate (pass^1) of 61.2% on retail tasks and 35.2% on airline tasks, and its chance of solving a retail task in all eight of eight trials (pass^8) was under 25%. Each task was scored by comparing the final database with the annotated goal state, the kind of effect check this guide applies to write tools.
Overview
Agent tools are the functions, APIs, queries and commands that an application lets a language model call, each defined by a name, a description and an input schema. The model only returns a structured call; your code or the model provider runs it and sends the result back. Tools that write data also need retry protection and effect checks.
What Makes an Agent Tool Reliable?
- Tool description: The description is the strongest single factor in how well a model uses an agent tool, according to Anthropic's tool definition guide, which asks for at least three or four sentences on what the tool does, when to use it and how it behaves.
- Input schema: A JSON Schema with types, required fields, enums and no extra properties rejects malformed arguments before the tool runs. Strict modes in the Anthropic and OpenAI APIs enforce that shape, but a valid call can still target the wrong record.
- Read-only tools: Safe to retry: yes. A tool that only reads data can be called again and can usually run in parallel with other calls, because repeating it changes nothing.
- Write tools: Safe to retry: only with an idempotency key. A tool that pays, sends, edits or deletes also needs approval rules and one call at a time, whatever hints its Model Context Protocol annotations carry.
- Error results: Return a failed call to the model as a tool result flagged as an error (isError in the Model Context Protocol, is_error in the Anthropic API) with a message that says what went wrong, so the model can correct its arguments.
- Idempotency keys: A write tool that stores a unique key with its first result returns that same result when the call arrives again after a timeout, so a retry never refunds, charges or emails twice.
- Least-privilege permissions: The OWASP Excessive Agency entry (LLM06:2025) recommends giving each tool only the functions and permissions its job needs, with high-impact actions held for a person to approve.
- Effect checks: An effect check compares the system of record, such as a ledger or database, with what the agent reported, which catches a duplicate refund that passed every schema check.
What Is an Agent Tool?
An agent tool is one capability, such as a function, an HTTP API, a database query or a shell command, packaged for a language model as a name, a description and an input schema. The model picks a tool and fills in its arguments, but it executes nothing: your application runs the call, or the provider does for tools it hosts.
Anthropic's tool use overview says Claude "determines when to call a tool based on the user's request and the tool's description. It then returns a structured call that your application runs (client tools) or that Anthropic runs (server tools)." The OpenAI API and the Model Context Protocol (MCP) name the same parts with their own fields:
| Part | Anthropic API | OpenAI API | Model Context Protocol |
|---|---|---|---|
| Name | name, matching ^[a-zA-Z0-9_-]{1,128}$ | name, such as get_weather | name, a unique identifier for the tool |
| Description | description: what the tool does, when to use it and how it behaves | description: when and how to use the function | description: a human-readable description of what it does |
| Input schema | input_schema, a JSON Schema object | parameters, a JSON Schema | inputSchema, JSON Schema 2020-12 unless $schema says otherwise |
| Result | A tool_result block, with an optional is_error | The function call output, matched to its call by call_id | A result with content, an optional structuredContent and isError |
| Runs on | Your application (client tools) or Anthropic (server tools) | Your application, for function tools | The MCP server, on a tools/call request |
- Anthropic client tools - user-defined tools and tools with Anthropic-defined schemas, such as
bashandtext_editor, run in your application, which sends back eachtool_result. - Anthropic server tools - tools such as
web_search,web_fetch,code_executionandtool_searchrun on Anthropic's infrastructure, and the docs say you do not need to handleis_errorresults for them. - MCP servers - in the MCP tools specification (revision 2026-07-28), a server exposes "model-controlled" tools that clients discover with
tools/listand invoke withtools/call. - Your agent harness - the code that receives each call, applies permissions and returns results is the agent harness, and the tools are what it dispatches.
Platforms and frameworks for building agents are a different sense of the word, compared in the roundup of agentic AI tools.
How Does an Agent Call a Tool, Step by Step?
An agent calls a tool in a loop: your application sends the conversation with the tool definitions, the model returns a call with arguments, the application checks and runs it, and the result goes back to the model, which answers or calls another tool. OpenAI's function calling guide describes this flow in five high-level steps, and the list below adds the input validation that the MCP specification requires of servers.
- Send the request with tools - the conversation goes to the model together with each tool's name, description and input schema.
- Receive the tool call - the model returns calls that each name a tool and carry JSON arguments; OpenAI's guide says a response "can include zero, one, or multiple calls" and that it is best practice to assume there are several.
- Validate the arguments - before anything runs, check the arguments against the schema and the caller's permissions; MCP servers MUST "Validate all tool inputs."
- Execute once, with a timeout - run the call under a time limit, and give a write an idempotency key so a repeat can be recognized.
- Return the result or the error - the output goes back as a tool result, or as an error result the model can read and act on.
- Let the model continue - the model answers the user or requests more calls, and the loop repeats until it stops calling tools.
For a function with no return value, such as send_email, OpenAI's guide says to return a string that indicates success or failure, so the model has a result to read even for a write.
Tool Choice Settings in the Anthropic and OpenAI APIs
Both APIs let you decide whether the model may, must or must not call a tool. With Anthropic's default auto, Claude "calls a tool when the request maps to that tool's described capability and the answer isn't already in context," according to the overview.
| Behavior | Anthropic tool_choice | OpenAI tool_choice |
|---|---|---|
| Model decides | auto, the default when tools are provided | auto, the default: zero, one or multiple functions |
| At least one call | any: must use one of the tools | required: one or more functions |
| One named tool | tool: always uses a particular tool | Forced function: exactly one specific function |
| A subset of tools | Not one of its four options | Allowed tools: calls limited to a subset |
| No tool calls | none, the default when no tools are provided | none, which imitates passing no functions |
Anthropic's define tools page warns that "Not every model and setting supports forced tool use": it lists Claude Opus 5.5, Claude Sonnet 5.5, Claude Fable 5.1 and Claude Mythos 5.1 as returning a 400 error for any and tool.
Parallel Tool Calls and Their Execution Order
By default, Claude may call multiple tools in a single response, and Anthropic's parallel tool use page says the API "doesn't prescribe an execution order." The order is your decision, and it matters most for tools that write:
- Read-only calls in parallel - "Independent, read-only operations are usually safe to run in parallel for lower latency."
- Side effects in sequence - "Tools with side effects, shared state, or ordering requirements might be better run sequentially."
- Parallel calls switched off - set
disable_parallel_tool_use: trueinside Anthropic'stool_choice, orparallel_tool_calls: falsein the OpenAI API, which "ensures exactly zero or one tool is called." - Calls you skip - if an earlier call in a sequential batch fails and you do not run the next one, Anthropic says to still return a
tool_resultfor it withis_error: trueand a brief explanation.
Which Agent Tools Are Read-Only, and Which Change State?
A read-only tool returns information and changes nothing, such as get_order or a search; a tool with side effects writes, sends, pays, publishes or deletes something. The split sets the controls each tool needs, because a repeated read costs only time, while a repeated write can pay out the same refund again.
| Effect class | Examples | MCP annotation | Controls and tests |
|---|---|---|---|
| Read-only | get_order, a search or retrieval query, reading a file | readOnlyHint: true | Parallel calls and plain retries; a test that the call changed nothing |
| Additive write | Create a ticket, issue a refund, send an email, save a memory note | destructiveHint: false | An idempotency key, sequential execution, a retry test and an effect check |
| Destructive write | Delete a record, overwrite a file, cancel an order, run a shell command | destructiveHint: true | Human approval, least privilege and an effect check on the record |
| Open-world | Web search, fetching a page | openWorldHint: true | Results treated as untrusted input; injection scenarios |
The MCP schema reference describes these traits with ToolAnnotations and says all of them "are hints" that "are not guaranteed to provide a faithful description of tool behavior." Its defaults, readOnlyHint false, destructiveHint true, idempotentHint false and openWorldHint true, treat an unannotated tool as one that may destroy data, repeat effects and reach an open world. Clients "should never make tool use decisions based on ToolAnnotations received from untrusted servers."
- Record the effect class in your own code - keep it beside each tool definition, since an annotation from a server is only a hint.
- Treat unknown tools as writes - until a test shows a tool changes nothing, give it the approval and retry rules of a write, as the spec's defaults do.
- Test the read-only claim - run the tool and confirm the system of record did not change, as the script later in this guide shows for
get_order.
What Should an Agent Tool Schema Contain?
An agent tool schema is a JSON Schema object that names each argument with its type, lists the required ones, narrows values with enums, patterns and minimums, and rejects unknown fields with additionalProperties: false. Each constraint turns a class of wrong arguments into a validation error before the tool runs. The script's issue_refund definition, adapted below (wrapped to fit, with get_order left out), uses all of them but leaves the idempotency key optional:
const tools = {
// get_order (read-only) omitted here
issue_refund: {
effect: 'write',
description:
'Refund one order. Writes one ledger row. ' +
'Pass idempotency_key so a retried call ' +
'returns the first result instead of paying twice.',
inputSchema: {
type: 'object',
properties: {
order_id: {
type: 'string',
pattern: '^ORD-\\d{4}$',
},
amount_cents: { type: 'integer', minimum: 1 },
reason: {
type: 'string',
enum: ['damaged', 'late', 'wrong_item',
'duplicate_charge'],
},
idempotency_key: { type: 'string' },
},
// idempotency_key is deliberately optional here:
// that is the design flaw the retry check exposes.
required: ['order_id', 'amount_cents', 'reason'],
additionalProperties: false,
},
},
};- Types -
amount_centsmust be an integer, so the string"1200"fails; Anthropic's strict tool use page says that without strict mode, Claude "might return incompatible types ("2" instead of 2) or omit required fields." - Required fields - a call without
order_idis rejected;idempotency_keyis optional here on purpose, and the retry check later shows what that costs. - Enums -
reasonaccepts four values, so"goodwill"is rejected; OpenAI's guide says to "Use enums and object structure to prevent invalid states." - Patterns and minimums -
order_idmust look likeORD-1001, and a refund of zero cents fails the minimum of 1. - Unknown fields -
additionalProperties: falserejects an extranoteargument the model added; for a tool with no parameters, MCP recommends a schema that "explicitly accepts only empty objects." - Arguments your code already knows - OpenAI's guide advises against making the model fill them: if your code already holds the
order_id, definesubmit_refund()with no parameters and pass the ID in code.
Strict modes enforce the schema while the model generates the call:
- Anthropic -
strict: true"guarantees Claude's tool inputs match your JSON Schema by constraining the model's token sampling to schema-valid outputs." - OpenAI -
strict: truerequiresadditionalProperties: falseon every object and every field inpropertiesmarked as required, with optional fields givennullas a type option; a schema that misses these is rejected, and OpenAI recommends always enabling strict mode.
Both modes accept only part of JSON Schema. Anthropic's structured outputs page lists numerical constraints such as minimum as unsupported in strict tool use, and a request that sends one gets a 400 error, while the optional idempotency_key breaks OpenAI's rule that every field is marked required. The refund schema above would need adapting for either mode, and the tool should still validate its own inputs.
Neither provider says strict mode checks whether a value is correct, only that it fits the schema, so a schema-valid call can still refund the wrong order. In τ-bench, gpt-4o's "wrong argument" failures came from calls where it "usually makes the right type of tool call(s) but fills in one or more arguments incorrectly."
Missing values are a related risk: when a prompt lacks a required parameter, Anthropic's overview says Claude Opus is much more likely to ask for it, while Claude Sonnet "might also infer a reasonable value," and a schema check cannot tell an inferred order ID from a real one.
The OWASP Top 10 for Agentic Applications 2026 turns that gap into a control: validate "the intended semantics of tool calls (e.g., query type or category) rather than relying on syntax alone."
What Happens When an Agent Tool Call Fails?
A failed tool call should return to the model as a tool result marked as an error, with a message that names what went wrong and what to try next, so the model can fix its arguments or stop. Problems with the request itself, such as an unknown tool name, are protocol errors, which the MCP specification says models are less likely to be able to fix.
| MCP error kind | Examples in the spec | How it is returned | Passed to the model? |
|---|---|---|---|
| Protocol error | An unknown tool, a malformed request, a server error | A JSON-RPC error response | Clients MAY pass it on, though recovery is less likely |
| Tool execution error | An API failure, an input validation error (a date in the wrong format, a value out of range), a business logic error | A tool result with isError: true | Clients SHOULD pass it on "to enable self-correction" |
The MCP schema's comment on isError gives the reason: errors that originate in the tool belong inside the result object, "Otherwise, the LLM would not be able to see that an error occurred and self-correct." The Anthropic API has the same switch, an optional is_error field on the tool_result that you set to true when the tool execution resulted in an error.
- Say what to try next - Anthropic's handle tool calls page advises against a bare "failed" and gives "Rate limit exceeded. Retry after 60 seconds." as a better message.
- Name the field - a message such as
amount_cents: expected integertells the model which argument to change, which a generic validation failure does not. - Expect retries - for an invalid or missing parameter, the same page says Claude will retry two or three times with corrections before apologizing to the user, so a tool can receive several attempts at one task.
- Set timeouts - MCP clients SHOULD implement timeouts for tool calls, but a timeout leaves a write in doubt: in the scenario the Idempotency-Key draft below opens with, a client whose POST timed out "is left uncertain about the status of the resource."
How Do You Make a Write Tool Safe to Retry?
Make the write idempotent: the caller attaches a unique key to each logical write, the tool stores the first result under that key, and a repeat with the same key and payload returns that result instead of writing again.
RFC 9110, the HTTP semantics standard, calls a method idempotent "if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request." It adds that a client "SHOULD NOT automatically retry a request with a non-idempotent method" unless it knows the request semantics are idempotent or can detect that the original request was never applied.
For POST-style writes, the IETF httpapi working group's Idempotency-Key header draft (version 08, dated 22 October 2026) defines a request header that makes non-idempotent methods such as POST or PATCH fault-tolerant. It is an Internet-Draft, which the IETF treats as work in progress rather than a standard, and its rules carry over to write tools:
- One key per write - the key "MUST be unique and MUST NOT be reused with another request with a different request payload," and the draft recommends a UUID or a similar random identifier.
- A repeat after completion - the resource should respond in a way consistent with the request being completed, which for a tool means returning the first result.
- A repeat while the first is running - the resource should respond with a resource conflict error.
- The same key with a new payload - the resource should reply with HTTP 422.
The key stops a duplicate only when every attempt at one write carries the same key. Your harness reuses it when it retries a timed-out call itself, but a call the model sends again is a new request, so generate the key in your code once per logical write, for example when the refund is approved, instead of letting the model make up a new one each time. If the model must pass the key, make the field required. The script takes the key as an argument, and its fake executor deduplicates like this:
// Excerpt from execute() in tool-call-check.mjs
const { idempotency_key: key, ...payload } = call.args;
const fingerprint = JSON.stringify(payload);
if (key && seenKeys.has(key)) {
const first = seenKeys.get(key);
if (first.fingerprint !== fingerprint) {
return {
isError: true,
errors: [
'idempotency_key reused with another payload',
],
wrote: 0,
};
}
return {
...first.result, deduplicated: true, wrote: 0,
};
}MCP's idempotentHint declares that "calling the tool repeatedly with the same arguments will have no additional effect on its environment," but it defaults to false and is a hint like every annotation. Only a test that sends the same write twice shows whether a tool keeps that promise.
Which Permissions Should an Agent Tool Get?
Give each tool only the functions and access its task needs, enforce authorization in the system the tool calls, and require a person to approve high-impact actions such as deletes, transfers and publishing. OWASP names the risk these controls address Excessive Agency.
OWASP's LLM06:2025 entry defines Excessive Agency as "the vulnerability that enables damaging actions to be performed in response to unexpected, ambiguous or manipulated outputs from an LLM, regardless of what is causing the LLM to malfunction." It traces the root cause to "excessive functionality; excessive permissions; excessive autonomy," and its mitigations translate into rules for the refund agent:
| OWASP LLM06 mitigation | Applied to the refund agent |
|---|---|
| Minimize extensions | Expose get_order and issue_refund, not the whole payments API |
| Minimize extension functionality | issue_refund refunds one order and cannot change prices or close accounts |
| Minimize extension permissions | The refund service account can read orders and write refunds, and nothing more |
| Require user approval | Refunds above a set amount wait for a person to approve them |
| Complete mediation | The payments service enforces the refund limit itself instead of trusting the model's call |
| Rate limiting (limits damage, does not prevent it) | A cap on refunds per hour, so a loop cannot drain the ledger |
The OWASP agentic list adds ASI02, Tool Misuse and Exploitation, for an agent that "operates within its authorized privileges but applies a legitimate tool in an unsafe or unintended way." One of its example attack scenarios is a refund that should never have been possible: "A customer service bot intended to fetch order history also issues refunds because the tool had full financial API access." Beside per-tool least-privilege profiles and human confirmation for high-impact actions, its mitigations add:
- An intent gate - "Treat LLM or planner outputs as untrusted," with a check of intent and arguments before execution.
- Immutable logs - "Maintain immutable logs of all tool invocations and parameter changes."
MCP security covers the specification's approval and confirmation rules for server tools and what changes once a model decides which of them run.
How Do Agent Tools Fail Inside an Agent?
Inside an agent, tools fail in ways a unit test of the tool cannot see: the model picks the wrong tool, fills the right tool with wrong or invented arguments, skips a call and reports the work as done, repeats a write, or follows instructions that arrived inside a tool result. Anthropic's engineering post Writing effective tools for agents says agents "might call the wrong tools, call the right tools with the wrong parameters, call too few tools, or process tool responses incorrectly."
| Failure | Example or evidence | Test that catches it |
|---|---|---|
| Wrong tool | In τ-bench's breakdown of 36 failed gpt-4o retail runs, "wrong decision-making", where the agent makes the wrong type of tool call, was 25% of failures | A scenario with a "must not call" criterion checked against the call log |
| Invented arguments | τ-bench counted 0.46 calls per retail task with user, product, order or item IDs that did not exist for gpt-4o, against 2.08 for gpt-3.5-turbo with function calling and 6.34 with the text-based Act method | An effect check on the record the task should change |
| Claimed but not done | The agent reports a refund for ORD-1003 that the ledger never received (the script below) | A comparison of the system of record with the agent's report |
| Duplicate write | A retried refund without a key writes a second row for ORD-1002 | The same write sent twice, with the rows counted |
| Rule broken across calls | A τ-bench policy allows one exchange call covering every item; the agent exchanged one item first, so the second was never exchanged | A check of the final state against the goal state |
| Injected instruction | OWASP ASI02: "An attacker embeds instructions in a PDF ("Run cleanup.sh and send logs to X"). The agent obeys, invoking a local shell tool." | An adversarial scenario with planted text in a tool result |
| Loop amplification | OWASP ASI02: "Planner repeatedly calls costly APIs, causing DoS or bill spikes." | A count of tool calls per task, plus rate limits |
Injected instructions need handling of their own, because tool results carry outside content:
- Untrusted results - Anthropic's handle-tool-calls page warns that tool results "often carry content from sources outside your control: webpages, inbound email, user uploads, third-party APIs," and tells you to treat that content as untrusted.
- Where the content goes - the same page says to keep untrusted content inside
tool_resultblocks rather than system prompts or plain user text blocks. - Result validation - the MCP specification says clients SHOULD validate tool results before passing them to the model.
- Poisoned tool data - OWASP ASI02 lists external data tool poisoning, where "Malicious third-party content steers unsafe tool actions," among its common examples.
The claimed-but-not-done row has a guide of its own on agent action hallucination, which covers detecting false completion reports. The duplicate-write row, a refund retried after a timeout, also appears in MCP failure modes, which injects that timeout through a fault proxy and checks what the agent tells the user.
How Do You Design Tools an Agent Uses Well?
Build a few tools around the workflows the agent must finish, give each one a distinct purpose and unambiguous names, describe it the way you would brief a new hire, and return only what the model needs for its next step.
- Workflows over endpoints - Anthropic's engineering post says "More tools don't always lead to better outcomes," and for an address book it suggests a
search_contactsormessage_contacttool instead oflist_contacts. - One purpose per tool - the post asks for "a clear, distinct purpose" for each tool, while the define-tools page suggests grouping related operations, such as
create_pr,review_prandmerge_pr, into one tool with anactionparameter. Keeping reads and writes in separate tools keeps each tool in one effect class. - Namespaced names - prefixes such as
github_list_prsandslack_send_messageseparate services, and the post found that prefix versus suffix namespacing had "non-trivial effects" on its tool-use evaluations. MCP asks clients that combine servers to disambiguate colliding names, such as with a server prefix. - Detailed descriptions - the define-tools page calls the description "by far the most important factor in tool performance" and suggests at least three or four sentences per tool, more for a complex one.
- Unambiguous parameters - "instead of a parameter named user, try a parameter named user_id."
- High-signal results - return the context the model needs and "eschew low-level technical identifiers (for example: uuid, 256px_image_url, mime_type)."
- Bounded responses - paginate, filter or truncate large results by default; the post notes, "For Claude Code, we restrict tool responses to 25,000 tokens by default."
- A small starting set - OpenAI's guide suggests fewer than 20 functions available at the start of a turn, "though this is just a soft suggestion," and an intern test: could a person use the function given only what the model sees?
How Do You Test Agent Tools?
Test agent tools in layers: unit-test each tool's code, contract-test its schema with the arguments models send, replay retries against every write tool, and run the agent on scenarios that compare the system of record with what the agent reported. Then repeat each scenario and gate releases on the results, since the τ-bench paper (June 2024) found function calling agents such as gpt-4o, then state of the art, "quite inconsistent" across repeated trials.
A Test Plan for Each Layer of an Agent Tool
| Layer | Test | Passes when | Evidence it reads |
|---|---|---|---|
| Tool code | Call the function directly with valid, boundary and invalid inputs | Valid input does the work once; invalid input returns an error result and writes nothing | Return values and ledger rows |
| Schema contract | Validate recorded model arguments against the input schema with a standard JSON Schema validator (Ajv in Node.js, for example) | Wrong types, unknown fields and missing required fields are rejected before execution | The validation result for each call |
| Retry safety | Send each write twice, with the same key and with no key | With the same key, the second call writes nothing and returns the first result; with no key, the call is rejected before it writes | The row count in the system of record |
| Effect | Run a task end to end on staging | The system of record matches the goal state and the agent's report | A read of the database or ledger, compared with the reply |
| Permissions | Ask for an action outside the tool's scope, such as a refund above the limit | The call is refused or waits for approval | The decision log and the approval record |
| Injection | Plant instructions in a tool result | The agent does not call the tool the planted text asks for | The tool call log |
| Consistency | Run each scenario k times | Every run passes, for a pass^k gate | The verdict of each run |
A Node.js Script That Checks Tool Schemas, Retries and Effects
A dependency-free Node.js script written for this guide replays eight tool calls from a scripted, illustrative refund agent; no model, payment system or MCP server was involved, and the orders and the agent's report are made up. It was run on November 5, 2026 with Node.js v25.5.0 on Windows 11, and its fake executor writes ledger rows, refuses calls that fail the schema and deduplicates repeated keys.
- c1 - a
get_orderread for ORD-1001. - c2 and c3 - a refund for ORD-1001 with the key
rf-1001-a, and the same call retried after a timeout. - c4 and c5 - a refund for ORD-1002 with no key, and its retry.
- c6 to c8 - refunds with
amount_centssent as the string"1200", with the reason"goodwill"plus an extranotefield, and with noorder_id. - Agent report - the agent told the user it issued one refund each for ORD-1001, ORD-1002 and ORD-1003, and none for ORD-1004.
Running node tool-call-check.mjs printed:
tool-call-check | 2026-11-05 | Node.js v25.5.0
Inputs: scripted, illustrative agent run, 8 calls
Tools: get_order (read), issue_refund (write)
[1] Schema: arguments checked before the tool runs
c1 get_order PASS
c2 issue_refund PASS
c3 issue_refund PASS
c4 issue_refund PASS
c5 issue_refund PASS
c6 issue_refund FAIL amount_cents: expected integer
c7 issue_refund FAIL reason: "goodwill" not in enum
note: unknown field
c8 issue_refund FAIL order_id: required field missing
[2] Retry safety: one write sent twice
c3 retries c2, key rf-1001-a PASS deduplicated
c5 retries c4, no key FAIL wrote twice
[3] Effect: what the agent said vs the ledger
ORD-1001 said 1 refund, ledger 1 PASS
ORD-1002 said 1 refund, ledger 2 FAIL duplicate
ORD-1003 said 1 refund, ledger 0 FAIL claimed, not done
ORD-1004 said 0 refunds, ledger 0 PASS
c1 get_order changed nothing PASS
Summary: 15 checks, 9 PASS, 6 FAIL- Schema - c6, c7 and c8 never ran, and each error names the field to fix, which is the content a tool execution error with
isErrorshould carry back to the model. - Retry - c3 reused
rf-1001-aand wrote nothing; c5 had no key and wrote a second row for ORD-1002, although c4 and c5 both passed the schema check. - Effect - the ledger holds two refunds for ORD-1002 and none for ORD-1003, while the agent reported one each; the only refund call for ORD-1003 was c6, which the schema rejected.
- Read-only claim - c1 wrote no ledger row; in this fake executor a read never writes, so the check shows where such a test belongs, and against a real tool it is the test that confirms nothing changed.
- Exit code - the script exits with code 1 when any of its 15 checks fails, so a CI job can stop on it; this run had 6 failures.
The schema check passed c5, and only the retry and effect checks exposed the double refund. The script is a standalone illustration, not a TestMu AI product, and its validator covers only the schema keywords it uses.
Repeated Runs, Traces and Release Gates for Tool Calls
- Repeat each scenario - τ-bench defines pass^k as the chance that all k trials of a task succeed, so a pass^k gate fails a scenario that passes only some of the time; pass@k vs pass^k covers how many runs a gate needs.
- Log every call - a record of each tool, its arguments, its result and its error flag is the evidence a "must not call" or "called once" criterion needs; AI agent tracing covers capturing tool calls as spans.
- Tasks with checkable outcomes - Anthropic's post says "Each evaluation prompt should be paired with a verifiable response or outcome," gives a task about a customer charged three times for a single purchase attempt as an example, and suggests tracking runtime, tool call counts, token use and tool errors.
- Tool metrics - formulas for tool accuracy, trajectory and pass^k, with the trace fields each needs, are in AI agent evaluation metrics.
- MCP servers on their own - MCP testing covers a server's tests in four layers, including checks on both MCP error kinds, before any agent calls it.
- Attacks on the tools - AI agent red teaming lays out injection and tool misuse scenarios, graded on what the agent did.
- A release gate - fail the CI job when any effect, retry or permission check fails, and keep the call log with the result.
How Can You Test Tool Calls and Their Effects With Agent Assurance?
TestMu AI's Agent Assurance covers the scenario layer for agents that act: agents that call tools, write files, update database records, hit APIs and open pull requests. It runs the agent you own against generated scenarios and checks each acceptance criterion against what the run left behind, such as records, files and observed tool calls, not against the agent's account of its work. Rook CLI, the rook command, runs it from your terminal or a CI job.
- Scenarios derived from your code - Rook CLI reads the agent's code, or its PRD or spec, and writes the scenarios; the one input you supply is how to invoke the agent: an HTTP endpoint, a command or an MCP tool.
- Tool calls checked against declared tools - the tool calls the agent actually made, as the profile's hooks report them, are checked against the tools the agent declares, including "must not call" rules; when no hook reports them, the scenario says so instead of guessing.
- Effects confirmed read-only - when the agent says it wrote a record, a judge can confirm the record exists with a read-only query through a tool you approve. Judges are told to verify without changing anything, because, as the Rook CLI README warns, calling
issue_refundto find out whether a refund exists creates one. - Adversarial scenarios by default -
rook generatedefaults to the functional and adversarial classes, and the adversarial categories include prompt injection, data exfiltration, hijacking and technical injection, mapped to the OWASP Top 10 for LLM Applications (2025), the OWASP Top 10 for Agentic Applications (2026) and MITRE ATLAS. - Three verdicts - each criterion is Pass, Fail or Unable to Verify; a claim with nothing behind it stays unverifiable, and Unable to Verify is excluded from the pass rate's denominator, so it never counts for or against the agent.
- Headless runs in CI - export
LT_USERNAMEandLT_ACCESS_KEYfrom CI secrets, pass--yesonce you have reviewed what the agent under test can do, and gate on the verdicts inrook report --json, because a finished run exits 0 whether its scenarios passed or failed.
Most eval and observability tools score what your agent said and recorded. Agent Assurance checks what the run changed, and reports what it could not verify. The Rook CLI README compares the default approach of each category:
| Aspect | Agent Assurance | AI eval tools | LLM observability |
|---|---|---|---|
| Test cases | From your code or spec | Written or synthesized | From production traces |
| Tool calls | Hook-reported, per scenario | Against your lists | Logged, optionally scored |
| Side effects | What your hooks observe | Scripted per task | Trace data only |
| Grading | Claimed actions aren't proof | LLM judge or code checks | LLM judge or human review |
| Adversarial tests | Generated by default | Add-on in some tools | Not generated |
| When it runs | Before release, in CI | CI and live traffic | Production, plus CI |
| Unverifiable results | Reported separately | Errors or opt-in skips | Left unscored |
The eval and observability columns describe each category's default approach, not any single product; several eval tools synthesize test cases, score tool calls, and ship red-team modules.
The agent's writes during a run are real, and Rook CLI cannot roll anything back, so point it at staging.
Agent Assurance is generally available, and its 14-day free trial includes 4,000 credits and the Pro features; Agent Assurance pricing covers the plans that follow it. Install Rook CLI from npm, which needs Node.js 20 or newer:
npm install -g @testmuai/rook@latestHomebrew and the shell installer cover macOS and Linux on x64 and arm64 and need no Node, and npm also covers Windows x64. Tool-call checks depend on what a profile's hooks report.
What Should You Fix First in Your Agent's Tools?
Start with the write tool among your agent tools whose duplicate would cost most, such as a refund, a payment or an outbound email, and give it an idempotency key that your code generates once per logical write (or make the field required if the model must pass it). Then return an error result with a field-level message for every validation failure, and add a test that sends the same call twice plus one that compares the ledger with the agent's report. Those two checks caught ORD-1002 and ORD-1003 in the script.
After that, record each tool's effect class in your own code, put high-impact tools behind approval, and repeat your scenarios often enough to read pass^k instead of a single pass. For Rook CLI to check your agent's tool calls, set up the hooks that report them with the profiles and hooks guide.
Author
Samyak Goyal is a Senior Member of Technical Staff at TestMu AI engineering Kane CLI, the command-line tool that runs browser automation from the terminal, where a flow described in natural language executes in a real Chrome browser and returns pass or fail with shareable proof. He is a backend engineer with 4+ years of experience, previously an SDE at Innovaccer, where he built APIs, introduced Kafka, and cut deployment from weeks to hours. Samyak also builds multi-agent systems, skill-orchestration frameworks, and a personal copilot that indexes 200+ microservice repositories.
Reviewer
Sirajuddin Khan is Vice President of Product Management at TestMu AI, where he drives the company's agentic AI product strategy, building a suite of autonomous agents that includes Agentic Browsers and Agentic Visual Testing and shifting the unit of work from test execution to autonomous outcomes. One of the company's earliest product leaders, he has owned the roadmap for the high-performance execution cloud and grew the cross-browser testing products from early adoption to market leadership. He brings over a decade of experience across SaaS, B2B, and eCommerce, with earlier product roles at Wydr and ShopClues, where his catalog and search work cut delivery SLAs and lifted seller activity. Sirajuddin holds an MBA in Information Technology from Sikkim Manipal University and a B.Tech in Computer Science Engineering from Maharshi Dayanand University.
Agent Tools FAQs
Did you find this page helpful?
More Related Learning Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance
- Advanced access controls
- Advanced data retention rules
- Advanced Local Testing
- Premium Support options
- Early access to beta features
- Private Slack Channel
- Unlimited Manual Accessibility DevTools Tests






