PPactDocs
Glossary

Playbook

An event-driven automation rule in Pact: how PlaybookEngine matches a trigger event, evaluates conditions, and fires audited actions with per-account idempotency.

Playbook

A playbook is an event-driven automation rule: when a specific event fires on an account's timeline, if a set of conditions all pass, then run a list of actions. The engine is PlaybookEngine in core/playbook.py, and playbooks are managed under /v1/playbooks (api/routes/playbooks.py), gated by require_module("marketing").

Trigger and evaluation

Each playbook watches a single trigger_event. PlaybookEngine.evaluate(...) is called with an incoming event and the account_row; it iterates the loaded playbooks and only considers ones whose trigger_event matches the event's event_type (and whose tenant matches). For a matched playbook, all conditions must pass for the actions to fire.

Conditions

A condition is field op value, where field is a dot-path into the evaluation context. The context is the account row merged with the triggering event under _event — so icp_score, revenue_usd, _event.event_type, and _event.metadata.job_id are all addressable. Supported operators (_OPS in core/playbook.py):

eq, ne, gt, gte, lt, lte, contains, not_contains, exists, not_exists, in, not_in.

An unknown operator or a raised comparison evaluates to False (fail-closed), never an error.

Actions

Four action types are supported:

  • enqueue_job — enqueue a background job.
  • set_stage — update companies.crm_stage; when the stage actually changes, it also records a stage transition via core.activity.record_stage_transition (changed_by="playbook").
  • enroll_sequence — enqueue enrollment of the account into a sequence.
  • notify_webhook — enqueue an outbound webhook (fire_webhook).

Unknown action types are silently ignored, so a newer playbook definition degrades gracefully on an older engine.

Idempotency and audit

Every firing is written to playbook_run_log. When a playbook sets run_once_per_account=True, the engine checks playbook_run_log before firing and skips accounts it has already acted on — so a re-delivered event can't double-fire.

Dry-run testing

POST /v1/playbooks/{id}/test calls evaluate(..., dry_run=True). In dry-run mode no DB writes or job enqueues occur — it returns the list of actions that would fire (each record marked status="dry_run"), so you can validate a playbook against a simulated event before enabling it.

bash
curl -X POST https://api.pact.place/v1/playbooks/PB_ID/test \
  -H "Authorization: Bearer $PACT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": {"event_type": "deal_stage_changed", "metadata": {}}, "account": {"icp_score": 82}}'

Playbook vs journey

A playbook is a stateless rule that reacts to one event. A journey is a stateful, multi-step graph a subject travels through over time. Playbooks are a good way to start a journey (via enroll_sequence or a job), not a replacement for one.