# npx zavudev functions

> Scaffold, deploy, invoke, inspect and roll back your code

`npx zavudev functions` (alias `fn`) drives Zavu Functions — your TypeScript running on
every messaging event. The most-used subcommands are also available at the top
level: `npx zavudev deploy` is `npx zavudev fn deploy`.

## Scaffold

```bash
npx zavudev fn init --name order-bot --template blank
```

Writes `index.ts`, a `package.json` declaring `@zavudev/functions`, a
`tsconfig.json`, and `.zavu/config.json` holding the function's id. Run
`npx zavudev fn init --help` for the current template list.

> **Note:**
> **Commit `.zavu/`.** It holds the `functionId`, and there is no command to look
> one up — a teammate who clones without it cannot deploy.

To start from a working agent instead of a blank file, see
[`npx zavudev agents pull`](https://www.zavu.dev/docs/guides/cli/agents).

## Deploy

```bash
npx zavudev deploy
```

```
› Deploying Order Bot (order-bot)…
  deployment id: nx7v0h30epeh2s7ppxcn9mpan58b6yre
› status: active
ℹ Agents synced:
    + Bella
ℹ Tools synced:
    + lookup_order
✓ Deployed in 11.5s
```

The summary lists what the deploy did to your agents and tools. **Read the lines
above the ✓** — they print before the success line. There is no ✓ at all, and the
command exits non-zero, in **two** cases:

1. Your declarations were not synced. The Lambda is live and its agents and tools
   are unchanged.
2. Your declarations synced and something in them cannot work — an agent no
   connected sender can reach, for instance. Everything deployed; the result is
   not usable as-is.

A CI job gating on the exit code will fail on both, which is the intent: the
second one is the deploy that otherwise looks green and answers nobody.

Warnings you may see, and what they mean:

| Warning | What happened |
|---|---|
| `manifest probe threw: …` | Your code failed to load. Nothing was synced; fix and deploy again. Exits non-zero. |
| `agent … cannot receive anything` | Its `channels` name nothing any connected sender carries. Deployed, enabled, and permanently silent. Exits non-zero. |
| `agent … triggers only on … so messages on other channels are dropped` | A sender it is connected to receives on a channel the agent does not list. Those messages are discarded before the agent sees them. Use `["*"]` unless you are deliberately excluding one. |
| `agent … was created without a sender` | It will not answer anything until a sender is attached. |
| `tools are synced but will NOT be called on <channel>` | Historical warning from before tools ran on the text path; on current deployments tools run on every channel. |
| `sender … now has N agents` | Only the first answers. The rest are unreachable — give this function its own sender. |

`npx zavudev fn push` updates the draft **without** deploying. Useful to save work in
progress; nothing changes in production until `deploy`.

## Run it locally

```bash
# Call one tool handler directly, with no deploy:
npx zavudev fn invoke --tool lookup_order --args '{"orderId":"ORD-001"}'

# Or dispatch a synthetic event at your default export:
npx zavudev fn invoke --event message.inbound \
  --data '{"from":"+14155551234","text":"hola"}'
```

| Flag | |
|---|---|
| `--tool <name>` / `--args <json>` / `--args-file <path>` | Call one `defineTool` handler |
| `--event <name>` / `--data <json>` / `--data-file <path>` | Dispatch an event |
| `--source <file>` | Entry file. Defaults to `index.ts`. |
| `--live` | Make real API calls. Off by default: outbound HTTP is stubbed and logged. |

> **Note:**
> `fn invoke` runs your code with [Bun](https://bun.sh). Every other command runs
> under plain Node.

This is the cheapest feedback in the product: it exercises your handler exactly
as production will, in milliseconds, without deploying or spending anything.

## Logs

```bash
npx zavudev fn logs            # recent invocations
npx zavudev fn logs --tail     # follow
```

Run it from the function's directory. Lambda's own noise is filtered out and
internal identifiers are redacted.

## Secrets

```bash
npx zavudev fn secrets list
npx zavudev fn secrets set STRIPE_KEY sk_live_…
npx zavudev fn secrets set STRIPE_KEY --from-file ./key.txt
npx zavudev fn secrets unset STRIPE_KEY
```

Values are write-only: `list` shows the last four characters, never the secret.
Reach them in your handler with `process.env.STRIPE_KEY`.

> **Warning:**
> Secrets apply on the **next deploy**. Setting one does not change the running
> function until you run `npx zavudev deploy`.

## Triggers

```bash
npx zavudev fn triggers list
npx zavudev fn triggers events                    # what you can subscribe to
npx zavudev fn triggers add --events message.inbound
npx zavudev fn triggers toggle <triggerId> --off
npx zavudev fn triggers remove <triggerId>
```

A trigger subscribes the function to an event, optionally scoped to one sender.
A function that only declares an agent and its tools needs no triggers — the
agent path invokes it directly.

## Versions and rollback

```bash
npx zavudev fn versions list
npx zavudev fn rollback <version>
```

Every deploy is a version with its own record. `rollback` republishes a previous
one's source and dependencies; it always asks for confirmation. Secrets are not
rolled back.

## Delete

```bash
npx zavudev fn delete            # in the function's directory
npx zavudev fn delete <functionId>
```

Removes the function and everything it owns — its triggers, secrets, deployment
history, and the agents and tools it manages. It asks you to type the slug
first, because there is no undo.

## Where to go next

  - [How agents work](https://www.zavu.dev/docs/concepts/agent-architecture): What a deploy actually does, with diagrams.
  - [npx zavudev agents](https://www.zavu.dev/docs/guides/cli/agents): Test, connect and inspect the agents your code declares.
