Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.usezombie.com/llms.txt

Use this file to discover all available pages before exploring further.

A zombie that’s misbehaving falls into one of six failure shapes. Find the symptom you’re seeing and follow the diagnostic chain.

Decision tree

SymptomMost likely causeStart here
zombiectl install --from exits non-zeroFrontmatter validation failed§1 Install rejected
Upstream says it sent the webhook, zombie didn’t wakeSignature mismatch or wrong URL§2 Webhook delivered but zombie silent
Zombie woke, stage failed before producing outputCredential, network, or tool error§3 Stage opens then fails
Stage produces a result but it’s wrongSKILL.md prose or memory issue§4 Stage runs but output is wrong
Stage terminates with budget_breachdaily_dollars / monthly_dollars ceiling hit§5 Budget breach
zombiectl itself is broken (auth, network)Local config or platform reachability§6 zombiectl can’t reach the platform

1. Install rejected

zombiectl install --from <path> exited with code 2. The platform parsed your SKILL.md + TRIGGER.md and rejected them.
zombiectl install --from ./my-zombie --json 2>&1 | tail -5
The --json output carries the wire error code:
Wire codeCauseFix
UZ-ZMB-008TRIGGER.md config_json fails schema validationRe-read Authoring §x-usezombie: subkeys. Common: a runtime key (tools, credentials, network) at the top level instead of nested under x-usezombie:.
UZ-ZMB-011SKILL.md and TRIGGER.md disagree on top-level name:Make both files’ name: value identical.
UZ-VAULT-001Credential data body is empty / not a JSON objectThe error is from a prior credential add call, not from install itself. Re-run zombiectl credential add <name> --data=@- with a non-empty JSON object.
For other codes, check Error codes and grep for the UZ- prefix. Local validation tip: the parser the platform uses is the same one zombiectl install --from runs — there’s no separate lint command. To catch schema errors before committing, run zombiectl install --from <path> --json and read the structured error output. Note the call still uploads on success; there is no --validate-only flag.

2. Webhook delivered but zombie silent

The upstream provider says it fired the webhook, your activity stream shows nothing.

Diagnostic

# All webhook-actor events in the last hour, including rejected ones
zombiectl events <zombie_id> --actor 'webhook:*' --since 1h --json
Three things to look for in the output:
PatternMeaning
Zero events in the windowRequest never reached the platform (DNS, firewall, wrong URL on the upstream side).
Events with rejection metadata, not stage opensSignature verification failed.
Events but actor: webhook:unknownSource label is missing or the signature block in TRIGGER.md doesn’t match the upstream’s actual headers.

Wire codes returned to the upstream

If the upstream itself shows a non-2xx response, the body carries one of:
Wire codeHTTPWhat to check
UZ-WH-001404URL is wrong. The path is https://api.usezombie.com/v1/webhooks/{zombie_id} — verify the ID matches zombiectl status.
UZ-WH-002400Request body is malformed JSON or empty.
UZ-WH-003403Zombie is paused or killed. zombiectl status will show the state; re-install with zombiectl install --from <path>.
UZ-WH-010401HMAC signature verification failed. The shared secret in your vault doesn’t match the one configured at the upstream. Rotate per Quickstart → Wire the GitHub webhook.
UZ-WH-011401Replay-window violation — request timestamp is older than 5 minutes. Sender clock skew is the usual culprit.
UZ-WH-020401No webhook credential configured for this zombie’s source. The secret_ref in TRIGGER.md either isn’t set or points at a vault key that doesn’t exist. Run zombiectl credential list to confirm; add with zombiectl credential add <source> --data=@-.
UZ-WH-030413Payload exceeds the 1 MiB ingest limit. The upstream is sending too much; filter or trim the event body before forwarding.

Common signature config mistakes

# WRONG — secret_ref references a vault key that doesn't exist
signature:
  secret_ref: github_secret    # but you ran: zombiectl credential add github
                               #              ^^^^^^ — name is "github", not "github_secret"

# RIGHT
signature:
  secret_ref: github
For first-class providers (github, slack, linear), don’t set header and prefix manually — the registry fills those. See Webhooks → Natively normalized providers.

3. Stage opens then fails

The webhook landed and a stage opened, but it terminated before producing output. The activity stream shows the stage, then an error event.

Diagnostic

zombiectl events <zombie_id> --since 1h --json | jq 'select(.error)'
Wire codeCauseFix
UZ-ZMB-003A required vault credential is absentThe credential name in TRIGGER.md credentials: doesn’t exist in the workspace vault. zombiectl credential list to confirm; zombiectl credential add <name> --data=@- to add.
UZ-ZMB-002Agent timeoutThe model didn’t return within the per-event ceiling. Often a sign the prompt is too large or the model is overwhelmed. Tighten SKILL.md or check tool_window in Context lifecycle.
UZ-MEM-003Memory backend unavailableTransient. Re-trigger; if persistent, file an issue.
UZ-MEM-001Memory scope deniedThe agent tried to read another zombie’s memory. Check the key derivation in SKILL.md — keys are zombie-scoped.
Tool-related failures don’t surface as wire codes. When a tools: entry has a typo, the executor logs UZ-TOOL-005 at warn level and silently skips it. When the agent tries to invoke a tool that isn’t in its resolved set, NullClaw returns a “no such tool” message in the activity stream rather than emitting UZ-TOOL-004 to a caller. Both UZ-TOOL-* codes exist in the registry (see Error codes → Tool) but in v2 today the diagnostic signal is the activity-stream entry, not a wire response. Audit zombiectl logs <zombie_id> for the actual error text. See Tools catalogue → Validation.

