# Runbook: the contact didn't land in the pipeline (the pipeline automation didn't fire)

> **Symptom.** *"la automatización del pipeline no agregó el contacto cuando cambió la
> propiedad"* · *"el lead calificó y no aparece en el pipeline"* · *"quedó en la etapa
> equivocada, no se movió"* · *"pipeline automation FACT_CHANGED not firing
> ADD_CONTACT_TO_PIPELINE evaluator property"* · *"the contact never moved to the next stage"*.
>
> Split it first: **not in the pipeline at all** → H1–H4. **In the pipeline, wrong stage** →
> H5–H6. The chain is always the same: the evaluator writes a contact property, the change
> becomes a fact event, the rule reads the event. Mechanics in `how-to/native-crm`.

```text
lead says it → property flips → fact event (needs the CRM add-on) → rule matches → record added / moved
```

## What you need first

- The workspace id, the contact id and the rule name.
- The time the triggering property flipped (`get_contact`: each property's `updated_at`).

No MCP tool lists rule executions: `get_crm_pipeline_automations` returns the rules, not their
runs. Each test below reads configuration or the record instead.

---

## Not in the pipeline at all

### H1: The CRM add-on was off when the property flipped

Without the add-on the property is saved, but its automation event is discarded, and turning the
add-on on later does not replay it. The tell: properties are true, rules are fine, and the
contact has no record.

- **Test:** `get_crm_overview` → `features.pipelineAutomations`. Off now → that is the answer.
  On now → ask an org admin when the add-on was turned on (Studio, organization billing page)
  and compare with the flip time.
- **Stop condition:** add-on off now, or turned on after the flip → **you're done**.
- **Fix:** an org admin turns it on (`how-to/native-crm`, "The CRM add-on"). Then add each
  contact that flipped meanwhile by hand: `execute_crm_pipeline_command({idempotencyKey,
  command:{intent:"add-contact", contactId, pipelineId, stageId}})`. Re-writing the same value
  does nothing (H3).

*Evidence: a B2B services account, 2026-11-07. Three properties written true by the evaluator,
three matching enabled rules, no record. All three events were discarded as "not entitled": the
add-on trial started three hours after the flips. The same rules had worked a week earlier.*

### H2: The property never flipped

The rule is correct and simply never sees a change. Same failure as every other property-gated
automation.

- **Test:** `get_contact` → the triggering property's `is_set`, value and `updated_at`.
- **Stop condition:** not set, or false, on a contact where the event clearly happened → **you're
  done**.
- **Fix:** the property, not the rule. `custom-properties`, "The two gates that make a property
  look broken"; for a relayed channel, also `runbooks/notification-never-arrives` H3.

*Evidence: an automotive account on a relayed WhatsApp channel, 2026-09: no property was ever
written on agent-handled conversations, so no tag, stage or CRM action fired downstream.*

### H3: The rule does not match the value, or it came too late

Unvalidated (from code, no case yet). Three ways a correct-looking rule never runs:

- **Value mismatch.** Values are strings; an option property compares by **option id**, not
  label; a boolean rule needs `EQUALS` `"true"`.
- **Rule newer than the change.** Rules are read as they were when the property changed, and a
  rule runs on a change, not on a state. Creating or enabling a rule after the property was
  already true does nothing for that contact.
- **Disabled or archived.**
- **Test:** `get_crm_pipeline_automations` → the rule's `enabled`, `trigger.definitionId`,
  `trigger.operator`, `trigger.value`, and its `updatedAt` against the flip time.
- **Stop condition:** any of the three → **you're done**.
- **Fix:** `manage_crm_pipeline_automation` (`save` with the current `expectedRevision`), then
  add the contacts already past the flip by hand, as in H1.

### H4: Only `MOVE` rules, and the contact had no record to move

A `MOVE_PIPELINE_RECORD` rule never creates a record. If the contact was never added, the rule is
refused (`SOURCE_RECORD_NOT_FOUND`).

- **Test:** `get_crm_pipeline_automations` → is there an `ADD_CONTACT_TO_PIPELINE` rule for this
  pipeline on the property the contact flipped first?
- **Stop condition:** no `ADD` rule on the entry property → **you're done**.
- **Fix:** add one `ADD` rule on the entry property (`how-to/native-crm`, "The pattern that
  works").

*Evidence: 7 refusals in 2 workspaces, 2026-10/11 (platform execution records).*

---

## In the pipeline, wrong stage

### H5: The rule is an `ADD`, and the contact was already in the pipeline

`ADD_CONTACT_TO_PIPELINE` only opens a record. A contact that already has an active record in that
pipeline is refused (`ACTIVE_RECORD_EXISTS`) and stays in its stage. This is the most frequent
outcome of a pipeline automation that did not do what the operator expected.

- **Test:** `get_crm_pipeline_automations` → for the destination stage, is there a
  `MOVE_PIPELINE_RECORD` rule, or only an `ADD`?
- **Stop condition:** only `ADD` rules point at that stage → **you're done**.
- **Fix:** add `MOVE` rules, one per stage the contact can come from, each with its
  `sourceStageId`. Keep the `ADD` for contacts not in the pipeline yet.

*Evidence: about 10,300 `ACTIVE_RECORD_EXISTS` refusals across 10 workspaces, 2026-10/11 (most of
them harmless `ADD` halves of a correct ADD + MOVE pair); separately, 148 manual `add-contact`
calls hitting the same refusal in one week, 2026-10.*

### H6: The `MOVE` rule's source stage is not where the record is

A `MOVE` rule with a source stage only runs when the record is in that exact stage; otherwise it
is skipped and leaves no trace. The usual gap: the rule moves "from Nuevo", and the record was
already in a later stage.

- **Test:** `get_crm_pipelines({pipelineId, recordId})` → the record's current stage, against
  the `sourceStageId` of every `MOVE` rule on the property.
- **Stop condition:** no `MOVE` rule starts from the record's current stage → **you're done**.
- **Fix:** add the missing `MOVE` rule for that source stage, or one `MOVE` with no source stage
  that matches from any stage. Only one `MOVE` or `TRANSFER` runs per change (lowest `priority`
  that matches), so do not try to chain them.

Unvalidated (from code, no case yet).

---

## Not this runbook

- The contact is in the pipeline but **owned by the wrong person**: that is routing
  (`get_crm_routing`), not a pipeline automation. Routing criteria on conversation- or
  record-scoped properties never fire, because the evaluator writes only contact facts.
  *Evidence: two cases on an aesthetics clinic, 2026-10.*
- The contact should be in **GoHighLevel**, not the native CRM: `how-to/gohighlevel-and-crm`.

## When to stop

If the add-on was on at the flip, the property changed after the rule existed, the rule matches
the value, and the record's stage has a rule that starts from it, capture it: the contact id,
the property with its `updated_at`, the rule id and revision, the record id and its current
stage. Send that with `report_feedback`.
