> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zavu.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# zavu agents

> Create, test, connect and inspect agents from the terminal

An agent is a standalone object with its own id. It can answer on several
senders, and it can exist with none while you build it.

```bash theme={null}
zavu agents list
```

```
id                                name        kind   enabled  senders  model
qd75detym58c6has4sfrye3vws8b6ygt  Atlas       voice  yes      1        openai/gpt-4o-mini
qd7ck28evcskdc3xx4wzevtmeh8b6bcm  Pizza Desk  text   no       0        gpt-4o-mini
```

`kind` reflects what the agent actually is — an agent named for voice whose
`voice` block is missing reads as `text`, which is usually the thing you wanted
to know.

## Test an agent

The command you will use most. It runs the real prompt, model and knowledge
base and prints what the agent **would** reply. Nothing is delivered, nothing is
charged, no execution is logged — so it is safe on every edit.

```bash theme={null}
zavu agents test --agent <agentId> --message "where is order ORD-001?"
```

```
Your order ORD-001 shipped on Tuesday and arrives Thursday.

  1418→40 tokens · 5249ms · 1 knowledge chunk(s)
```

| Flag                  |                                                                     |
| --------------------- | ------------------------------------------------------------------- |
| `--agent <agentId>`   | The agent. Get it from `agents list`.                               |
| `--sender <senderId>` | Address it by sender instead (resolves to that sender's one agent)  |
| `--message <text>`    | What to say                                                         |
| `--turn <text...>`    | Prior turns, alternating user/assistant, oldest first. Repeatable.  |
| `--no-knowledge`      | Skip retrieval, to isolate prompt behaviour from the knowledge base |
| `--json`              | Raw response                                                        |

Multi-turn:

```bash theme={null}
zavu agents test --agent <agentId> \
  --turn "I need to change my booking" --turn "Sure — which one?" \
  --message "the one on Friday"
```

<Warning>
  **Read the warnings.** A dry run cannot prove everything, and it tells you what
  it could not: an agent that is still disabled, tools its channels will never
  call, flows it did not evaluate, contact metadata that exists live but not here.
  Treat them as part of the result — a good answer here is not proof the agent
  works on a real channel.
</Warning>

## Start from a factory agent

```bash theme={null}
zavu agents catalog                      # what is available
zavu agents pull kepler --dir kepler     # scaffold it locally
cd kepler && npm install
zavu deploy
```

`pull` writes a real TypeScript project: `index.ts` with the agent and its
skills, a `tsconfig.json`, and `@zavudev/functions` as a dependency so your
editor and `tsc` resolve it. Edit it freely — the code is the source of truth
and `zavu deploy` reconciles whatever it declares.

| Flag                    |                                                     |
| ----------------------- | --------------------------------------------------- |
| `--dir <path>`          | Where to scaffold. Defaults to `./<id>`.            |
| `--sender <senderId>`   | Sets the `SENDER_ID` secret for you                 |
| `--calendar <provider>` | For booking agents: `webhook` (default) or `calcom` |

### Booking agents

Kepler, Hopper and Fermi book meetings. By default they scaffold against a
generic webhook — an HTTPS endpoint **you** build and host that returns open
slots and books them. Until it exists the agent cannot book, and says so rather
than inventing a time.

Point it at Cal.com instead and it works with an API key:

```bash theme={null}
zavu agents pull kepler --calendar calcom
```

`pull` then lists every secret the agent needs, with a hint for each:

```
zavu fn secrets set CALCOM_API_KEY <value>
  ↳ Cal.com API key (Settings → Developer → API keys).
zavu fn secrets set CALCOM_EVENT_TYPE_ID <value>
  ↳ Numeric id of the Cal.com event type to book.
```

The Cal.com client only reports a booking when Cal.com accepted it. An event
type that requires confirmation comes back pending, and telling a caller they
are booked at that point is the worst outcome on that line.

`zavu agents init` walks the same path interactively: pick or create a sender,
pick an agent, get ready to deploy.

## Create one from scratch

```bash theme={null}
zavu agents create --sender <senderId> \
  --name "Order desk" --provider zavu --model openai/gpt-4o-mini \
  --channels whatsapp,sms \
  --prompt "You are the order desk for Tony's Pizza. Answer in one or two sentences."
```

Use `--prompt-file` for anything longer than a line — terminal paste mangles
newlines. `--data` / `--file` take a full JSON body for advanced fields.

<Note>
  An agent is created **disabled** and answers nobody until you turn it on. Pass
  `--enabled true` on create, or `zavu agents update --sender <id> --enabled true`
  later. The CLI says so when it happens.
</Note>

## Connect senders

A sender is the identity a conversation happens on. An agent can answer on
several; **a sender answers with at most one agent.**

```bash theme={null}
zavu agents senders connect    --agent <agentId> --sender <senderId>
zavu agents senders disconnect --agent <agentId> --sender <senderId>
```

Connecting a sender that is already in use is rejected, naming the agent that
holds it — otherwise you would have an agent that looks connected and never
receives a message.

## Tools

```bash theme={null}
zavu agents tools list --sender <senderId>
zavu agents tools test --sender <senderId> <toolId> --data '{"orderId":"ORD-1"}'
```

<Warning>
  Tools are offered to the model on **voice**, and inside a flow's `tool` step.
  The plain **text** path does not call tools — a text agent asked to look
  something up answers *"let me check that, one moment"* and then does nothing.
  See [how agents work](/concepts/agent-architecture).
</Warning>

Tools declared in code with `defineTool` are managed by their function: they
appear here read-only and are changed by redeploying.

To run a handler in isolation, without deploying:

```bash theme={null}
zavu fn invoke --tool get_order --args '{"orderId":"ORD-1"}'
```

## Knowledge bases

```bash theme={null}
zavu agents knowledge-bases create --sender <senderId> --name "Product docs"
zavu agents knowledge-bases documents add --sender <senderId> --kb <kbId> \
  --title "Pricing" --content-file ./pricing.md
zavu agents knowledge-bases documents list --sender <senderId> --kb <kbId>
```

Processing takes a few seconds. Verify retrieval actually fires with `agents
test` — it reports how many chunks the answer used.

<Warning>
  A prompt that says *"only state what the documentation returns"* with no
  documents attached does not refuse. It invents. Attach the documents before
  relying on that instruction.
</Warning>

## Flows

```bash theme={null}
zavu agents flows list   --sender <senderId>
zavu agents flows create --sender <senderId> --file flow.json
```

A flow is a deterministic sequence with a trigger. Steps take a `config`
object; a `tool` step resolves its tool through `config.toolId`, which holds the
tool's **name**. A flow naming a tool the agent does not have is rejected at
creation, listing the ones it does have.

Flows are **not** evaluated by `agents test` — they run on a real message, and
`agents test` says so when the agent has any.

## Inspect what happened

```bash theme={null}
zavu agents stats            --sender <senderId>
zavu agents executions list  --sender <senderId>
zavu agents executions get   --sender <senderId> <executionId>
zavu agents reset-thread     --sender <senderId>
```

`executions get` carries `errorMessage` and `responseText` — the place to look
when a live reply went wrong. `reset-thread` closes the conversation and any
flow session for one contact so the next inbound starts fresh.

Dry runs do not appear in `stats` or `executions`; they are not executions.

## Calls

```bash theme={null}
zavu calls list --status completed
zavu calls get <callId>       # includes the transcript, turn by turn
zavu calls hangup <callId>
```

`calls get` prints the conversation including tool calls. It is the only record
of what the agent actually said, and the first place to look after a call went
wrong.

```bash theme={null}
zavu calls create --to +14155551234
```

<Warning>
  `calls create` places a real outbound call, billed per connected minute plus
  telephony. `--greeting`, `--language` and `--max-minutes` override the agent's
  configuration for that call only.
</Warning>
