AI Workforce — Business Process Runbooks
Human-facing process maps for operating the AI Workforce. The feature doc explains the architecture; this doc explains who does what, when, and how to recover when things go sideways.
Every node in every diagram traces to real code — see Cross-references at the bottom.
Process Inventory
| # | Process | Trigger | Primary Actor | Cadence | Inputs | Outputs | Success Signal | Escalation |
|---|---|---|---|---|---|---|---|---|
| 1 | Run Lifecycle | Cron tick or admin "Trigger run" | System (Rails + Agent Runner) | Per-employee schedule (daily / weekly / biweekly) | AiEmployee config, memory, skills | AiArtifact(pending) on the Ops Board | AiRun.status = succeeded, artifact appears on the board within 2 min of run completion | Run stuck in running > 15 min → inspect Run Detail; Agent Runner unreachable → see Process 5 |
| 2 | Ops Board Review Decision | New AiArtifact(pending) appears | Ops operator (admin) | Continuous; target ≤ 4 hr response SLA during business hours | Artifact payload, preview, delivery metadata | Approve / Approve-with-edits / Reject + reason | Artifact approval_status transitions to approved or rejected; DeliverArtifactJob enqueued on approve | Reject count > 2 for same employee in 1 week → pause employee, review memory/skill config |
| 3 | Delivery Routing | ApproveArtifact success event | System (DeliverArtifactJob) | Immediate (async) on approval | Approved artifact, artifact.kind, destination creds | GitHub PR / Mailtrap draft / Slack message / docs commit | delivered_at timestamp set; external ID recorded (PR URL, draft ID, etc.) | delivery_status = failed → check agent-runner-ops credentials, retry manually from Run Detail |
| 4 | Activation Funnel WoW | Cron tick (daily at midnight UTC) | System (Rails endpoint) | Daily · 0 0 * * * | 7-day rolling-window user cohorts | Metrics: signed_in, wizard_completed, first_goal, first_check_in, first_badge + WoW % change | Response 200 + log entry shows current/previous counts and WoW % | skip_run=true (zero cohort) → log and continue; 401/422 → log config error, investigate secret/server; 5xx → retry 3x with backoff |
| 5 | Autonomy Promotion | Operator clicks "Promote" in Employee Detail | Team lead (Josh / delegated) | Quarterly review; ad-hoc when criteria met | Approval-rate chart, weeks-active, recent-rejections, role type | Autonomy level change (shadow → semi → autonomous) | DB validation promotion_requirements_met passes; level committed; employee card badge updates | Blocked by validation → fix criteria gap or acknowledge role lock (Ally is shadow-only) |
| 6 | Failure & Budget Circuit | Any error: agent runner down, HMAC mismatch, error_max_turns, budget exceeded | System → operator | On exception | Error payload, run_log, tokens_used, month_spend | Run transitions to failed with error_message; Slack budget alert fires for monthly cap | Circuit-breaker retries exhaust or budget alert fires → operator inspects, pauses or bumps cap | HMAC signature mismatch persisting → rotate RAILS_WEBHOOK_SECRET, coordinated redeploy (both services) |
| 7 | Operator Cadence | Time (daily / weekly / monthly / quarterly) | Ops operator + team lead | Recurring | Admin dashboard, Slack alert channel | Queue drained, health recorded, promotions considered | Zero pending artifacts > 24h; no paused employees without reason; budget utilization < 90% | Cadence misses 2 cycles → raise in weekly lead review |
Process 1 — Run Lifecycle (End-to-End)
How one execution flows from a scheduler tick to a delivered artifact.
flowchart LR
subgraph Trigger
A[Crono: every 5 min] --> B[ScheduleRunsJob]
A2[Admin: Trigger Run button] --> C
B --> C{TriggerRun<br/>budget gate}
end
C -->|month_spend ≥ cap| X1[Fail: monthly_budget_exceeded]
C -->|concurrent run exists| X2[Fail: already_running]
C -->|ok| D[AiRun queued]
D --> E[ExecuteRunJob]
E --> F[AgentRunnerClient<br/>POST /runs]
subgraph AgentRunner[Agent Runner service]
F --> G[Load skills + memory + MCP]
G --> H[query loop<br/>maxTurns, maxBudgetUsd]
H --> I{post_filter_skill<br/>configured?}
I -->|yes| J[Brand-voice query<br/>auto_reject on fail]
I -->|no| K[Skip post-filter]
J --> L[webhook sender<br/>HMAC signed]
K --> L
end
L --> M[Rails: /webhooks/ai-workforce]
M --> N{HMAC valid?}
N -->|no| X3[401 + log]
N -->|yes| O[ProcessWebhookResult]
O --> P[Upsert AiEmployeeMemory]
O --> Q[Create AiArtifact pending]
Q --> R[(Ops Board<br/>Needs review column)]
R -.-> S[Process 2: Review]
style X1 fill:#fee,stroke:#c33
style X2 fill:#fee,stroke:#c33
style X3 fill:#fee,stroke:#c33
style R fill:#eef,stroke:#55a
Operator notes
- Actor: None — fully automated until artifact lands on the Ops Board.
- Trigger: Crono tick (scheduled) or admin clicks "Trigger run" on an employee card.
- Latency: Typically 30s–3min end-to-end. Runs > 15 min in
runningstate are stuck (Agent Runner lost the fire-and-forget call or webhook failed). - Success signal:
AiArtifactappears on the Ops Board's Needs review column withapproval_status = pending(orauto_rejectedif post-filter blocked it). - Where to look: Admin → Run Detail for tool calls, cost, duration; Run Log JSON has the full SDK trace.
- Escalation: Stuck run → check agent-runner-ops; repeated budget fails → Process 5.
Process 2 — Ops Board Review Decision Tree
What the operator does when they open a pending artifact's Focus Detail overlay.
flowchart TD
A[Operator opens ticket<br/>Focus Detail overlay] --> B[Artifact card expands]
B --> C{Artifact kind?}
C -->|code_patch| D[Render diff2html<br/>read-only]
C -->|email_template / slack_message / report / other| E[Editable textarea]
D --> F{Quality check}
E --> F
F -->|Good as-is| G[Click Approve]
F -->|Small edits needed| H[Edit payload inline]
F -->|Off-brand or incorrect| I[Click Reject]
H --> G2[Click Approve]
G --> J[ApproveArtifact<br/>record reviewer + timestamp]
G2 --> J2[ApproveArtifact<br/>record edit_distance Levenshtein]
I --> K[Enter reason ≥ 10 chars]
K --> L[RejectArtifact]
J --> M[Publish event<br/>ai_workforce.artifact_approved]
J2 --> M
M --> N[Enqueue DeliverArtifactJob]
N --> O[Process 3: Delivery]
L --> P[Set approval_status rejected]
P --> Q[Append reason to<br/>employee memory<br/>recent_rejections FIFO cap 5]
Q --> R[Surfaces in next run<br/>via memory injection]
style J fill:#efe,stroke:#393
style J2 fill:#efe,stroke:#393
style L fill:#fee,stroke:#c33
style R fill:#eef,stroke:#55a
Operator notes
- Actor: Ops operator (admin role).
- Cadence: Continuous; target first-response within 4 hours during business hours. Queue polls every 30s.
- Reject rule: Reason is required (min 10 chars) and becomes training data — write it as if teaching the employee ("too long, cut to 3 sentences" beats "bad").
- Edit distance signal: Heavy edits on approval (Levenshtein ratio > 0.3) = artifact is borderline; watch for a pattern across runs.
- Escalation: 2+ rejects in one week for the same employee → pause it (Process 6 weekly review) and inspect skill config / memory.
Process 3 — Delivery Routing
How an approved artifact reaches its destination.
flowchart LR
A[Approved Artifact] --> B[DeliverArtifactJob]
B --> C{delivered_at<br/>already set?}
C -->|yes| Z[No-op idempotent]
C -->|no| D{artifact.kind?}
D -->|draft_post / code_patch| E[deliver_github_pr]
D -->|email_template| F[deliver_mailtrap_sandbox]
D -->|report| G[deliver_report_slack_and_docs]
D -->|recommendation| H[deliver_recommendation_to_docs]
E --> E1[Create branch via Octokit]
E1 --> E2[Commit file]
E2 --> E3[Open PR]
E3 --> E4[Record PR URL in<br/>delivery_metadata]
F --> F1[POST draft to<br/>Mailtrap sandbox inbox]
F1 --> F2[Record draft_id<br/>never sends to recipients]
G --> G1[Validate host = hooks.slack.com]
G1 --> G2[POST to Slack webhook]
G2 --> G3[Octokit commit to<br/>docs/reports/ path]
H --> H1[Octokit commit to<br/>docs/recommendations/]
E4 --> Y[Set delivered_at<br/>delivery_status = delivered]
F2 --> Y
G3 --> Y
H1 --> Y
Y --> Q[Visible in Run Detail<br/>expandable delivery panel]
style Z fill:#eee,stroke:#888
style Y fill:#efe,stroke:#393
Operator notes
- Actor: System; no human intervention on the happy path.
- Idempotency:
delivered_atis the guard — re-enqueuing is safe. - Mailtrap is always sandbox. Lifecycle emails never send to real users from an AI run. Promotion to production mail sending would be a separate feature gate.
- Slack host check is a security guard — the job refuses any webhook URL not under
hooks.slack.com. - Failure recovery:
delivery_status = failedsurfaces in Run Detail. Fix the underlying cause (missing token, repo permission, revoked webhook) and retry manually.
Process 4 — Autonomy Promotion Ladder
When and how an employee moves up the trust ladder.
stateDiagram-v2
[*] --> shadow: All new employees
shadow --> semi_autonomous: approval_rate > 80%<br/>AND weeks_active ≥ 4<br/>AND zero rejections in last 2 weeks
semi_autonomous --> autonomous: approval_rate > 95%<br/>AND weeks_active ≥ 8<br/>AND operator confirms modal<br/>(promotion_confirmed_at set)
autonomous --> semi_autonomous: Demote button
semi_autonomous --> shadow: Demote button
state shadow {
[*] --> All_artifacts_queue: Every artifact → Ops Board
}
state semi_autonomous {
[*] --> Low_risk_auto: Low-risk kinds auto-approve<br/>High-risk → queue
}
state autonomous {
[*] --> Direct_delivery: No review gate
}
note right of shadow
customer_support_drafter (Ally)
is permanently locked here
by model validation
end note
Operator notes
- Actor: Team lead (Josh today; delegated later). Not an ops-operator action.
- Cadence: Quarterly review cycle + ad-hoc when a thriving employee hits the metrics.
- Gate enforcement: It's a database validation (
promotion_requirements_met), not just a UI warning. A rawupdatefrom a rails console will still fail if criteria aren't met. - Autonomous tier requires a separate confirmation modal — this is intentional friction. Write a one-line justification in the commit when promoting.
- Demote freely. Demotion has no criteria check and costs nothing — if behavior regresses, step the employee down immediately.
- Ally (customer_support_drafter) is locked to shadow permanently by the model. Customer-facing copy is too high-risk for auto-approval.
Process 5 — Failure & Budget Circuit
What the system does — and what the operator does — when things break.
flowchart TD
subgraph Failures
A1[Agent Runner<br/>unreachable]
A2[error_max_turns /<br/>SDK error]
A3[HMAC signature<br/>mismatch]
A4[Monthly budget<br/>exceeded at trigger]
end
A1 --> B1[ExecuteRunJob<br/>circuit breaker]
B1 --> B2{Retries < 3?}
B2 -->|yes| B3[Exponential backoff]
B3 --> B1
B2 -->|no| B4[AiRun failed<br/>error = unreachable]
A2 --> C1[Agent Runner<br/>webhook fires]
C1 --> C2[run.status = failed<br/>run_log has trace]
A3 --> D1[Webhook controller<br/>returns 401]
D1 --> D2[Rails log: signature_invalid]
D2 --> D3[Run stays in running]
D3 --> D4[Operator inspects<br/>after 15 min SLA]
A4 --> E1[TriggerRun fails<br/>code: monthly_budget_exceeded]
E1 --> E2[Slack budget alert<br/>via SLACK_WEBHOOK_URL]
E2 --> E3{Operator action}
E3 -->|bump cap| E4[Edit monthly_budget_cents<br/>in Employee Detail]
E3 -->|wait for month reset| E5[Pause employee<br/>until month rollover]
E3 -->|investigate overspend| E6[Run Detail → input/output<br/>token breakdown]
B4 --> F[Operator inspects Run Detail]
C2 --> F
F --> G{Recoverable?}
G -->|yes| H[Re-trigger manually]
G -->|no| I[Pause employee<br/>open skill/config ticket]
style A1 fill:#fee,stroke:#c33
style A2 fill:#fee,stroke:#c33
style A3 fill:#fee,stroke:#c33
style A4 fill:#fee,stroke:#c33
style E2 fill:#ffd,stroke:#c80
Operator notes
- Agent Runner unreachable: Usually means Cloud Run cold start delay > client timeout, or the service is down. Check
/healthonAGENT_RUNNER_URL. The 3-retry circuit breaker with backoff gives it ~1 min of grace before failing the run. - HMAC mismatch: Almost always a secret-rotation gap between services. Verify
RAILS_WEBHOOK_SECRETmatches on both sides. Rotation = coordinated redeploy — both services in the same window, not sequential. - Budget exceeded: The
TriggerRuninteraction enforces the gate before dispatching. A rapidly-overspending employee almost certainly has skill prompts producing runaway tool calls — inspect the Run Detail tool-call timeline. - Ally special case: A failed run on the Ally employee is extra-sensitive; any failure pattern there warrants a same-day investigation because the role already can't auto-approve.
- Never bypass HMAC verification to "unblock" a run — it exists to prevent spoofed webhooks. Fix the secret instead.
Process 6 — Operator Cadence (Daily / Weekly / Monthly / Quarterly)
The recurring human rituals that keep the workforce healthy.
flowchart LR
subgraph Daily[Daily Ops ∼ 10 min]
D1[Ops Board sweep<br/>drain pending artifacts]
D2[Run Detail spot-check<br/>on any failed runs]
D3[Confirm no stuck runs<br/>more than 15 min]
end
subgraph Weekly[Weekly Lead ∼ 20 min]
W1[Approval-rate chart<br/>per employee]
W2[Memory hygiene<br/>review recent_rejections]
W3[Pause employees<br/>with 2+ rejects in week]
W4[Review Slack budget<br/>alerts history]
end
subgraph Monthly[Monthly Lead ∼ 30 min]
M1[Budget reconciliation<br/>actual vs cap per employee]
M2[Cost-per-approved-artifact<br/>ratio trend]
M3[Paused / stuck<br/>employees audit]
M4[Skill performance review<br/>approval-rate by skill]
end
subgraph Quarterly[Quarterly Lead ∼ 60 min]
Q1[Autonomy promotion<br/>review each employee]
Q2[Consider new employees<br/>from skill catalog]
Q3[Retire underperforming<br/>employees]
Q4[Brand-voice post-filter<br/>sampling audit]
end
D1 --> D2 --> D3
W1 --> W2 --> W3 --> W4
M1 --> M2 --> M3 --> M4
Q1 --> Q2 --> Q3 --> Q4
Daily -.feeds.-> Weekly
Weekly -.feeds.-> Monthly
Monthly -.feeds.-> Quarterly
Operator notes
- Daily is non-negotiable — the value prop is freshness. Artifacts going stale in the queue defeats the point.
- Weekly is the leverage point — most quality issues surface here before they become monthly budget problems.
- Monthly is financial hygiene — track trending, not just current month. A 15% MoM growth is fine; 40% warrants inspection.
- Quarterly is the strategic review — promotions, retirements, new employees. Pair with the roadmap review.
Cross-references
Every diagram node maps to concrete code. Use these when updating or validating the runbooks.
Scheduling & dispatch
rails_api/config/cronotab.rb:24—ScheduleRunsJobevery 5 minrails_api/app/jobs/ai_workforce/schedule_runs_job.rb:16— picks due employeesrails_api/app/interactions/ai_workforce/trigger_run.rb:12— budget gate, concurrency guardrails_api/app/jobs/ai_workforce/execute_run_job.rb:22— circuit breakerrails_api/app/services/ai/agent_runner_client.rb:20— POST /runs, OIDC or secret auth
Agent execution
agent_runner/src/routes/runs.ts:9— fire-and-forget ingress, 202 responseagent_runner/src/agent/runner.ts:33— query() loop, maxTurns, maxBudgetUsdagent_runner/src/agent/postFilter.ts— brand-voice second queryagent_runner/src/webhook/sender.ts:35— HMAC-signed callback, retry loop
Rails result processing
rails_api/app/controllers/webhooks/ai_workforce_controller.rb:7— HMACsecure_comparerails_api/app/interactions/ai_workforce/process_webhook_result.rb:11— artifact + memory upsert
Review + delivery
rails_api/app/interactions/ai_workforce/approve_artifact.rb:9— edit-distance trackingrails_api/app/interactions/ai_workforce/reject_artifact.rb:13— FIFO recent_rejections (cap 5)rails_api/app/jobs/ai_workforce/deliver_artifact_job.rb:19— kind-based routing,delivered_atidempotency
Autonomy
rails_api/app/models/ai_employee.rb:19—promotion_requirements_metvalidation, Ally shadow lock
Operator surfaces
admin_dashboard/src/views/OpsBoardView.vue— Live Ops Board landing (v4.8, OBJ-1562), four-column ticket board, 30s polladmin_dashboard/src/components/ops/FocusDetailOverlay.vue— ticket detail overlay: approve / edit / reject / hand-off / pause, diff2html + DOMPurify forcode_patchadmin_dashboard/src/views/AIWorkforceView.vue— secondary "Agents" route: employee grid, trigger/pause actions, 30s polladmin_dashboard/src/views/EmployeeDetailView.vue— config, memory, autonomy ladder, promotion modaladmin_dashboard/src/views/RunDetailView.vue— tool-call timeline, cost, artifacts, delivery metadata
Related operational docs
- AI Workforce (architecture) — system design, employees, skills, budget tiers
- Agent Runner Ops — deployment, scaling, troubleshooting
- AI Runbook — LiteLLM proxy, rate limits, kill switches
- Incident Response — general solo-operator recovery procedures
- Alerting — Slack budget alerts, Sentry rules
Last updated: 2026-07-20