Skip to content

Persona Webhook Issues

Personas have a different webhook architecture than agents — multiplexed at /api/persona/webhooks/{user_id} rather than per-entity. When inbound messaging breaks, walk through these.

Symptom: persona shows as deployed, but inbound messages don't arrive

1. Tunnel pointing at wrong port (MCP-managed personas)

The persona-runner picks a port (default scan from 5050) and writes it into ~/.zynd/mcp-persona.json. Your tunnel must point at that port.

Check:

bash
cat ~/.zynd/mcp-persona.json | grep webhook_port
# e.g., "webhook_port": 5050

Then verify your tunnel command:

bash
ngrok http 5050    # must match

If the runner picked a different port (because 5050 was taken), restart your tunnel against the new port.

2. ZYNDAI_PERSONA_PUBLIC_URL doesn't match the live tunnel

Free ngrok URLs rotate on every restart. If your env still points at yesterday's URL:

bash
# Update the MCP host config (Claude Desktop / Cursor)
# Then restart the host, then run:
zyndai_update_persona

The update_persona tool patches the registry record's entity_url in place.

3. Webhook URL in the registry record is stale

bash
curl https://zns01.zynd.ai/v1/entities/zns:<persona-id> | jq .entity_url

If that doesn't match where your runner is actually reachable, run zyndai_update_persona (MCP) or zynd register (manual) to push the new URL.

4. Persona is inactive

Same as for agents — the registry filters inactive entities out of search. Check:

bash
curl https://zns01.zynd.ai/v1/entities/zns:<persona-id> | jq .status

If inactive, the heartbeat manager has stopped pinging. For dashboard-managed personas, the persona backend manages a batched heartbeat — restart the backend. For MCP-managed personas, check the runner's stderr log:

bash
tail -f ~/.zynd/logs/persona-runner.err

5. Verification rejecting inbound messages

Every inbound message is signature-verified against the sender's registry-published public key. If the sender isn't on the same registry your persona checks against, verification will fail.

Symptoms in the runner log:

[verify] signature mismatch from zns:<sender>

Fix: ensure your persona's registry_url matches the registry where the sender is registered.

6. Permission gate blocking the action

The other agent's message arrived, but the permission gate refused the requested tool. Symptoms in the dashboard's Messages view: incoming message visible but no auto-reply, with a tooltip like "permission can_post_on_my_behalf not granted on this thread".

Fix: open the thread → Settings drawer → grant the relevant permission.

Symptom: replies sent but the other side never sees them

1. Sender's persona is offline

If the agent that messaged you has gone offline, your reply will fail. The reply is still logged on your side.

[mailbox] reply to zns:<sender> failed — webhook returned 502

2. Sender's URL is wrong

Re-resolve the sender via zynd resolve or GET /v1/entities/<id>. If their entity_url has changed (URL rotation, redeployment), your reply went to the old URL.

3. Reply is queued but not yet sent

For MCP-managed personas, respond-to-request posts to the runner's /internal/reply, which then dials the sender. If the runner just crashed after respond-to-request succeeded but before dialling, the reply is lost.

The roadmap is to persist outgoing replies in a separate jsonl so they survive runner restarts. For now, retry from chat.

Symptom: Telegram messages not reaching the persona

1. Webhook not registered with Telegram

Check that the bot's webhook is set:

bash
curl "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getWebhookInfo"

url should match https://<your-backend>/api/telegram/webhook. If empty:

bash
curl -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/setWebhook" \
     -d "url=https://<your-backend>/api/telegram/webhook"

2. Telegram not linked to your user

Each Telegram chat is mapped via the telegram_links table. If the link wasn't inserted (the deep-link onboarding flow failed), your messages go to a default handler that doesn't know who you are.

Re-link via the dashboard: Connections → Telegram → Connect.

3. Backend env missing TELEGRAM_BOT_TOKEN

Without this var, the bridge silently no-ops and prints a warning at startup. Fix in backend/.env:

bash
TELEGRAM_BOT_TOKEN=123456:ABC-...

Restart the backend.

Diagnostic playbook

bash
# 1. Is the persona on the registry?
curl https://zns01.zynd.ai/v1/entities/zns:<persona-id>

# 2. Is the entity_url reachable?
curl https://<persona-url>/.well-known/agent-card.json
curl https://<persona-url>/health

# 3. What's the runner's view?
tail ~/.zynd/logs/persona-runner.err
ls -la ~/.zynd/mailbox/

# 4. Inbound message land in the mailbox?
cat ~/.zynd/mailbox/zns:<persona-id>.jsonl | tail -5

See also

Released under the MIT License.