Task Lifecycle
From vision submission to task completion — the full lifecycle of work in Starweft.
Lifecycle Overview
The lifecycle of a task in Starweft begins with a Principal submitting a vision, followed by the Owner decomposing it into tasks, Workers executing them, and evaluation leading to completion.
Principal Owner Worker
│ │ │
│ vision submit │ │
├─────────────────▶│ │
│ │ plan & charter │
│◀─────────────────┤ │
│ │ discover peers │
│ ├───────────────────▶│
│ │◀───────────────────┤
│ │ join offer/accept │
│ ├───────────────────▶│
│ │◀───────────────────┤
│ │ delegate task │
│ ├───────────────────▶│
│ │ progress │
│ │◀───────────────────┤
│ │ result submit │
│ │◀───────────────────┤
│ │ evaluation issued │
│ ├───────────────────▶│
│ │ │From Vision to Charter
The Principal runs starweft vision submit to send a VisionIntent message to the Owner.
starweft vision submit --title "Implement search functionality" \
--text "Implement full-text search using Elasticsearch" \
--owner <owner-actor-id>A VisionIntent contains the following:
- title: A short title
- raw_vision_text: Free-form goal description text
- constraints: Execution constraints (budget_mode, allow_external_agents, human_intervention)
When the Owner receives a VisionIntent, it automatically generates a ProjectCharter.
- Issues a
project_idas a ULID - Sets the 4-dimensional weights (quality, speed, reliability, alignment) in
evaluation_policy - Determines whether external agents may participate via
participant_policy - Sets the stop authority (typically the Principal) in
stop_authority_actor_id
The Owner decomposes the vision into tasks. It generates a list of PlannedTaskSpec entries according to the planning strategy in use.
Each task is configured with the following:
- title / description / objective: The task definition
- required_capability: The capability required for execution (e.g.,
"openclaw.execution.v1") - input_payload: Input data for the Worker (JSON)
- expected_output_schema: JSON Schema describing the expected output
JoinOffer / Accept Flow
Before the Owner delegates a task to a Worker, it verifies capabilities and establishes participation agreement.
Owner Worker
│ │
│──CapabilityQuery────────────────▶│
│◀─CapabilityAdvertisement────────│
│ │
│ (verify capabilities) │
│ │
│──JoinOffer──────────────────────▶│
│ required_capabilities │
│ task_outline │
│ expected_duration_sec │
│ │
│◀─JoinAccept─────────────────────│
│ capabilities_confirmed │
│ │Conditions for a Worker to accept a JoinOffer:
accept_join_offers = truemust be set- The current number of active tasks must be below
max_active_tasks - The Worker must possess the requested capabilities
Task Execution
Sending TaskDelegated
After receiving a JoinAccept, the Owner delegates the specific task to the Worker via a TaskDelegated message.
{
"parent_task_id": null,
"title": "Build search index",
"description": "Design and build the Elasticsearch index",
"objective": "Design an index to enable full-text search",
"required_capability": "openclaw.execution.v1",
"input_payload": { "target": "search_index" },
"expected_output_schema": { "type": "object" }
}Task Status Transitions
A task transitions through the following statuses.
queued ──▶ offered ──▶ accepted ──▶ running ──▶ submitted ──▶ completed
│ │ │
│ ▼ │
│ stopping ──▶ stopped │
│ │
└──────────────────────────────────────────────────────────▶ failed| Status | Description |
|---|---|
queued | The task is in the queue, waiting for a Worker to be assigned |
offered | A JoinOffer has been sent to a Worker |
accepted | The Worker has returned a JoinAccept |
running | The task is being executed via the OpenClaw bridge |
submitted | The Worker has submitted results and is awaiting evaluation |
completed | The task has completed successfully |
failed | Task execution has failed |
stopping | A StopOrder has been received and stop processing is in progress |
stopped | The stop has been completed |
Execution via OpenClaw Bridge
The Worker launches the OpenClaw binary as a subprocess to execute the task.
Task information is written in JSON format to OpenClaw's stdin.
{
"title": "Build search index",
"description": "...",
"objective": "...",
"required_capability": "openclaw.execution.v1",
"input_payload": { "target": "search_index" }
}Lines matching the format PROGRESS:<float>:<message> are detected from stdout, and TaskProgress messages are sent to the Owner.
PROGRESS:0.3:Analyzing data schema
PROGRESS:0.6:Generating index mapping
PROGRESS:0.9:Validating index with test dataAfter the process completes, the final JSON output from stdout is parsed as a BridgeTaskResponse.
{
"summary": "Search index has been built",
"output_payload": { "index_name": "search_v1" },
"artifact_refs": []
}If the openclaw.timeout_sec (default: 3600 seconds) is exceeded, the process is forcibly terminated and reported as Failed.
Progress Reporting
The Worker reports progress of running tasks to the Owner via TaskProgress messages.
pub struct TaskProgress {
pub progress: f32, // 0.0 to 1.0
pub message: String, // Progress message
pub updated_at: OffsetDateTime,
}On the Owner side, the projection (tasks table) is updated, and current status can be viewed in real time using the starweft status command.
Result Submission and Evaluation
TaskResultSubmitted
When task execution is complete, the Worker sends a TaskResultSubmitted to the Owner.
pub enum TaskExecutionStatus {
Completed, // Completed successfully
Failed, // Execution failed
Stopped, // Interrupted by a stop order
}Results can include artifact references.
pub struct ArtifactRef {
pub artifact_id: ArtifactId,
pub scheme: String, // "file"
pub uri: String, // File path
pub sha256: Option<String>,
pub size: Option<u64>,
pub encryption: Option<ArtifactEncryption>,
}EvaluationIssued
The Owner evaluates the task result and issues an EvaluationIssued. The evaluation consists of scores across 4 dimensions.
| Dimension | Description |
|---|---|
| quality | Quality of the output |
| speed | Execution speed |
| reliability | Reliability and stability |
| alignment | Alignment with the stated goal |
{
"subject_actor_id": "<worker-actor-id>",
"scores": {
"quality": 0.85,
"speed": 0.70,
"reliability": 0.90,
"alignment": 0.95
},
"comment": "High-quality implementation. Room for performance improvement."
}Stop / Cancel Flow
Task stopping via StopOrder is performed safely through a 3-phase handshake.
Principal Owner Worker
│ │ │
│──StopOrder───────▶│ │
│ │──StopOrder───────▶│
│ │ │ cancel_flag = true
│ │ │ Stop OpenClaw process
│ │◀─StopAck─────────│
│◀─StopAck──────────│ │
│ │◀─StopComplete────│
│◀─StopComplete─────│ │
│ │ │The Principal runs the starweft stop command. A StopOrder specifies a scope_type (Project / TaskTree) and scope_id.
starweft stop --project <project-id> --reason "Change in direction"When the Owner receives a StopOrder, it changes the target project's status to stopping and forwards the StopOrder to all associated Workers.
The Worker performs the following:
- Sets the cancel_flag (
AtomicBool) for the target task totrue - Waits for the OpenClaw subprocess to terminate
- Sends a StopAck (ack_state:
"stopping") to the Owner - Once all target tasks have stopped, sends a StopComplete (final_state:
"stopped")
The Owner relays StopAck / StopComplete messages from Workers to the Principal. The project status transitions to stopped, and the lifecycle ends.
Retry Strategy
When a task fails, the Owner performs rule-based retry determination.
Determination Flow
TaskResultSubmitted (status = Failed)
│
▼
Rule matching (pattern matching on summary text)
│
├── "timeout" / "timed out"
│ → Retry on the same Worker
│
├── "process failed" / "worker overloaded" / "worker unavailable"
│ → Retry on a different Worker
│
├── "capability mismatch" / "invalid input" / "schema" / "unauthorized"
│ → Do not retry (permanent failure)
│
└── No pattern match
→ Retry on a different Worker (default)Retry Configuration
[owner]
max_retry_attempts = 8 # Maximum number of retries
retry_cooldown_ms = 250 # Retry interval
retry_strategy = "rule_based"
[[owner.retry_rules]]
pattern = "timeout"
action = "retry_same_worker"
reason = "transient timeout"
[[owner.retry_rules]]
pattern = "capability mismatch"
action = "no_retry"
reason = "permanent task/input failure"During a retry, the Owner copies the blueprint (original task definition) of the failed task and creates a new task with parent_task_id set to the original task's ID.
Project Status
The overall project status transitions through the following states.
planning ──▶ active ──▶ stopping ──▶ stopped| Status | Condition |
|---|---|
| planning | Immediately after ProjectCharter generation. No tasks have started yet |
| active | Tasks are in execution |
| stopping | A StopOrder has been issued and tasks are being stopped |
| stopped | All tasks have stopped and the project has ended |