Debugging Functions
When your function isn’t behaving, the issue is usually in one of these layers:1. Did the inbound message arrive?
Open the dashboard → Senders → your sender → Conversations.- No message visible: the inbound never reached Zavu. Check your sender’s webhook (WhatsApp, Telegram) is wired up. The dashboard shows webhook config and recent delivery attempts.
- Message visible, no reply: inbound is fine, problem is downstream. Go to step 2.
2. Did the agent run?
a) “No executions.”
The inbound arrived but the agent dispatcher didn’t even try to invoke the agent. Causes:| Likely cause | Check |
|---|---|
Wrong SENDER_ID secret on the function | zavu fn secrets list — last 4 chars of the value must match the senderId you’re testing |
| Agent disabled | zavu agents get --sender <senderId> → enabled must be true |
| Channel filtered out | triggerOnChannels doesn’t include the inbound’s channel. Use ["*"] or include the specific one (e.g. "telegram") |
| Message type filtered out | triggerOnMessageTypes excludes the type (e.g. you sent an image and only "text" is allowed) |
| Empty message text | The dispatcher skips messages with no text. Inbound types like reactions or system events don’t trigger agents |
b) status: error
The agent ran but something blew up. Fetch the full detail:
errorMessage and errorCode. Common error categories:
errorCode | Meaning | Fix |
|---|---|---|
balance_insufficient | Provider zavu ran out of AI gateway balance | Top up balance in dashboard, or switch to BYOK by setting provider + apiKey in defineAgent |
rate_limited | Hit the LLM provider’s rate limit | Lower concurrency or wait |
provider_error | LLM provider rejected the call | Check the message text — sometimes prompts trigger safety filters. Also verify your model ID is valid for the provider |
tool_not_found | Agent tried to call a tool that doesn’t exist | Tool name in defineTool doesn’t match what the LLM is calling. Or the deploy didn’t reconcile — run zavu deploy again |
tool_error | A tool handler threw | Check the tool’s source. The errorMessage includes the handler’s exception text |
c) status: success but no message sent back
The agent succeeded but didn’t reply. Look at responseText in the execution
detail — if it’s empty, the LLM returned nothing useful. Adjust your
systemPrompt to encourage replies, or check that the model isn’t returning
just tool calls without a final response.
3. Is the LLM working?
If executions are failing withprovider_error:
errorMessage. Typical issues:
- Bad model ID: e.g.
openai/gpt-4o-miniworks onprovider: "zavu"(our gateway uses prefixed IDs), but the rawgpt-4o-miniworks onprovider: "openai"directly. - Expired API key (when using
provider: "openai"etc.): rotate the key and update the agent’sapiKey. - Tool schema malformed: rare, but if your
defineToolparameters JSON Schema has a typo, the LLM’s tool-calling step can fail. Validate the schema renders to valid JSON.
4. Did the tool get called?
Once the agent runs successfully but you suspect the tool wasn’t invoked, check the function logs:agents executions shows
success, the LLM chose not to call the tool. Tighten the tool’s
description so the LLM understands when to call it.
5. Is the tool handler buggy?
Once you confirm the tool is being called, isolate it locally:ctx.log calls inside the handler:
zavu deploy and zavu fn logs --tail while triggering the tool from
a real conversation. The [ctx.log] lines appear in the live tail.
Reconcile didn’t pick up my new agent / tool
When you runzavu deploy, the platform reads your defineAgent /
defineTool declarations from a manifest probe Lambda invocation, then
reconciles the live agent + tools to match. If you see:
- Missing required secret: e.g.
process.env.SENDER_ID!evaluates toundefinedbecause you didn’t set the secret yet. Fix:zavu fn secrets set SENDER_ID <value>thenzavu deploy. - Syntax error in your
index.ts: the bundler caught it earlier but some edge cases get through. Runtsc --noEmitlocally before deploying.
Local invocation cheat sheet
| Goal | Command |
|---|---|
| Test a single tool handler | zavu fn invoke --tool <name> --args '{...}' |
Test an event handler (defineFunction) | zavu fn invoke --event message.inbound --data '{...}' |
| Tail live production logs | zavu fn logs --tail |
| Query recent agent runs | zavu agents executions list --sender <senderId> |
| Full detail of one run | zavu agents executions get <executionId> --sender <senderId> |
| Inspect the agent config | zavu agents get --sender <senderId> |
| Inspect tools attached | zavu agents tools list --sender <senderId> |
| See what secrets are set | zavu fn secrets list |
When all else fails
- Add
ctx.log("got here", { someState })aggressively in your handler. zavu deployandzavu fn logs --tailsimultaneously.- Trigger the flow from a real conversation.
- Read the logs top-to-bottom — the first absence of expected output is the layer that’s failing.
- Open a ticket with the function ID, the
executionIdthat failed, and the timestamp. Support can pull internal traces faster than guessing.
