Workflow Orchestration¶
Kohakku uses Temporal for durable workflow execution. Single-shot tasks do not need workflows -- use them when you need sequencing, fan-out, human gates, or durable execution.
Workflow Patterns¶
| Pattern | Description |
|---|---|
| Single Dispatch | One task, wait for completion |
| Chained | Sequential tasks, each gets prior result as context |
| Fan-Out | N tasks in parallel, optional aggregation |
| Supervisor/Worker | Supervisor dispatches sub-agents via signals |
| Review Loop | Worker -> reviewer -> iterate until pass |
| Advisor | Long-lived child workflow that wakes on signals |
Pre-built Templates¶
Seed with manage.py seed_workflow_templates:
- Coding Sprint -- plan -> fan-out impl -> review -> gate -> test -> merge
- Coding Waterfall -- requirements -> design -> gate -> impl -> test -> gate -> deploy
- Swarm Spike -- brief -> fan-out spike -> aggregate -> judge -> gate -> polish
- Code Review Loop -- impl -> review -> decision gate -> test -> merge
- Bug Fix -- investigate -> gate -> fix -> test -> review -> gate -> PR
Launching a Workflow¶
- Navigate to Workflows -> select template -> Launch
- Provide input context (JSON or text)
- Monitor progress on the instance detail page
- Approve/reject at human gates
Temporal Integration¶
Determinism Rules¶
Workflow code must be deterministic. No ORM calls, HTTP requests, or random numbers directly in workflow functions. All side effects go through activities.
# Wrong -- non-deterministic
task = Task.objects.get(guid=task_guid)
# Right -- side effect in an activity
result = await workflow.execute_activity(
get_task_activity,
task_guid,
start_to_close_timeout=timedelta(seconds=30),
)
Activities¶
Activities bridge workflows to Django and the dispatch pipeline:
| Activity | Purpose |
|---|---|
dispatch_task_activity |
Assembles brief, dispatches to Dispatcher |
get_task_status_activity |
Reads task state from DB |
update_workflow_status_activity |
Updates WorkflowInstance state |
send_signal_activity |
Sends signals to other workflows |
Activities use run_in_executor to bridge synchronous Django ORM operations into async Temporal activities.
Signals¶
Task callbacks trigger Temporal signals. Human gates wait for operator signals.
@workflow.signal
async def task_completed(self, result: dict):
self.task_result = result
self.task_done = True
Worker Process¶
The Temporal worker runs separately from Django:
Scale workers independently of Controller instances.
Human Gates¶
Insert a human gate between workflow stages:
- Workflow reaches a gate stage
- Workflow pauses (
wait_condition) - Operator reviews in the Controller UI
- Operator sends an approve/reject signal
- Workflow continues or aborts
Workflow Templates¶
WorkflowTemplate records define reusable patterns:
| Field | Description |
|---|---|
category |
single, chained, fanout, supervisor, review, advisor |
default_config |
JSON config applied to all instances |
is_published |
Whether the template is available for use |
Each template has ordered WorkflowStage records:
| Field | Description |
|---|---|
order |
Execution order |
stage_type |
dispatch, gate, aggregate, review |
agent_definition |
Which agent to use |
skills / configs |
M2M relations |
on_failure |
fail, retry, skip |
Reference Flows¶
See flows.md in the repo root for 13 reference flows demonstrating these patterns:
| Pattern | Flows |
|---|---|
| Single agentic loop | 1, 3, 7 |
| Fan-out / parallel | 2 |
| Sequential / chained | 5, 6 |
| Event-driven | 3, 6, 7 |
| Human gate | 5 |
| Human-in-the-loop (mid-task) | 8 |
| Dark factory (autonomous) | 9 |
| Supervisor / worker | 10 |
| Review / critique loop | 11 |
| Competitive dispatch | 12 |
| Agent-spawns-agent | 13 |