Skip to main content

Agents

An agent in ASF50 is a role-bound actor. Each run is dispatched with a role and an adapter. The role determines capability boundaries (allowed_paths, forbidden_paths, allowed commands); the adapter determines how the work is actually performed.

Roles

The canonical role set is declared in agent-harness/roles/. Each role has its own constraints:

RolePurpose
PLANNERReads canonical sources, emits a child task graph.
BUILDERImplements the bounded scope; runs bounded tests.
TEST_ENGINEERRuns the test suite; produces evidence.
INDEPENDENT_AUDIT_HIGHFresh-context auditor of a specific audit target.
INDEPENDENT_DOCS_AUDITORIndependent accuracy auditor for documentation.
RELEASE_MANAGERPerforms governed merge and deployment.
REPAIRERExecutes a bounded repair against a frozen target.
ARCHITECTProduces architecture-level decisions.
GOAL_OWNERThe human owner of the goal (offline).

A Builder cannot review, audit, or release its own work. The role-separation rule is enforced by the orchestrator and by the goal_registry.REQUIRED_FIELDS validator (via the required_role field).

Adapters

An adapter is a concrete implementation of an invoke(request) -> result function. ASF50 ships:

AdapterUse
deterministicIn-process stub; always returns PASS. Used for bootstrap and tests.
deterministic-cliRuns a real subprocess for non-AI side effects.
claude_cliAnthropic Claude CLI. PAID_MODEL_DISPATCH_APPROVAL required.
codex_cliOpenAI Codex CLI. PAID_MODEL_DISPATCH_APPROVAL required.
cursor_cliCursor CLI. PAID_MODEL_DISPATCH_APPROVAL required.
fake_agentTest harness.

The model router resolves which adapter a goal may use, gated by the PAID_MODEL_DISPATCH_APPROVAL scope.

Worktrees

A worktree is a detached Git working tree used to isolate a single dispatch. Worktrees are managed by scripts/goal-runner/worktree_manager.py. Two-root contracts (INDEPENDENT_AUDIT_HIGH) require both a dispatch worktree and an audit worktree pinned at the audit subject SHA; one-root contracts use the dispatch worktree only.

The worktree_policy field of a goal contract declares:

worktree_policy:
mode: CLEAN_DETACHED | BRANCH_SHARED | REPAIR_PINNED
source_commit: "<40-char SHA>"
  • CLEAN_DETACHED — create a fresh detached worktree pinned at source_commit.
  • BRANCH_SHARED — create a branch-based worktree; the goal owns the branch.
  • REPAIR_PINNED — the goal targets a frozen subject and may not advance HEAD.

Concurrency

ASF50 is single-agent sequential by default. MAX_ACTIVE_AI_AGENT_COUNT = 1. There is no parallel Builder, no parallel Auditor, no parallel Repairer. A fresh Independent Auditor context is logically separate but sequentially dispatched.

If you see the orchestrator attempting parallel AI dispatches, that is a policy violation and must be reported in the receipt.

Dispatch consumption

When a goal needs a paid model, the orchestrator reserves a gate from the runtime store. The reservation is recorded against owner_gates.last_dispatched_run_id and reservation_run_id. After the run finishes, the gate is either consumed or returned; the receipt records which.