Skip to main content
Use this when you want one accountable owner for a unit of work: a supervisor that watches it, may step in, and decides whether people steer it directly. A supervisor has a shell (what it owns, what it may send, whether people may steer through it) and an engine that decides. Prerequisites: a server on http://localhost:9858 and the steer session with workflow slow from Control a run. Creating supervisors and assignments needs an ADMIN key; add -H "X-API-Key: $YUKTA_API_KEY" to every curl if your server has keys.

Steps

1

Create the supervisor

A supervisor has an id (letters, digits, ., _, -, up to 64), an engine type (rules, http, workflow or process) and settings. This one uses the rules engine with no rules yet, so it reviews and allows. Save as release-guard.json:
release-guard.json
  • allowedCommands is what the supervisor itself may send. Name them, whatever the engine’s default is.
  • operatorAccess is what a person may send for what it owns (default none). A listed command is reviewed by the owner’s engine.
Check the draft without saving, then save:
Validation answers 200 with "valid": false and a settings.<key> field for an unknown key or wrong type. Saving answers 201; a second save of the same id with POST is 409, so use PUT /api/supervisors/{id} to replace it.
2

Say what it owns

An assignment targets one unit:Check first (it saves nothing), then set:
The check answers {"valid": true, "problems": []}. Setting replaces the assignments you made by hand, checks everything first and changes nothing if one check fails. CLI: yukta-cli supervisors save -f release-guard.json, yukta-cli supervisors assign release-guard workflow:steer/slow. MCP: save_supervisor, check_assignment, set_assignments.
3

Try the one-owner rule

Every unit has one owner. Save a second supervisor and give it the same workflow:
The save is refused with 409 and the code OWNERSHIP_CONFLICT, naming the other supervisor and the units in dispute (the message reads like <unit> already owned by release-guard):
Nothing is inherited and nothing is overridden. To give one node to a specialist, narrow the first supervisor’s assignment (for example to workflow:steer/slow//go) before assigning the node.
4

See what people may still do

With a run going (yukta-cli workflow start steer slow or the start call from the control guide), ask the server before you send:
The first lists each command with allowed, via (the carrying supervisor, or default) and reason. The second names the owner of the run level and of each node. Now send commands as a person:
5

Declare ownership in the workflow

A session or workflow can name its supervisors, so imports, templates and every saved version carry them. The supervisor must exist when the definition is saved, and the one-owner rule runs first.
A session-level assignments covers the whole session; a workflow-level one covers the workflow or only the listed nodes (ids, <prefix>.* or group:<name>). enabled: false declares and keeps it off. These assignments have source DEFINITION: saving the definition takes up what is declared and releases what is no longer declared, never touching hand-made ones. A supervisor a definition names cannot be deleted.
6

Lock it

"locked": true on an assignment means only a lock holder may change or remove it (any admin, or the keys in yukta.supervisor.lock-holders). To change it, add ?unlock=true:
Without unlock, the second call is 409.

Verify it worked

The list shows release-guard with target workflow:steer/slow and its source (MANUAL, DEFINITION or SYSTEM). The summary counts workflows nobody owns. Stopping the run as a person is refused with 409 CONTROLLED_BY_SUPERVISOR, pausing it works, and GET /api/control/audit records both.

Variations

  • Units nobody owns go to the default supervisor, which lets people act as before. Set yukta.supervisor.default.enabled=false in production so every workflow must name its owner; a person’s command for an unowned unit is then 409 CONTROLLED_BY_SUPERVISOR with no supervisor named.
  • Commands that need approval. A rule’s requireApproval parks a command and answers 202 with {"status":"AWAITING_APPROVAL","requestId":"..."}: Write a rules supervisor.
  • A veto is a 403 with code CONTROL_REJECTED and the rule’s reason.
  • Which engine? rules for exact cases, http for an agent or another service, workflow for a decision you edit as a workflow, process for a local program: Supervisor engines.
  • Delete. A supervisor can be deleted only when it owns nothing, no definition names it and no supervisor reports to it (409 otherwise).