Skip to main content

Playbooks and flows API

Playbooks and Flows are control-plane resources. They coordinate normal Kheish runs rather than replacing them.

Endpoint inventory

Playbooks:
  • GET /v1/playbooks
  • POST /v1/playbooks
  • POST /v1/playbooks/validate
  • GET /v1/playbooks/{playbook_id}
  • POST /v1/playbooks/{playbook_id}/publish
  • POST /v1/playbooks/{playbook_id}/revoke
Flows:
  • GET /v1/flows
  • POST /v1/flows
  • GET /v1/flows/{flow_id}
  • POST /v1/flows/{flow_id}/cancel
  • POST /v1/flows/{flow_id}/evidence
  • POST /v1/flows/{flow_id}/verify/product-view
  • GET /v1/flows/{flow_id}/stream

Playbook manifest

POST /v1/playbooks/validate and POST /v1/playbooks both accept:
The daemon computes a digest over the immutable manifest body. Creating the same playbook_id + version + digest is idempotent. Creating the same playbook_id + version with a different digest is rejected. Manifest fields such as tools, runtime_defaults, scopes, and required_evidence are stored and digest-covered. Flow start still executes a normal SubmitInputRequest; enforcement is expressed through start-time scope checks and Flow contract projection rather than a separate workflow runtime. A durable schedule can also carry flow_start; in that case the root run is a scheduled input run with Flow correlation metadata. When tools.enforce is true, Flow views evaluate scoped session journals against the manifest allow/deny lists. A completed run that used a blocked or non-allowed tool is projected as fail-closed instead of succeeded. scopes.required_capability_scope and scopes.required_credential_scope use the daemon CapabilityScope and CredentialScope shapes. Flow start rejects sessions whose current scope is wider than these requirements. This keeps scope enforcement on the existing session capability/credential machinery rather than introducing a second runtime. required_evidence can be declared at the manifest top level and per phase. Missing required evidence prevents a completed Flow from reporting success. Known primitive refs such as run, task, agent, approval, question, schedule, output, and flow must resolve inside the Flow projection; other evidence kinds are treated as operator attestations and can be appended later.

Publish and revoke

POST /v1/playbooks/{playbook_id}/publish accepts:
Allowed publish statuses are verified, canary, and active. Publishing to one of those statuses requires evidence_refs. POST /v1/playbooks/{playbook_id}/revoke accepts:

Start a Flow

POST /v1/flows accepts:
The request field is the normal SubmitInputRequest shape used by session run creation. The daemon validates and normalizes that request through the existing session-run path. Flow start writes daemon-owned kheish_flow metadata into the underlying run. Callers must not provide that metadata key themselves. The metadata includes the Flow id, Playbook id, version, digest, and a daemon-generated nonce used for recovery matching. Retries are idempotent only when the submitted flow_id, idempotency_key, Playbook reference, session id, input request, Flow metadata, and evidence refs match the existing Flow.

Flow status

Flow status is derived from scoped daemon primitives, not from a persisted flow.status field. The scope starts with the root run and includes sidechain agents spawned from that run, runs in those child sessions, scoped session tasks, and approval/question ids from current run state and historical run events. FlowView.status uses Flow statuses such as succeeded; the embedded run, when present, is a normal RunView with normal run statuses such as completed. Any interrupted scoped run projects the Flow to interrupted.
  • no run reference yet -> pending
  • cancelled before run scheduling -> cancelled
  • failed scoped run or failed scoped task -> failed
  • cancelled scoped run or cancelled scoped task -> cancelled
  • waiting scoped run or blocked scoped task -> waiting
  • queued/running scoped run or pending/in-progress scoped task -> running
  • completed scoped work with no failed/cancelled/running/waiting work -> succeeded
  • interrupted scoped run -> interrupted
  • missing referenced run -> unknown
Failure and cancellation are fail-closed: a scoped failed task prevents the Flow from appearing succeeded just because the root run produced a positive final answer. Flow views include:
  • phase_states: one derived entry per manifest phase with pending, satisfied, or blocked.
  • contract: generic validation checks for required evidence and enforced tool policy.
  • completed_at_ms: the first terminal projection boundary. Later reused child-session activity is ignored so an old Flow cannot regress after it has settled.

Append Flow evidence

POST /v1/flows/{flow_id}/evidence accepts:
Appending evidence is idempotent by kind + id. Known daemon primitive kinds must resolve inside the Flow projection. The response is the updated FlowView, so operators can immediately see whether required evidence gates now pass. GET /v1/flows/{flow_id}/stream is a thin proxy over the referenced run stream. It does not create a second Flow event bus.

Evidence Used

  • DTOs and status mapping: crates/kheish-daemon/src/playbooks.rs
  • API routes: crates/kheish-daemon/src/api/handlers.rs
  • Run scheduling path: crates/kheish-daemon/src/state/playbook_workflow.rs

Evidence Note

  • Code verified: crates/kheish-daemon/src/playbooks.rs, crates/kheish-daemon/src/state/playbook_workflow.rs, crates/kheish-daemon/src/api/handlers.rs, crates/kheish-daemon/src/cli/commands/playbooks.rs.
  • CLI/API verified: endpoint inventory and command names checked against implemented routes and CLI commands.
  • Daemon live tested for this note: yes; an isolated daemon with OpenAI gpt-5.4 started a Flow, completed a real provider run, failed closed while required manual evidence was missing, then recovered to succeeded after flows evidence.
  • Provider-specific tested for this note: OpenAI gpt-5.4 smoke for Flow start, run completion, evidence gate, and evidence append.