---
title: "Test an agent"
method: POST
path: "/v1/agents/{agentId}/test"
tags: ["Agents"]
---

# Test an agent

`POST /v1/agents/{agentId}/test`

## Request

- Base URL: `https://api.zavu.dev`
- URL: `https://api.zavu.dev/v1/agents/{agentId}/test`
- Auth: HTTP bearer

Run the agent's prompt, model and knowledge base against a message and return the reply instead of delivering it. Nothing is delivered and no execution is recorded.

**Billed like a live reply.** On an agent with the `zavu` provider the run is charged to your balance at the same price per token, and refused with `402 insufficient_balance` at a balance of zero; on a bring-your-own-key agent it costs your provider. `cost` on the response is what it charged. Runs are rate limited per project (`429`).

**Tools.** By default the model is offered the agent's enabled tools but none is run: if it picks one, the reply stops there and `plannedToolCalls` says which, with what arguments. Set `executeTools` to run them — that reaches your real handlers, with whatever they cost and change — and read `executedToolCalls`.

**Test-mode keys** are billed the same way, and `executeTools` with one still reaches your real handlers and writes real memory: a test run is not sandboxed by the key's mode.

## Path parameters

- `agentId` string, required

## Request body

- AgentTestRequest: Run the agent and return what it would say. Nothing is delivered to anyone and no execution is recorded. A run is **billed like a live reply**: on an agent with the `zavu` provider it is charged to your balance at the same price per token, and refused with `402 insufficient_balance` at a balance of zero. On a bring-your-own-key agent it costs your provider, not Zavu. `cost` on the response is what this run charged.
  - `message` string, required: What to say to the agent.
  - `history` object[]: Prior turns, oldest first, to exercise multi-turn behaviour without persisting a thread. Trimmed to the agent's context window.
    - `role` 'user' | 'assistant', required
    - `content` string, required
  - `useKnowledgeBase` boolean: Set false to skip retrieval and isolate prompt behaviour from the knowledge base.
  - `executeTools` boolean: Run the tools the agent calls instead of reporting the choice and stopping. Off by default because a tool handler talks to the outside world: a rehearsal that charges a card is not a rehearsal. Turn it on to exercise the loop that actually matters — the model picks a tool, the handler answers, the model replies with the result — without sending a message to anyone. What ran comes back in `executedToolCalls`.

## Response `200`

The agent's reply.

- AgentTestResponse
  - `success` boolean, required
  - `text` string, nullable, required: What the agent would reply.
  - `error` string, nullable, required
  - `inputTokens` integer, required
  - `outputTokens` integer, required
  - `latencyMs` integer, required
  - `knowledgeChunksUsed` integer, required: Knowledge-base chunks retrieved for this message. Zero means the answer was not grounded in your documents.
  - `executedToolCalls` object[]: Tools that actually ran, in order, when the request set `executeTools`. Empty on a normal dry run, where nothing is executed. An entry with `ok: false` means the agent saw an error and answered around it, which is what a customer would have received.
    - `name` string, required
    - `ok` boolean, required
    - `error` string, nullable
  - `warnings` string[], required: Things that are true of this agent but that a dry run cannot prove. Surfaced so a passing dry run is never mistaken for proof that the agent works live. - The agent being disabled. - Enabled tools that were offered to the model but not run: if the agent picks one, the reply stops at that choice (see `plannedToolCalls`). Pass `executeTools` to run them. - Tools that ran for real, when `executeTools` was set, and any that failed. - An agent whose sender has none of the channels it triggers on, which answers every dry run and no real message. - Contact metadata that exists on a real conversation but not here, and memory tools (`remember`, `recall`, `save_record`), which have no contact to write about on a test run.
  - `cost` number, required: USD charged to your balance for this run. 0 on a bring-your-own-key agent. When the balance covers only part of a run, that part is charged and the next run is refused with `402`.
  - `plannedToolCalls` object[], required: Tools the model chose to call, with the arguments it chose, on a run without `executeTools`. Nothing was executed: the reply stops at the choice. Empty when it answered without reaching for a tool, and on a run that executed tools (see `executedToolCalls`).
    - `name` string, required
    - `arguments` string, required: The arguments as a JSON string.

## Other responses

- `400`: message is required, or the message and history exceed 64 KB.
- `401`: Unauthorized.
- `402`: The agent runs on a Zavu model and the balance is at or below zero.
- `404`: Sender or agent not found.
- `429`: Too many test runs for this project. Retry after the number of seconds in the message.

## Changes

> 80 revisions in range; 1 not diffed.

- **2026-10-19** `70b974d2650a`: 4 info
  - added the non-success response with the status `402`
  - added the non-success response with the status `429`
  - added the required property `cost` to the response with the `200` status
  - added the required property `plannedToolCalls` to the response with the `200` status
- **2026-08-11** `5a69a1777f6f`: 2 info
  - added the new optional request property `executeTools`
  - added the optional property `executedToolCalls` to the response with the `200` status
- **2026-07-25** `5cce7d79055c`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api/changes/v1/agents/:agentId/test/post.md)

---

[API](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api.md) - [All operations](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zavudev/apis/zavu-unified-messaging-layer-api/revisions/75bc777b0ffb?raw)
