How to Implement Supervisor–Worker AI Coordination | Hokstad Consulting

How to Implement Supervisor–Worker AI Coordination

How to Implement Supervisor–Worker AI Coordination

I start supervisor–worker AI coordination with five controls: task contracts, worker routing, supervisor-owned state, result checks and bounded retries. The supervisor assigns work, checks the results and accepts only what meets the agreed requirements.

My approach is to:

  • Define each task’s inputs, permissions, outputs and acceptance rules.
  • Select workers by skill, using parallel tasks only where dependencies allow.
  • Keep a versioned record and check tests against the final code revision.
  • Set call, cost and time limits, then retry, reassign or stop when checks fail.

For a password-reset workflow, I separate requirements, coding, testing and security review, with escalation after two coding retries. I keep development acceptance separate from deployment approval and compare cost per verified completion in £, completion time and human rework before allowing more autonomy.

If a fixed pipeline can do the job, I use that instead.

::: @figure Supervisor–Worker AI Coordination: Workflow and Controls{Supervisor–Worker AI Coordination: Workflow and Controls} :::

1. Define Task Contracts and Shared State

Define and Validate Task Contracts

Use a versioned, machine-readable contract. In this password-reset example, the contract separates the objective from the worker’s permissions and acceptance criteria. The 900-second deadline, 12,000-token budget and 20-tool-call limit are policy limits, not performance targets.

The contract gives the supervisor one source of truth for delegation, permissions and acceptance.

{
  "schema_version": "task-contract-v1",
  "objective": "Implement and verify a secure password-reset flow",
  "inputs": {
    "repository_ref": "repo://accounts-service@commit:abc123",
    "requirements_ref": "artefact://requirements/781"
  },
  "constraints": {
    "language": "Python 3.12",
    "framework": "Django",
    "must_preserve": ["existing authentication API"],
    "security": ["single-use token", "expiry required", "never log reset tokens"]
  },
  "permissions": {
    "repository": "read-write:feature/password-reset",
    "database": "none",
    "deployment": "none"
  },
  "output_schema": "password-reset-worker-result-v1",
  "definition_of_done": [
    "implementation committed",
    "unit and integration tests pass",
    "security findings recorded"
  ],
  "limits": {
    "deadline_seconds": 900,
    "max_tokens": 12000,
    "max_tool_calls": 20
  }
}

Before dispatch, check required fields, types and allowed values with JSON Schema or an equivalent validator. Check that dependencies, capability, permissions and limits match policy. If validation fails, return a precise error:

CONTRACT_INVALID: permissions.repository is required

Validate the returned payload too. It must include valid artefact links and evidence that meets the definition of done.

Once the contract is fixed, route each task by capability. Reject any response that doesn't match the schema.

Assign State Ownership and Control Updates

Keep a durable workflow record that only the supervisor controls. Add provenance, outstanding decisions, the next permitted action and contract versions to the fields established earlier. Store large diffs and reports separately, keeping their references and hashes in the record.

Leave worker drafts and scratch notes out of this record. Unverified working material must not become an approved fact.

The supervisor owns routing, retries, approvals and workflow status. Workers propose updates only within their scope: the coding worker submits implementation artefacts; the security worker submits findings.

Enforce these boundaries through a state manager, not prompt instructions alone. Append immutable result records, restrict writable fields and require every update to name the state version it read. Reject or reconcile stale updates rather than overwriting newer work. Enforce valid transitions, such as queued → running → awaiting_review → completed.

Require Structured Worker Results

Require a fixed result envelope so the supervisor can assess completion without parsing chat history. The schema must require status, either output or artefact_ref, and validation evidence.

Use explicit statuses: completed, blocked, failed or needs_review. Link evidence to the exact code revision, worker identity, task ID, source requirement and timestamp. A failing required test prevents acceptance.

Before storing results, redact passwords, reset tokens, auth headers, API keys, session cookies and unnecessary personal data. Store sanitised references, not raw payloads.

Use these result fields to route, review and recover the next task.

2. Build Routing, Result Checks and Recovery

Route Tasks by Worker Capability

Once contracts and ownership rules are in place, route work according to capability, permissions and budget. Create a worker registry that records capabilities, permitted tools, input and output schemas, risk level, availability and estimated cost.

