Skip to main content

Debugging Functions

When your function isn’t behaving, the issue is usually in one of these layers:
Walk the layers top-to-bottom. The first one that fails is the one to fix.
If you use Claude Code / Cursor / Copilot, install Zavu’s Coding Agent Skills and ask your assistant “why isn’t my agent responding?” — it’ll run the diagnostic commands below in order and interpret the output.

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?

This is the most useful debug command. Three possible states:

a) “No executions.”

The inbound arrived but the agent dispatcher didn’t even try to invoke the agent. Causes:

b) status: error

The agent ran but something blew up. Fetch the full detail:
You’ll see errorMessage and errorCode. Common error categories:

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 with provider_error:
Look at the full errorMessage. Typical issues:
  • Bad model ID: e.g. openai/gpt-4o-mini works on provider: "zavu" (our gateway uses prefixed IDs), but the raw gpt-4o-mini works on provider: "openai" directly.
  • Expired API key (when using provider: "openai" etc.): rotate the key and update the agent’s apiKey.
  • Tool schema malformed: rare, but if your defineTool parameters 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:
Then send a message that should trigger the tool. You should see:
If you see nothing in the function logs but 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:
This runs the handler with synthetic args and prints the result. Iterate locally without redeploying. For deeper debugging, add ctx.log calls inside the handler:
Then npx zavudev deploy and npx zavudev 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 run npx zavudev 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:
…the issue is your code threw at module load time. Common causes:
  • Missing required secret: e.g. process.env.SENDER_ID! evaluates to undefined because you didn’t set the secret yet. Fix: npx zavudev fn secrets set SENDER_ID <value> then npx zavudev deploy.
  • Syntax error in your index.ts: the bundler caught it earlier but some edge cases get through. Run tsc --noEmit locally before deploying.

Local invocation cheat sheet

When all else fails

  1. Add ctx.log("got here", { someState }) aggressively in your handler.
  2. npx zavudev deploy and npx zavudev fn logs --tail simultaneously.
  3. Trigger the flow from a real conversation.
  4. Read the logs top-to-bottom — the first absence of expected output is the layer that’s failing.
  5. Open a ticket with the function ID, the executionId that failed, and the timestamp. Support can pull internal traces faster than guessing.