porchopsdev
DocsFormat reference
OpenPlaybook

Format reference

The shape of a .playbook.json document, generated from the shipped OpenPlaybook 1.11 schemas: the envelope, the playbook, its manifest, triggers, the seven step kinds, and guardrails.

The document envelope

An OpenPlaybook file is one JSON object: a format-version envelope around the playbook, plus optional declarations of what the playbook needs (connections, MCP servers, named secrets) and where it came from (provenance).

  • opbVersionstring · required
  • requiresobject
  • triggerFilterSchemasarray
    Per-source trigger filter schemas — the filterable dotted paths + primitive types for every webhook-trigger source this playbook references. Projected at export (SPEC §7.3); absent on pre-1.7 documents.
  • provenanceobject
    Origin attestation + tamper-detection signature over the playbook's executable core (its steps + embedded tool manifests) (SPEC §2.1; ADR `pps-manifest-signing`). Present on a signed first-party export; absent on an unsigned or pre-1.11 document (readers MUST tolerate the absence).
  • playbookobject · required

The playbook

The playbook object carries the work: identity and manifest, plain-English instructions, embedded tool definitions, triggers, the step graph, and guardrails.

  • idstring · required
  • playbookIdstring · required
  • opbVersionstring
  • versionstring · required
  • statusenum · required
    draftpublisheddeprecated
  • manifestobject · required
  • instructionsstring · required
  • configSchemaobject · required
  • toolsarray
  • triggersarray · required
  • stepsarray · required
  • guardrailsobject · required
  • onExitarray
  • testCasesarray
  • outcomeMetricsarray
  • changelogstring
  • documentationstring

Manifest

Identity and policy: the slug and name, the author, the category, the connectors and permissions the playbook requires, and its visibility and pricing tier.

  • idstring · required
  • slugstring · required
  • namestring · required
  • descriptionstring · required
  • authorobject · required
  • author.typestring · required
  • author.idstring · required
  • author.displayNamestring · required
  • categoryenum · required
    revenueretentionsupportonboardingoperationsgrowthcomplianceother
  • requiredConnectorsarray · required
  • requiredPermissionsarray · required
  • visibilityenum · required
    privateporchopsmarketplace
  • pricingTierenum · required
    freepremium
  • premiumPriceCentsinteger | null · required

Triggers

A trigger starts a run. The trigger union has 5 kinds:

webhookschedulemanualdependencyagent_finding

A schedule trigger carries a cron expression; a webhook trigger names its source and event (and may carry typed filters); manual, dependency, and agent_finding cover operator-started runs, run-after-run chaining, and agent-initiated work. The per-kind fields are in the spec repository.

Steps

A step is one node in the control-flow graph. Control flow is explicit: linear kinds carry a next edge naming the following step; decision steps carry branches. The validator enforces unique step ids, resolvable edges, and an acyclic, fully reachable graph. There are 7 kinds:

agent

One unit of model-driven work. Declares a plain-English purpose, the tools it may call (allowedTools), an optional output schema, an approval policy, and a failure mode. Declares an agent, a role, or both.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • retryarray
  • retry[].errorEqualsarray · required
  • retry[].intervalSecondsinteger · required
  • retry[].maxAttemptsinteger · required
  • retry[].backoffRatenumber · required
  • retry[].maxDelaySecondsinteger
  • retry[].jitterboolean
  • catcharray
  • catch[].errorEqualsarray · required
  • catch[].nextstring · required
  • kindstring · required
  • agentenum
    loufrankiehankdaleinky
  • roleenum
    bookkeepersupportsuccesschief-of-staffcomms
  • nextstring
  • preconditionsarray
  • allowedToolsarray · required
  • outputSchemaunknown
  • approvalPolicyobject
  • approvalPolicy.modestring · required
  • failureModeenum
    halt_runcontinue_on_failure
  • modelHintenum
    cheapstandardexpensive
  • effortTierenum
    low_effortnormal_efforthigh_effort
  • toolPoliciesobject
  • requiresKnowledgearray

tool

A scripted, deterministic tool call: one named tool, a fixed input expression, no model in the loop.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • retryarray
  • retry[].errorEqualsarray · required
  • retry[].intervalSecondsinteger · required
  • retry[].maxAttemptsinteger · required
  • retry[].backoffRatenumber · required
  • retry[].maxDelaySecondsinteger
  • retry[].jitterboolean
  • catcharray
  • catch[].errorEqualsarray · required
  • catch[].nextstring · required
  • kindstring · required
  • nextstring
  • toolstring · required
  • inputobject
  • outputSchemaunknown
  • failureModeenum
    halt_runcontinue_on_failure

decision

Explicit branching. Each branch carries a `when` expression and a `next` edge; `default` catches the rest. The graph must stay acyclic and fully reachable.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • kindstring · required
  • branchesarray · required
  • branches[].conditionstring · required
  • branches[].nextstring · required
  • branches[].descriptionstring · required
  • defaultstring · required

wait

Parks the run until a duration or condition passes. Conforming runtimes treat waits as explicit transitions, never wall-clock polling in a test context.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • kindstring · required
  • nextstring
  • waitobject · required
  • wait.modestring · required
  • wait.durationSecondsinteger · required
  • timeoutstring · required