Network allowlist drops

If the agent calls http_request against a host not in network.allow:, the call fails silently from the agent’s perspective (the tool returns an error, the agent reasons about it). The drop appears in the activity stream as a tool-error event with the blocked hostname. Add the host to network.allow: in TRIGGER.md and re-install.

4. Stage runs but output is wrong

The hardest class of failure. Stage exits cleanly, the diagnosis posts to Slack, but the diagnosis is wrong, off-topic, or omits something it should have said.

Diagnostic

# Full event with the agent's tool calls and reasoning trail
zombiectl events <zombie_id> --since 30m --json | jq 'select(.actor | startswith("webhook:") or startswith("steer:"))'
The model’s tool-call trail tells you what it actually did. Compare against what your SKILL.md told it to do:
SymptomLikely cause
Agent skipped a step you specifiedStep is unclear, ambiguous, or buried mid-paragraph. Move it to a numbered list at the top.
Agent called the wrong endpointSKILL.md named the endpoint without context. Add the full URL or the credential name explicitly.
Agent hallucinated a valueSource data wasn’t in the event payload or a memory recall. Don’t ask the agent to invent — surface every input explicitly.
Agent re-asked for info you already gave itmemory_recall isn’t being called at the start of the stage. Audit your SKILL.md — recall must happen before reasoning. See Memory.
Agent posted twiceWebhook delivery is at-least-once. Add a dedupe step using the upstream event_id in memory_recall/memory_store.

Iterating on prose

SKILL.md is a prompt. The fastest debug loop is zombiectl steer:
zombiectl steer <zombie_id> "<the same input that triggered the bug>"
Edit SKILL.md, zombiectl install --from ., re-steer. The next event uses the new prose — no redeploy.

5. Budget breach

Stage terminated with UZ-ZMB-001. The daily_dollars or monthly_dollars ceiling in TRIGGER.md was hit.
zombiectl status --json | jq '.[] | select(.zombie_id == "<id>") | {state, budget}'
Two layers of cap exist independently:
  1. Per-zombie (TRIGGER.md budget.daily_dollars / monthly_dollars) — terminates this zombie’s stages until the rolling window resets. Raise the value, re-install.
  2. Tenant wallet — every workspace’s stages debit the same pool. When it hits zero, all stages across all workspaces stop. Top up at app.usezombie.com/billing. See Billing → Budgets.
If you’re hitting the per-zombie cap repeatedly on legitimate traffic, the zombie’s per-stage cost is higher than you sized for. Audit the activity stream for unusually long stages (high tokens or wall_ms fields), and consider tightening SKILL.md or splitting the work across multiple smaller zombies.

6. zombiectl can’t reach the platform

Anything that affects every command — login fails, status returns errors, install 401s.

Diagnostic

zombiectl doctor
Three checks run; all must pass:
CheckFailure means
server_reachableAPI is unreachable from your machine. Check your network. The base URL is https://api.usezombie.com (override with --api or ZOMBIE_API_URL).
workspace_selectedLocal config has no current_workspace_id. Run zombiectl workspace add [name] (creates + activates) or workspace use <id> (activates an existing one).
workspace_binding_validAuth token doesn’t have access to the selected workspace. Either the token expired (re-run zombiectl login) or the workspace was deleted on the server.
Pass --json for the structured envelope: { ok: bool, api_url: string, checks: [{ name, ok, detail }] }.

Auth resolution order

If zombiectl keeps acting unauthenticated, your token might be coming from somewhere unexpected. Resolution order, highest priority first:
  1. --token <value> flag
  2. ZOMBIE_TOKEN environment variable
  3. Stored credentials at ~/.config/zombiectl/credentials (written by zombiectl login)
Unset ZOMBIE_TOKEN if you’ve been running CI scripts that exported it; otherwise it overrides whatever zombiectl login wrote.

When to escalate

Two paths, depending on whether you want a fix or a faster sanity-check. Fast: ask in Discord. Best for “is this a known issue?”, “is this expected?”, or anything where you need a human eye in minutes rather than hours. Design partners and the core team hang out there. Durable: file an issue at github.com/usezombie/usezombie/issues. Best when the problem is reproducible, blocks shipping, or hits any of:
  • Diagnostic returns no error but the symptom persists across multiple triggers.
  • A UZ-INTERNAL-* or UZ-AUTH-004 (auth service unavailable) keeps firing.
  • zombiectl doctor passes but operations still fail.
Either way, include the request_id from the --json error envelope, the wire code, and a recent timestamp — those uniquely identify the request server-side.

See also