Factory agents
Factory agents are ready-made agents you pull straight into your project with one command, then deploy. Under the hood each is a Zavu Function that declares an agent withdefineAgent and its skills with defineTool — so
what you pull is real, editable code you own, not a black box.
npx zavudev agents pull fermi scaffolds the agent, registers it, and leaves you a
directory to npx zavudev deploy. Voice agents answer phone calls; text agents run on
WhatsApp, SMS, and more.
You’ll need an active sender in your Zavu project. For voice, the sender
also needs a phone number (purchase one).
1. Install the CLI
2. Browse the catalog
3. Find your sender
Connect more channels (from the CLI)
Voice and SMS work as soon as the sender has a number. The rich channels each connect with one command:channels list names, and only those.
Connecting a channel to the sender is necessary and not sufficient: a channel the
sender receives on but the agent does not list is dropped before the agent sees
it, with no error and no reply. It is recorded: the drop lands in
GET /v1/senders/{senderId}/agent/executions with status: "filtered" and a
line saying which channel arrived and which the agent listens on, and the
dashboard’s Agents → Logs → Filtered view shows the same. The factory agents ship channels: ["*"]
— every channel their sender carries — so this only bites once you narrow it.
Check the channels line in the file you pulled before you go looking for a bug
in Telegram.
4. Pull the agent
index.ts:
The
voice block is what makes this agent answer calls. It runs the LLM
co-located in the voice network for the lowest latency, independent of the
model used for text. Remove the voice block and redeploy to turn the agent
back into a text-only agent.5. Deploy
6. Call it
Dial the sender’s phone number from your phone. Fermi greets you, qualifies the lead, and callsqualify_lead near the end of the conversation.
Prefer to test outbound? Place a call from code:
7. Watch it run
8. Iterate
Editindex.ts — tweak the prompt, add a defineTool, change the greeting —
and redeploy:
Common pitfalls
The agent doesn't answer calls
The agent doesn't answer calls
Confirm the sender has a phone number assigned.
Then check the deploy printed
Agents synced: + Fermi and that the voice
block has enabled: true.voice config ignored warning on deploy
voice config ignored warning on deploy
A field in your
voice block is out of range (e.g.
maxCallDurationMinutes above the cap) or misspelled. The deploy warns and
ships the agent as text-only rather than failing. Fix the value and
redeploy.A skill never gets called
A skill never gets called
The LLM decides when to call a tool from its
description. Rewrite each
description as the answer to “when should the model call this?” — vague
descriptions don’t trigger.Next steps
defineAgent in depth
Providers, models, prompts, and the voice block.
defineTool in depth
Schemas, handlers, returning structured data.
Voice configuration
Greetings, languages, voicemail, and transfer.
Secrets
Store SENDER_ID, API keys, and other env vars.
