6.5 KiB
Why
agent-runtime (apex-agent-mvp, code-complete, unapplied) gives the runtime exactly one shape of work: a single flat goal driven by one Planner/Executor Observe-Think-Act-Observe loop until it succeeds, fails, or exceeds max_steps. Real device-automation usage is rarely one flat goal — it is a sequence of distinct sub-goals with control flow between them: open an app, send a message, wait for a reply to arrive, take a screenshot, then end; or run a locally-learned Skill (skill-learning-runtime, Milestone 7) instead of re-planning from scratch, only re-planning if the skill's assumptions don't hold. Nothing in the current runtime can express "do A, then B, then wait until C is true, then D," track where a multi-stage run is, or resume it if the process restarts mid-way. Workflow Runtime introduces Workflow as a first-class, persisted, resumable object composed of planner-derived steps, skill-invocation steps, wait-for-condition steps, and simple branch steps — sitting one layer above the existing single-goal loop, not replacing it.
What Changes
- Add a new
workflow/package defining aWorkflowDefinition(an ordered, possibly-branching list ofWorkflowSteps) as a discriminated union of four step kinds: a planned-goal step (delegates a sub-goal string to the existingagent-runtimePlanner/Executor loop), a skill-invocation step (resolves parameters and executes a locally-synthesizedFlowTemplateSkillfromskill-learning-runtime, Milestone 7), a wait-for-condition step (polls a named condition — e.g. scene text present, a world variable equals a value, elapsed time — up to a timeout), and a branch step (evaluates a condition and jumps to a named step id instead of falling through sequentially). - Add a
WorkflowRun— the persisted, mutable execution record for one execution of aWorkflowDefinition: status (pending/running/waiting/completed/failed/cancelled),current_step_id, workflow-scopedvariables, and a per-step result log — checkpointed to storage after every completed step so aWorkflowRunner.resume(run_id)can continue from the last checkpoint instead of re-running from step 0, without re-executing already-completed mutating steps. - Add a
WorkflowRunnerorchestration component that composes (imports, never subclasses or edits)runtime/task.py's existingTaskRunnerfor planned-goal steps, and drives skill-invocation/wait/branch steps itself. - Add a first, minimal skill-invocation execution path (
workflow/skill_exec.py): resolve aFlowTemplateSkill's declared parameters against a step's supplied argument values, validate against the skill's parameter schema, and drive the resolved tool calls throughtools/— the "some future runner resolves parameters and drivestools/" gapskill-learning-runtimeexplicitly left open. - Add a
ConditionEvaluatorport + registry (workflow/conditions.py) for wait/branch conditions, mirroring the Driver Registry /PerceptionProviderextension-point pattern already established bydevice-agent-runtime-foundation, with a small starting set of condition kinds (scene_contains_text,world_variable_equals,elapsed_seconds,step_result_success). - Add a new, independently-owned SQLite-backed
WorkflowStore(workflow/store.py) forWorkflowDefinition/WorkflowRunpersistence, following the same connect-per-callsqlite3pattern asstorage/task_metadata.pybut in its own database file — not a schema change tostorage/, which remains owned by the pendingtask-memorycapability. - No changes to
runtime/task.py,runtime/planner.py,runtime/executor.py,runtime/context.py,storage/*,tools/*, or any other existing module's public behavior — this change is purely additive composition on top of them.
Capabilities
New Capabilities
workflow-orchestration: AWorkflowmodel (planned-goal / skill-invocation / wait-for-condition / branch step kinds), executed by aWorkflowRunnerthat composes the existing single-goal Planner/Executor loop and the not-yet-built skill-execution path, persisted via a task-memory-style store, and resumable from its last checkpoint if interrupted mid-workflow.
Modified Capabilities
(none — openspec/specs/ has no applied baseline for agent-runtime, task-memory, skill-authoring, or skill-embedding-retrieval yet, so this change cannot and does not write a MODIFIED Requirements delta against any of them; it composes with their pending, unapplied designs in prose only, and does not alter their specified behavior.)
Impact
- New package:
workflow/—models.py(WorkflowDefinition,WorkflowStepvariants,WorkflowRun,WorkflowStepResult),runner.py(WorkflowRunner),conditions.py(ConditionEvaluatorport + registry),skill_exec.py(parameter resolution + tool dispatch for skill-invocation steps),store.py(WorkflowStore, SQLite-backed),config.py(enable flags, default poll interval, default wait timeout). - New storage: a new
workflows/workflows.sqlite3database file (own schema:workflow_definitions,workflow_runs,workflow_step_resultstables), independent ofstorage/task_metadata.py'stasks/tasks.sqlite3. - Composed, not modified, dependencies:
runtime/task.py'sTaskRunner(planned-goal steps construct aTaskand callTaskRunner(...).run(task), reading backtask.status/task.failure_reason),skill-learning-runtime'sFlowTemplateSkill/Skilldataclass shape (imported, not redefined, matching that change's own D6 precedent for composing withskill-catalog-subscription), and optionallyworld-model-runtime'sWorldState.variables(read-only, forworld_variable_equalsconditions — degrades to "condition never satisfied until timeout" ifWorldStateis absent, never raises). - Config: add
workflow*topyproject.toml's[tool.setuptools.packages.find].includelist; no new third-party dependency beyond the standard librarysqlite3already used bystorage/task_metadata.py. - Out of scope: no visual workflow editor/UI (a future
web-consoleconcern, not touched here); no distributed/multi-device workflow execution (Milestone 10, Cloud Runtime); does not replace or remove the existing single-goal Planner/Executor loop, which remains the right tool for simple one-shot tasks; no generic expression/scripting language for branch conditions (a closed, registrable set of condition kinds only); no changes toskill-catalog-subscription,web-console, or any other pending change's files.