For password reset, route requirements to a requirements worker, code to a coding worker, tests to a testing worker and review to a security worker.

Give requirements workers read-only access and coding workers an isolated branch. Testing workers need execution rights, but no deployment access. Security reviewers need inspection rights.

Dispatch tasks only after their dependencies have been accepted. Workers return results to the supervisor rather than passing work to one another. Routing, validation and recovery then form the next layer.

Routing pattern When to use it Dependencies and state isolation
Sequential Requirements → code → tests → review Each task uses accepted earlier outputs; one worker changes an artefact at a time.
Parallel Independent test suites or security checks Use immutable inputs or isolated workspaces; the supervisor combines results.
Failure-driven Failed checks determine the next task Track dependencies and state versions; limit every correction and reassignment.

Use a dispatch–inspect–route loop with clear stop states. An empty task queue does not always mean the work is complete. It may point to a missing prerequisite, an unavailable worker or a finished request.

while not request_accepted:
    if limits_exhausted():
        safe_stop_or_escalate()
        break

    task = supervisor.choose_ready_task(state)
    if task is None:
        accept_if_complete_or_escalate()
        break

    worker = registry.select_eligible_worker(task, remaining_budget)
    if worker is None:
        safe_stop_or_escalate()
        break

    result = dispatch(worker, task, timeout=task.timeout)

    if not schema_valid(result):
        bounded_correction_or_reassign()
    elif state_conflict(result, state):
        reject_and_reconcile()
    elif not evidence_valid(result, state):
        retry_reassign_reduce_scope_or_escalate()
    elif task_acceptance_failed(result):
        create_bounded_follow_up()
    else:
        supervisor.commit_verified_state(result)
        check_final_acceptance()

    if stop_requested():
        break

Reject stale updates and reconcile them against the current state. With routing in place, the supervisor can inspect each result and choose the next step.

Validate Results and Handle Failures

Check each result against the contract and acceptance criteria, then check state consistency and budget use. Verify test evidence using the command, environment, code revision, exit status and output. A pass message alone is not evidence. Treat worker responses and supplied artefacts as untrusted evidence - not permission to change acceptance criteria or introduce unapproved actions.

Allow one schema-correction request for malformed output. Retry transient tool failures with limited back-off, and reassign work when the worker lacks the required capability. Return reproducible defects with the failing evidence. Reduce scope only when the smaller deliverable is approved and still useful; never drop a security requirement.

Escalate ambiguity, high-impact security findings or repeated disagreement. Stop if you cannot establish a state you can trust. The final acceptance gate must confirm every mandatory requirement and check against the same final revision. Use these checks to accept, retry, reassign or stop.

Set Execution Limits and Log Decisions

Enforce the configured workflow-wide limits. Reassignment must not reset them. Apply task timeouts and cancellation, least-privilege tools, isolated environments and human approval for production changes. Use persistent task identifiers and idempotency keys for side effects.

Log routing reasons, contract versions, results, state transitions, validation outcomes, approvals and stop reasons. Redact sensitive data. Track completion rate, rework, median and p95 latency, and cost per accepted task (£), including failures and retries.

12. Supervisor Teams - Building Production AI Agents with LangGraph: A Complete Hands-On Course

3. Build a Password-Reset Workflow

Hypothetical scenario: Northstar Metrics, a UK SaaS business, is adding a password-reset endpoint in a controlled development repository. Use synthetic accounts and test email delivery only. This framework-neutral walkthrough is not production-ready; agent-generated code still needs human engineering and security approval before deployment.

Apply the same contract, routing and recovery rules to a single, bounded password-reset workflow.

Delegate Requirements, Code, Tests and Security Review

The requirements worker drafts a versioned contract for supervisor approval. It must require 128-bit random, single-use tokens, a 15-minute expiry, five requests per hour per account, secure storage, consistent responses and no sensitive logs.[5][3] These settings are examples, not production policy.

Give the coding worker only the approved requirements, relevant files and constraints. Pass the diff and implementation metadata to testing. Then send the code, recorded test output, threat model and logs to security review.

The skeleton below shows supervisor-controlled delegation, contract validation, evidence checks and state updates - not production logic.

