Documentation source
SOPs & Process OS
Living SOPs as entities — imported from documents, run on the action spine, scored for delegation, and bridged into the AI opportunity portfolio.
# SOPs & Process OS
The Process OS turns an organization's standard operating procedures into living records: imported from real documents, executed as runs with per-step live status, scored for human→agent delegation readiness, and mined for AI-automation opportunities. It is built entirely on the platform's six primitives — no SOP-specific engine, tables, or tools exist (ADR-0055).
## Key concepts
- **SOP** — a canonical `sop` entity. Status lifecycle `draft → active → archived` lives in content; publishing a draft is a standard entity status update.
- **Step** — a child `task` entity (`parent_id` = the SOP, 1-based `content.sequence_order`). Each step carries a `delegation_state` (`human_only → trialing → agent_supervised → agent_autonomous`) — the same field the Delegate flow promotes.
- **Run** — `ensureSopRunActions` compiles the SOP into a `sop-run-<sopId>` parent action plus `sop-step-<taskEntityId>` child actions chained with `depends_on`. `runSop` triggers the tree through `trigger_task_atomic`; human steps wait in `waiting_human`, agent steps execute via the session executor.
- **Routine** — the parent run action flipped to a cron trigger. No separate scheduler.
- **Opportunity** — a `use_case` entity captured from a delegatable step by the deterministic `sop-to-opportunity` ActionDefinition, linked back via a `sop —supports→ use_case` relation and ranked by the existing AI portfolio.
## How it works
```
document ──import skill──▶ sop (draft) + ordered task steps
│ publish (status update)
▼
sop (active) ──ensureSopRunActions──▶ sop-run action tree
│ │ runSop / cron
▼ ▼
read-model projection ◀───────────── sessions (per-step state)
│
▼
/api/sops ──▶ SOP library UI (steps · runs · opportunities)
```
- **Read model** (`features/sops/server/read-model.ts`): projects entities + actions + sessions into `SopSummary` / `SopDetail`, including per-step live state (`todo / now / done / blocked`) and the run handle (`SopDetail.run`). Served by `GET /api/sops` and `GET /api/sops/[id]`.
- **Run UX**: the SOP detail header carries a Run button (active SOPs only; disabled while a run is in flight). The Runs tab reuses the actions module's `RoutineRecentRuns` and offers the routine toggle (cron presets or custom). Step states poll every 5s while a run is active.
- **Import**: the `import-sops-from-document` tenant skill (manifest-bound action, drafts-only posture) reads a document and batch-creates the SOP + parented, ordered steps. Library entry point: "Import SOPs" → document picker → drafts rail for review/publish.
- **Opportunities**: the Opportunities tab (injected through the generic `extraTabs` prop from custom code) lists captured `use_case` rows with expected value and offers idempotent extraction; rows flow into `/ai-portfolio`.
## API reference
| Surface | Shape |
| --- | --- |
| `GET /api/sops?status=&workstreamId=` | `{ sops: SopSummary[] }` |
| `GET /api/sops/[id]` | `{ sop: SopDetail }` (includes `steps[].state`, `run`) |
| `POST /api/sops/import` | `{ documentId }` → 202; runs the import skill |
| `POST /api/sops/[id]/run` | 202 `{ parentSessionId }`; 409 unless `status === "active"` |
| `POST /api/sops/[id]/routine` | `{ enabled, schedule? }` → ensures the run action + sets/clears the cron trigger |
| `runSop(tenantId, sopId, userId)` | server seam behind the run route |
| `extractSopOpportunities(sopId)` | custom server action (gates `entities.team.update`) running the `sop-to-opportunity` ActionDefinition |
## For agents
Zero dedicated SOP tools exist (D9 — skills over tools). Agents work SOPs through generic entity tools guided by three skills:
- **`manage-sops`** (platform skill) — the canonical work-model: how to read SOPs and steps (`getDescendants`), the status vocabulary, delegation states, and runs-as-sessions.
- **`import-sops-from-document`** (tenant skill + action row) — drafts SOPs from an uploaded document. Steps MUST set `parentId` in the same `batchCreateEntities` call and a 1-based `content.sequence_order`; never "Step N" title prefixes.
- **`sop-opportunity-analyst`** (platform skill) — when and how to run the `sop-to-opportunity` extraction and refine its recorded assumptions.
Per-tenant action rows are seeded by `scripts/seed-{oci,marbella}-skills.ts` (idempotent; the import action requires a LOCAL agent with `document` + `entity` tool groups).
## Design decisions
- **No parallel run system** — runs are ordinary action/session trees; routines are cron triggers on the same action (ADR-0055).
- **Drafts gate publication** — the import skill writes drafts only; human review + publish is the safety boundary, not write-time approval.
- **EV is deterministic and auditable** — extraction records every default in `content.assumptions`; humans refine by editing the `use_case`.
- **Platform stays slug-free** — `use_case`/`sop` product logic lives in `features/custom/**`; the platform's only concession is the generic `extraTabs` injection point.
## Related modules
- [Agent system](/docs/features/agent-system) — executor, delegation, permissions
- [Tool system](/docs/features/tool-system) — generic entity tools the skills rely on
- [Skills](/docs/features/skills) — manifest bindings and `runSkill`
- [Sessions](/docs/features/sessions) — the run substrate