Tasks
Multi-agent delegation — spawn async tasks, await results, and coordinate parallel workloads with concurrency control.
The task system enables agents to delegate work to other agents, run workloads in parallel, and coordinate results. It's the mechanism behind multi-agent collaboration in OpenWalrus.
Task lifecycle
Every task follows this state machine:
Queued ──→ InProgress ──→ Finished
│
├──→ Blocked ──→ InProgress
│
└──→ Failed| Status | Meaning |
|---|---|
queued | Waiting for a concurrency slot or heartbeat pickup |
in_progress | Currently executing |
blocked | Paused — waiting for user input or subtask results |
finished | Completed successfully |
failed | Completed with an error or timed out |
Concurrency control
The task registry limits how many tasks run simultaneously. Defaults are configurable in walrus.toml:
| Setting | Default | Description |
|---|---|---|
max_concurrent | 4 | Maximum tasks in in_progress state |
viewable_window | 16 | Maximum tasks returned by check_tasks |
task_timeout | 300 | Per-task timeout in seconds |
When a task finishes or fails, the next queued task is automatically promoted.
Tools
The task system registers five tools via the hook system:
spawn_task
Delegate an async task to another agent. Returns immediately with a task_id and status (in_progress or queued).
{
"name": "spawn_task",
"parameters": {
"agent": "researcher",
"message": "Find the top 5 Rust HTTP frameworks by GitHub stars"
}
}The target agent must be in the calling agent's members list. See delegation scope below.
check_tasks
Query the task registry with optional filters:
{
"name": "check_tasks",
"parameters": {
"status": "finished",
"agent": "researcher"
}
}Returns up to viewable_window (default 16) tasks with full details including token usage.
create_task
Queue a task for later pickup by the agent's heartbeat. Unlike spawn_task, this doesn't dispatch immediately.
{
"name": "create_task",
"parameters": {
"agent": "coder",
"description": "Implement the login form component"
}
}ask_user
Pause the current task and ask the user a question. The task becomes blocked until the user responds via the client.
{
"name": "ask_user",
"parameters": {
"question": "Should I use JWT or session-based auth?"
}
}Only works within a task context. Calling ask_user outside a task returns an error.
await_tasks
Block until all specified tasks reach finished or failed. The calling task is set to blocked while waiting.
{
"name": "await_tasks",
"parameters": {
"task_ids": [1, 2, 3]
}
}Returns the collected results for each task once all have completed.
Delegation scope
Agents can only delegate to agents listed in their members config:
---
members: ["researcher", "coder"]
---An empty members list means the agent cannot delegate at all — task tools won't be available. When members is set, the task tools are automatically added to the agent's tool whitelist.
Parent-child hierarchy
Tasks form a tree. When agent A spawns a task for agent B, the child task's parent_id points to A's task. You can query subtasks with check_tasks:
{
"name": "check_tasks",
"parameters": { "parent_id": 1 }
}Token tracking
Each task accumulates prompt_tokens and completion_tokens from every LLM call made during its execution. Use check_tasks to inspect token usage per task.
Heartbeat integration
Agents with a configured heartbeat interval periodically wake up. On each heartbeat tick, the daemon gathers any queued create_task entries for that agent and dispatches them as a batch message. This enables asynchronous task scheduling — other agents (or users) can queue work for an agent, and the agent picks it up on its next heartbeat.
See agent configuration for heartbeat setup.
What's next
- Agents — configuring delegation with
members, heartbeat - Permissions — controlling task tool access with
ask/deny - Event loop — how task events flow through the daemon