OpenWalrusOpenWalrus

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
StatusMeaning
queuedWaiting for a concurrency slot or heartbeat pickup
in_progressCurrently executing
blockedPaused — waiting for user input or subtask results
finishedCompleted successfully
failedCompleted with an error or timed out

Concurrency control

The task registry limits how many tasks run simultaneously. Defaults are configurable in walrus.toml:

SettingDefaultDescription
max_concurrent4Maximum tasks in in_progress state
viewable_window16Maximum tasks returned by check_tasks
task_timeout300Per-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

On this page