map

Fan-out over a list: runs an item step (or sub-playbook) per element, with concurrency and item caps.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • retryarray
  • retry[].errorEqualsarray · required
  • retry[].intervalSecondsinteger · required
  • retry[].maxAttemptsinteger · required
  • retry[].backoffRatenumber · required
  • retry[].maxDelaySecondsinteger
  • retry[].jitterboolean
  • catcharray
  • catch[].errorEqualsarray · required
  • catch[].nextstring · required
  • kindstring · required
  • nextstring
  • itemsPathstring · required
  • maxConcurrencyinteger · required
  • maxItemsinteger
  • itemStepstring
  • subPlaybookstring
  • toleratedobject
  • tolerated.failureCountinteger
  • tolerated.failurePercentagenumber

approval

A human gate. The run holds until an approver decides or the gate times out; an expired gate is terminal, never an implicit approve.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • kindstring · required
  • nextstring
  • approverstring · required
  • timeoutstring · required
  • onTimeoutenum · required
    cancelescalate

terminator

Ends the run, with a reason. Every path through the graph ends at one.

  • idstring · required
  • purposestring · required
  • dataScopearray
  • dataScope[].resourcestring · required
    Namespaced resource the step touches (e.g. 'customer', 'stripe.invoice', 'inbox', 'kb').
  • dataScope[].directionenum · required
    'read' gates what enters model context; 'write' gates what a tool may mutate (§49.2(b)).
    readwrite
  • dataScope[].fieldsarray · required
    Allow-list of field paths on the resource the step is permitted to touch.
  • authoredByobject
  • authoredBy.typeenum · required
    Whether a person, an authoring agent, or a human-over-AI accept produced this node.
    humanaicomposite
  • authoredBy.actorIdstring · required
    The user id (human) or agent id (ai) that authored the node.
  • authoredBy.sourcestring · required
    The affordance that produced the edit (e.g. 'manual', 'cold_start', 'chatbar').
  • authoredBy.rationalestring
    Why the operator overrode or edited an AI proposal (PB-7c / D-4). Bound to the row's provenance so it travels with the artifact and feeds the §44 get-better calibration. Present only on a `composite` override; omitted otherwise.
  • kindstring · required
  • reasonstring

Guardrails

The run's hard limits. Cost caps are authored in the document's own denomination (cents at the format level); a Level 3 runtime meters in its own denomination on top.

  • maxRunDurationSecondsinteger · required
  • maxLlmCostCentsinteger · required
  • maxRunsPerDayinteger
  • requiresApprovalForarray
  • excludedCustomerSegmentsarray

A complete document

This is a real document from the spec's conformance corpus (vector approval-expiry): a drafted email held at an approval gate. The tutorial walks it end to end.

approval-expiry.playbook.json
{
  "opbVersion": "1.6",
  "requires": {
    "connections": [],
    "mcpServers": [],
    "secrets": []
  },
  "playbook": {
    "id": "pvr_D17KJBXF1JN52X4RR9XXQQ8825",
    "playbookId": "plb_429B94127Y0TRRXKVC2FQ9RR25",
    "opbVersion": "1.6",
    "version": "1.0.0",
    "status": "published",
    "manifest": {
      "id": "plb_429B94127Y0TRRXKVC2FQ9RR25",
      "slug": "conf-approval-expiry",
      "name": "Conformance: approval expiry",
      "description": "A held email draft whose gate expires with no decision terminates the run.",
      "author": {
        "type": "porchops",
        "id": "porchops",
        "displayName": "PorchOps"
      },
      "category": "operations",
      "requiredConnectors": [],
      "requiredPermissions": [
        "email.draft"
      ],
      "visibility": "private",
      "pricingTier": "free",
      "premiumPriceCents": null
    },
    "instructions": "Draft the apology email, hold it at the gate; if the operator never decides, the gate expires and the run ends.",
    "configSchema": {},
    "tools": [],
    "triggers": [
      {
        "kind": "webhook",
        "source": "payments",
        "event": "charge.failed"
      }
    ],
    "steps": [
      {
        "id": "draft",
        "kind": "agent",
        "role": "support",
        "purpose": "Draft a short apology email to the customer email address named in the trigger payload, as a single email_draft artifact.",
        "allowedTools": [],
        "approvalPolicy": {
          "mode": "auto"
        },
        "failureMode": "halt_run",
        "next": "gate"
      },
      {
        "id": "gate",
        "kind": "approval",
        "approver": "operator",
        "timeout": "7d",
        "onTimeout": "cancel",
        "purpose": "Hold the drafted email for the operator's decision before the run may continue.",
        "next": "done"
      },
      {
        "id": "done",
        "kind": "terminator",
        "reason": "The operator approved (never reached in this vector).",
        "purpose": "End the run after approval; unreachable - the gate expires first."
      }
    ],
    "guardrails": {
      "maxRunDurationSeconds": 300,
      "maxLlmCostCents": 0,
      "requiresApprovalFor": []
    }
  }
}