Skip to content

Handbook

The handbook is a tenant-scoped compiled rulebook. Operators ingest Markdown sources, compile a versioned snapshot, and query it. Open conflicts are never resolved silently: a matching topic forces human approval.

Prompt Guard scans handbook text before it is stored. Query uses keyword overlap over the compiled snapshot (not embeddings).

Who can use it

Role Read / query Compile / delete source Resolve conflict
Viewer — — —
Security Analyst ✔ — —
Developer ✔ ✔ ✔
Admin ✔ ✔ ✔
Super Admin ✔ ✔ ✔

The Handbook item is in the Operate sidebar group (/handbook).

Sources

POST /api/v1/handbook/sources accepts one of:

kind Payload
paste raw_text (required), optional uri
markdown_dir uri path the API can read
archive uri or raw_text (base64 zip)

Compile with POST /api/v1/handbook/compile. The response includes version, entry_count, conflict_count, rendered markdown, and conflicts.

Delete a source with DELETE /api/v1/handbook/sources/{source_id} (compile permission). If a snapshot already exists, the delete is written to the audit log as handbook.compile.

Query

curl -X POST http://localhost:8001/api/v1/handbook/query \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"q":"refund limit"}'

The SPA session uses the HttpOnly cookie (credentials: include). A tenant X-API-Key is still valid for API clients.

The result includes handbook_version, ranked hits, and any open_conflicts on the matched topics.

Conflicts and HITL

POST /api/v1/handbook/conflicts/{conflict_id}/resolve body:

{ "resolution_entry_id": "<entry-uuid>" }

On POST /api/v1/policies/check and workflow steps, an open conflict is attached to the decision:

  • allow becomes false
  • required_approval becomes true
  • reason starts with UNRESOLVED CONFLICT on <topic>/<id>
  • Approving the HITL request does not clear that conflict

For action=workflow.step (default HANDBOOK_WORKFLOW_FAIL_CLOSED=true), any open conflict in the compiled snapshot pauses the step, even if the prompt topic did not match. Chat / Try Prompt still use topic match unless the same flag is set.

Gates apply only when the agent is invoked through this control plane (workflow.step, webhook/cron into the executor, or /agents/{id}/chat). A client that ignores allowed: false and calls the model itself bypasses the stop.

Resolve the conflict in Handbook, then re-run. After resolve, stale handbook HITL expires and resume evaluates overlay again (hitl_approved=false).

Compile and resolve are audited as handbook.compile and handbook.resolve. Filter them on Audit with ?action=handbook.compile or ?action=handbook.resolve.

Try Prompt

On an agent page, Try Prompt shows the handbook version used for the check. If the prompt hits an open conflict, the result links to /handbook?focus=conflicts.

Eval fixture

POST /api/v1/handbook/eval?fixture=studio_north&mode=compiler runs the bundled compiler fixture (also mode=runtime). This is a regression check, not tenant data. Missing fixtures return 404.