9.9 KiB
| name | description |
|---|---|
| orchestrate-agent-task-loop | Execute dependency-ready PLAN and CODE_REVIEW task loops with workspace write claims, a runtime-injected agent/model catalog, deterministic target failover, and persistent recovery state. |
Orchestrate Agent Task Loop
Final-channel gate
Do not end the caller turn through final until either:
- every in-scope task has a verified archived
complete.log, every generated work log is archived, no task or execution remains active, and the dispatcher exits0; or - the user explicitly asks to stop the current run.
Use commentary for non-terminal status, blockers, questions, recovery notices, and partial completion. If the user asked for a persistent run, successful completion alone does not release this gate.
Purpose
Monitor the file-backed workflow under agent-task/ and converge ready PLAN implementation, optional self-check, official review, follow-up PLAN, and archive completion. The dispatcher owns deterministic scheduling, recovery, target transitions, and runtime evidence. Child agents own implementation and review judgments within their assigned artifact.
Inputs
workspace: trusted repository root containingagent-task/; defaults to the current directory.execution_catalog: required runtime agent/model catalog path, supplied with--execution-catalogorAGENT_TASK_EXECUTION_CATALOG.task_group: optionalagent-task/<task_group>scope.dry_run: inspect routes, dependencies, claims, and catalog validity without launching an agent.max_parallel: workspace-wide active task-stage limit; defaults to3;0means unlimited.retry_blocked: retry eligible blocked tasks without changing their catalog route history.
--validate-plan validates one PLAN without launching orchestration and therefore does not require an execution catalog.
Preconditions
- Read the current plan and code-review contracts routed by
agent-ops/skills/common/router.md. - Obtain the execution catalog from the runtime or project layer. Common owns no default agent, model, provider, or route catalog.
- Run
--dry-runbefore the first live execution. - Never bypass the physical-workspace dispatcher lock.
- Keep automatic approval inside the current workspace and the PLAN's declared write set.
Runtime catalog contract
The catalog root contains exactly schema_version, targets, and routes. It must cover worker and review, and each stage must define every local-G01 through local-G10 and cloud-G01 through cloud-G10 route.
Each target has:
- an opaque
agentidentity; - an opaque
modelidentity; execution_class:local_modelorcloud_model;- optional
selfcheck_requiredboolean; runtime.command: a non-empty argv template executed without a shell;- optional
runtime.resume_command,preflight_command,environment,session_path,native_session_monitor, andauxiliary_logs; - optional
runtime.output_format:textorjsonl.
Command templates may use only {agent}, {model}, {target_id}, {workspace}, {attempt_dir}, {session_id}, {resume_session}, and {prompt}. The catalog must not embed repository secrets; environment values should refer only to runtime-provided non-secret configuration.
Each route owns its ordered candidates plus optional rule_id, policy_priority, and reason_codes. A route may use catalog-owned windows instead of a fixed candidate list; every window supplies an IANA timezone, start/end time, and candidates. Exactly one window must match.
Before work starts, the dispatcher:
- loads and validates the entire catalog;
- verifies exact route coverage and every target reference;
- verifies each target command is executable;
- runs an optional target
preflight_commandfor live execution; - records the catalog source and SHA-256 revision in the decision.
A persisted decision is valid only while the injected catalog revision and selected target snapshot still match. Catalog changes fail closed instead of silently changing an active work unit.
Selection and failover
- Initial execution selects the first candidate in the injected route.
- Resume pins the persisted target and route revision.
- The dispatcher never queries quota before admission and never accepts a quota snapshot as selector input.
- Classify actual terminal output after an attempt.
provider-quota,context-limit,model-unavailable,provider-stream-disconnect, andprovider-connectionmay advance to the next unused route candidate. - In particular, a confirmed quota/rate-limit error advances directly to the next candidate. A plain mention of quota in source text, model prose, or non-terminal output is not sufficient evidence.
generic-error, process termination, work-log failure, and review-control failure do not imply quota and do not change the selected target.- Never use a hidden promotion table or provider-specific fallback. If no next catalog candidate exists, keep recovery within the stage budget or block the task with evidence.
- Transfer logical context using the prior locator, normalized output, raw stream, workspace, and PLAN. Use native resume only when both targets opt into the same catalog-declared native-session mechanism and the session belongs to the current workspace.
Scheduling and write claims
- Admit every dependency-ready task whose canonical PLAN write set does not collide with another active claim.
- Require exactly one non-empty
Modified Files Summaryor supported legacy heading. Reject broad, malformed, directory, outside-workspace, or missing paths. - Atomically claim canonical paths before worker, self-check, or review execution. Keep a task's claim across retries and follow-up PLANs; release it only after verified archive completion.
- Treat explicit predecessors as unfinished while matching live execution evidence exists, even if a
complete.logis already visible. - Apply
max_parallelacross the physical workspace, independent of task-group filtering. Do not count internal helper coroutines as agent slots. - A blocker delays only that task and its dependency closure. Continue draining independent work.
Prompt and child boundary
Prefix worker and review prompts with the dispatcher-child boundary that prohibits starting or monitoring another orchestration loop. A child may use dispatch.py --validate-plan only when its plan or review finalization requires it.
Prompts must include absolute artifact paths and instruct the child to follow the repository's language and output rules. Do not hardcode a programming language, human language, agent, model, or provider in common prompts.
Never ask a child to create, edit, or summarize WORK_LOG.md; that file is dispatcher-owned.
Self-check
Run self-check only when the selected catalog target declares selfcheck_required=true. The completing decision, not a fixed agent identity or execution class, determines the requirement.
Accept self-check completion only when ## Implementation Checklist or its supported legacy heading contains at least one checkbox and every checkbox has a non-empty value. Run one full pass, then resume the latest successful native context for at most 10 unchecked-item retries when the target supports native resume. Block instead of silently starting a new context when a required persisted context is unavailable.
Runtime evidence and recovery
- Store each attempt under the dispatcher state directory with
locator.json,stream.log,normalized-output.log, andheartbeat.log. - Record the target id, opaque agent/model identity, execution class, runtime contract, catalog evidence, process identity, workspace identity, timestamps, result, and exact failure evidence.
- Treat stderr as terminal diagnostic evidence. For JSONL, recognize generic terminal event fields such as error/fatal type or severity, rejected/failed status with an error code, and explicit error flags.
- Determine liveness from PID/start-token/process-marker evidence and actual stream or native-session progress. Heartbeat mtime is never agent progress.
- Never start a duplicate attempt while owned live evidence remains.
- Keep a 10-consecutive-failure budget per task stage. Reset only that stage's budget after success.
- Preserve failed attempt logs. Delete successful attempt logs only after verified archive completion and no live evidence.
Work log
- Keep one dispatcher-owned
WORK_LOG.mdper task group. - Append chronological
STARTandFINISHrows with UTC time, task artifact, plan loop, role, attempt, selected agent/model display, result, and locator. - Archive the group log as the next
work_log_N.logonly after every observed task in the group is verified complete and idle. - Work-log write or archive failure is a retryable control-plane failure and prevents exit
0.
Invocation
python3 agent-ops/skills/common/orchestrate-agent-task-loop/scripts/dispatch.py \
--workspace /absolute/repository \
--execution-catalog /runtime/config/execution-catalog.json \
--dry-run
Remove --dry-run to start execution. Add --task-group <name>, --max-parallel <n>, or --retry-blocked only when requested by the workflow.
Launch the live dispatcher as one persistent foreground process. Do not wrap it in an arbitrary timeout and do not start a second dispatcher after a normal tool yield. Wait on the same execution handle until an attention event or terminal exit.
Completion checklist
- Catalog was injected, fully validated, preflighted, and revision-pinned.
- No fixed common agent/model/provider route or quota probe was used.
- Runtime quota errors moved only to the next catalog candidate.
- Dependencies, write claims, and workspace concurrency were enforced.
- Required self-check and official review stages completed.
- Every observed task has a verified archived
complete.log. - Work logs and successful attempt cleanup were reconciled.
- No active, waiting, pending, or blocked in-scope task remains.
- Dispatcher exited
0before successful final response.