Workflow tasks today often embed raw prompts, inline model hints, or duplicate AgentProfile fields. That violates the separation: Workflow owns WHAT ORDER; Fleet owns WHO; AgentProfile owns config.
{ role: "scout", prompt: "Investigate #4090 Ctrl+C path. Read-only." }
{ role: "implementer", prompt: "Fix #4090 with minimal diff." }
{ role: "reviewer", prompt: "Review diff for regressions." }
workflow.run({ fleet: "v0868-stopship", ... })
→ for each step: fleet.resolve(role) → AgentProfile
→ runtime.spawn(resolved_profile, ...)
Parent: #4175
Problem
Workflow tasks today often embed raw prompts, inline model hints, or duplicate AgentProfile fields. That violates the separation: Workflow owns WHAT ORDER; Fleet owns WHO; AgentProfile owns config.
Scope
Phase 2: workflow lowering resolves fleet roles at execution time.
Workflow step contract
Workflow steps declare a role (and optional task prompt), not a full AgentProfile:
At run time:
Fleet resolution
resolved_role,resolved_profile,resolved_provider,resolved_model,route_source.CLI entrypoint
Creates a Lane (#4176 Phase 1) and executes workflow steps through Fleet resolution.
Non-goals
Acceptance criteria
role:on task steps; rejects inline provider/model as required fields.workflow runrequires--fleet <name>(or configured default fleet).agent(profile:)launches (v0.9.0 remaining: make AgentProfile canonical for Fleet rosters #4111).TaskStartedevents include resolved role + profile + route (v0.9.0 remaining: Workflow automatic launch and unified activity UI #4110 checklist).workflows/v0868_stopship_lane.workflow.jsupdated to role-based steps (follow-up in v0.9.1: Stopship workflow as fleet-backed lane (dogfood #4090/#4093/#4094) #4178).Related