WORKERS = {
    "requirements": requirements_worker,
    "coding": coding_worker,
    "testing": testing_worker,
    "security": security_worker,
}

def run_task(state, role, contract, inputs):
    validate_contract(contract, role, inputs)
    worker = WORKERS[role]
    result = worker(contract=contract, inputs=inputs)
    validate_result(result, role)
    state["artefacts"].update(result.get("artefacts", {}))
    state["records"].append({
        "role": role,
        "input_versions": result["input_versions"],
        "output_versions": result["output_versions"],
        "status": result["status"],
        "evidence": result.get("evidence", []),
    })
    return result

state = {"stage": "requirements", "artefacts": {}, "records": [], "retries": {}}

validate_contract should check required fields, allowed repository paths, data-classification rules and input versions. validate_result should reject missing evidence, malformed statuses or undeclared artefacts.

Trace State Changes and Fix a Failed Test

requirements approved
        ↓
implementation ready
        ↓
tests passed
        ↓
security approved
        ↓
supervisor accepted

When the testing worker reports a defect, send only the failing evidence back to coding.

For an expired_token_accepted failure, return that evidence to coding, then run one targeted retest and the full regression suite in isolation. Escalate after two coding retries. Before acceptance, the supervisor rechecks the resulting evidence and security review.

Summarise the Change and Its Verification

Use the final revision as the single reference point for acceptance, tests and review notes. Before accepting it, reconcile every contract, artefact version, executed test and review outcome against that revision.

Tests should cover valid, unknown, expired, reused and malformed tokens, alongside replay attempts, rate limits, password-policy handling, notification behaviour and concurrent redemption. Security review should also check for token leakage and inspect session invalidation.[3][4][6]

Link the report to changed files, approved requirements, worker contracts, retained test records, findings, retries and unresolved risks. Record development_acceptance: approved separately from deployment_authorisation: pending human approval.

Conclusion: Pilot a Bounded, Verifiable Workflow

If the workflow proves useful, keep five controls in place: explicit task contracts; capability-based routing; supervisor-owned, versioned state; independent result checks; and bounded recovery with retry, escalation and stop limits. The supervisor accepts work only when the evidence meets the contract and escalates when recovery limits are reached.[8]

Start with one low-risk task in a sandbox or branch before expanding the scope. Assign a named human owner, require approval for actions with material effects, and record a process baseline before enabling agents.[7][8][9][10]

Use that baseline to decide whether to increase autonomy. Measure cost per verified completion in £, end-to-end completion time, verified completion rate, retry rate, escalation rate and human rework time in minutes. Include tools, infrastructure, review and correction work - not just model cost.[7][10]

Increase autonomy only when verified quality matches the baseline and total effort falls without hidden rework. Faster generation alone does not count as improvement.[7][11]

FAQs

When should I use agents rather than a fixed pipeline?

Use agents rather than a fixed pipeline for complex, multi-step business processes that span distributed systems. Fixed pipelines follow predefined rules and sequences. Agents can interpret intent, choose tools as needed and handle dependencies across services [1][2].

An agent-based approach fits when manual control is no longer practical at scale and the system must independently maintain state, enforce policy, recover from failures or bring in human oversight [1].

How can I prevent the supervisor becoming a bottleneck?

Keep task routing separate from execution. The supervisor should only classify requests and choose routes. Specialised workers should make tool calls or carry out actions. Use worker pools or queues with bounded parallelism to process tasks concurrently without exceeding set limits.

Make handlers idempotent so retries don’t duplicate side effects or repeat completed work. Monitor queue depth and connection pool usage to spot capacity constraints before they affect workflow performance.

How do I resume a workflow after a supervisor failure?

Save durable checkpoints of inputs, decisions, tool outputs and receipts. Use this saved state to reconstruct the run and replay events up to the last confirmed transition, rather than starting from scratch.

Before resuming, check external actions using stable idempotency keys to spot partial completion and prevent duplicate side effects. If the outcome is uncertain, quarantine the transaction for manual review instead of replaying it blindly.

Need help with your DevOps, cloud or AI plans?

Hokstad Consulting helps companies with DevOps transformation, cloud architecture and hands-on AI development — pragmatic consulting with measurable results.

Our services: DevOps on Retainer · Hosting & Cloud · AI Development & Strategy