# Runbook — "what's missing before it goes live?" / "I deployed and nothing changed"

> **Symptom.** *"¿qué le falta a mi agente para salir en vivo?"* · *"lo deployé y sigue igual"* ·
> *"cambié el prompt y responde lo mismo de antes"* · *"the agent is active but nothing happens"*.
>
> Two questions, one runbook, because the checks are the same list read in two directions: before
> launch you are confirming each item is present, after a deploy you are finding the one that
> silently did not land.

## Launch gate — the five that actually block traffic

Run `diagnose_agent` first; it covers several of these and returns the fix tool for each. Then
confirm by hand, in this order. An agent missing #1 receives zero messages no matter how good
everything else is.

| # | Check | Tool | Why it blocks |
|---|---|---|---|
| 1 | Linked to a connected account | `list_agent_channels` | Without the link, DMs never reach the agent. `is_active = true` is **not** enough — the platform creates the conversation with no agent attached and no trigger is ever evaluated. Must be linked in Studio, not by tooling, because the same action subscribes the Meta webhooks. |
| 2 | Trigger mode and keywords | `list_triggers` | A keyword-only agent with no registered keywords answers nothing. Mode is per **agent**, not per channel. |
| 3 | Agent enabled | `get_agent_config` | Check `is_active`. Also confirm you are looking at the production record, not a test one. |
| 4 | A terminal property with automation behind it | `list_custom_properties`, `list_contact_limits`, `list_custom_notifications` | A property nothing consumes is inert. Without a contact limit gated on it, the agent keeps messaging people who already converted; without a notification, the operator has to babysit DMs by hand. |
| 5 | A follow-up for leads who stall | `list_workflows` | A prompt never follows up. If there is no FOLLOW_UP workflow, every lead who goes quiet is lost by design. |

Items 4 and 5 are the ones that get skipped, because the agent "works" without them. It works and
it leaks: this is the single most common gap we find when auditing agents built by partner agencies
through the MCP — good prompts, incomplete systems.

Two more worth confirming before the operator watches real traffic:

- **The agent has been tested against realistic messages**, not just a happy path. Use
  `generate_synthetic_conversations` and read them.
- **Business hours / timezone are configured** if the offer depends on them, so the agent is not
  doing clock arithmetic in the prompt.

---

## "I deployed and nothing changed"

### H1 — You deployed to the wrong agent record

An agent's stored id can point at an inactive **test** record. The deploy succeeds, reports success,
and writes to a record that serves no traffic. Nothing in the output tells you.

- **Test:** `list_agents` and compare the id you deployed to against the one that is actually linked
  to a connected account.
- **Stop condition:** they differ → **you're done**.
- **Fix:** redeploy against the live record.

### H2 — The change landed in one file and the behavior lives in another

The most common silent no-op. Changing the prompt does not change:

- the **opening message** on a keyword — that is the trigger's literal response;
- **whether the agent stops** after a conversion — that is a contact limit;
- **whether anyone is notified** — that is a workflow or notification;
- **message length or splitting** — that is a platform setting, not a rule.

- **Test:** name the observable behavior the operator expected, then ask which layer owns it from the
  list above.
- **Stop condition:** the behavior is owned by a layer you did not touch → **you're done**.
- **Fix:** change that layer. A prompt rule aimed at a platform behavior is inert, and it will read
  as a deploy that "didn't work".

*Evidence: recurring across the launch-readiness bucket. 2026-05-18 — a new opener shipped in the
prompt only, with the keyword config untouched; production was unchanged.*

### H3 — A partial deploy left the agent inconsistent

Deploys made through the operator channel are frequently **additive**: the new instruction lands,
the old contradicting one survives, and the agent now holds both. The operator is told the change is
live, and for one path it is.

- **Test:** read the live prompt and search for the rule that was supposed to be replaced. If both
  the old and the new instruction are present, this is it.
- **Stop condition:** old and new coexist → **you're done**.
- **Fix:** remove the superseded instruction. Then check the same phrasing across the other SDK
  files, because the duplicate usually lives in more than one.

*Evidence: a clinic booking agent, 2026-06-19 — an operator-deployed rewrite reported as complete had
left the legacy path intact, verified against the deployed versions. Earlier the same month, nightly
operator deploys rebuilt a monolith on top of a refactor that had reduced the prompt from 1,186 to
111 lines, taking it back to 1,154.*

### H4 — Local and live have drifted

The deployed agent in the database is the source of truth; `agents/<name>/` is a working copy of it.
If they disagree, the local copy is the stale one — and if that is what you edited, nothing you
changed is serving traffic.

- **Test:** `get_agent_config` and diff it against local before making any further change.
- **Stop condition:** they differ in the section you edited → **you're done**.
- **Fix:** refresh local from the live config first, then re-apply your change and deploy. Never
  deploy over unexplained drift — the drift is usually someone else's un-synced change, and
  overwriting it re-introduces a fixed bug.

*Evidence: a marketing-agency agent — a reconciliation found the live prompt carried a dead booking
URL, duplicated sections, inconsistent openers, and the agent disabled with zero trigger keywords,
while local looked healthy. A local-services agent — the repo sat at v5 while the platform had been
iterated to v18 through the operator channel.*

### H5 — Something upstream failed silently

Sync jobs and deploy scripts can fail without surfacing an error, so the last known state is assumed
to still hold.

- **Test:** re-run the sync for the specific config you changed and read its output rather than its
  exit status.
- **Fix:** whatever it reports. Then treat a silent-failure path as a defect in its own right.

*Evidence: a clinic booking agent, 2026-08-11 — a keyword sync had been failing silently for days;
discovered only when a fix from four days earlier was verified in production.*

---

## When to stop

If all five launch checks pass, the live config matches what you deployed, and the behavior still
does not match, capture it: the agent id, the exact input, the expected and actual output, and the
deployed version you verified against. Send that with `report_feedback`.
