# AWL workers and placement

Action contracts, delivery policy, declared bodies, harnesses and relative node selection.

A worker declaration names a task queue and typed actions. An action without a body needs a compatible worker. A deployed declared body runs through the server's command executor.

## Contracts and delivery

Calls use named arguments. Delivery settings can be declared on an action and overridden at the call. Timeout bounds an attempt after a worker accepts it; queue availability has separate server settings.

- `worker`: Names a typed task-queue contract in a workflow, or opens a worker document implementing that queue. Arguments: form: declaration; positions: top-level.
- `action`: Declares one wire contract on a worker: named parameters, one return type, and at most one config line. Arguments: form: header-clause; positions: worker-block, role-block.
- `timeout`: Bounds the workflow run in the header, one activity on an action or call, or one `wait` — three distinct places. Arguments: form: statement; positions: workflow-header, worker-block, role-block, step-body, signal-reference.
- `retry`: Sets an action's retry policy, as `retry N every DURATION` or `retry N backoff MIN..MAX`. Arguments: form: header-clause; positions: worker-block, role-block.
- `fallback`: Declares the ordered task-queue chain consulted after a provider policy refusal. Arguments: form: header-clause; positions: worker-block, role-block.
- `advisory`: Marks an action whose failure never faults its calling step; it can bind no result and be no pipe stage. Arguments: form: header-clause; positions: worker-block, role-block.
- `agent`: Marks an action as an agent seam. The prompt is a String; an explicitly bound working-directory parameter can accompany it. The result has text, final_message, stop_reason and session_id fields. Arguments: form: header-clause; positions: worker-block, role-block.
- `every`: Sets a fixed retry interval, or the cadence that arms a workloop. Arguments: form: header-clause; positions: workloop-header, worker-block, role-block.
- `backoff`: Sets the growing retry interval in `retry N backoff MIN..MAX`. Arguments: form: header-clause; positions: worker-block, role-block.
- `node`: Constrains relative placement with `node same as STEP`, `node different from STEP`, or `node group LABEL`; `node from PATH` reads a String in the run and an empty value gives no call-site pin. Arguments: form: header-clause; positions: worker-block, role-block.
- `affinity`: Keeps unpinned actions from this worker block on the node of its first unpinned lease. An explicit selector wins for that action. Arguments: form: header-clause; positions: worker-block.
- `run`: Gives an action a command-line body, which the server runs itself with no sandbox of any kind; `runs command <name>` is the typed alternative. Arguments: form: header-clause; positions: worker-block.


Retry counts additional attempts. A retryable failure consumes that policy; worker loss can redispatch the same attempt. A fallback names another declared worker queue, not an arbitrary program.

## Relative placement

An authored node selector relates work inside a run. A bare physical node name is refused. The referenced step must exist and cannot be the enclosing step itself.

- `same`: Selects the node recorded for another step in `node same as STEP`. Arguments: form: statement; positions: worker-block, role-block, step-body.
- `as`: Joins `same` to its step name in `node same as STEP`. Arguments: form: statement; positions: worker-block, role-block, step-body.
- `different`: Excludes the node recorded for another step in `node different from STEP`. Arguments: form: statement; positions: worker-block, role-block, step-body.
- `from`: Names the reference step in `node different from STEP`, or opens a runtime binding path after `node`. Arguments: form: statement; positions: worker-block, role-block, step-body.
- `group`: Keeps actions with the same run-scoped label on their group's recorded node. Arguments: form: statement; positions: worker-block, role-block, step-body.


A call site can override node and timeout. Retry policy and declaration markers cannot be overridden there. A call-site selector wins over its declaration. Run affinity keeps unpinned actions from one worker block on the first unpinned lease's node. It is a workflow delivery policy and is refused in a worker document.

## Worker documents

A worker document opens with one queue and owns its actions' implementations. It declares no workflow inputs, outcomes or steps. Capture can return the command outcome, trimmed text or decoded JSON of the declared result type.

The worker advertisement is derived from that document. It must agree with the workflow's independently derived contract. Use worker check mode before connecting.

## Agent harnesses

A harness section declares the adapter, concurrency, reconnect policy and environment variable names. ACP also requires a command, explicit permission and an exit grace. Both kinds require a working directory. Paths can be absolute or begin with the literal workspace-root marker; a working directory can instead be bound to an action parameter. The checker names missing fields for the declared kind.

No undeclared environment is inherited by the agent. A missing declared variable is reported at launch. Read [worker operations](/aion/operations/workers/) for serving and supervision.

## Harness fields

- `kind`: Required: acp or norn. Kind-specific fields from the other adapter are refused.
- `concurrency`: Required positive maximum activities served at once.
- `reconnect_initial_backoff`: Required positive first reconnect duration.
- `reconnect_max_backoff`: Required duration at least the initial delay.
- `reconnect_max_attempts`: Required positive reconnect budget.
- `connect_timeout`: Optional positive overall connect duration; requires registration_timeout. The total outer bound adds twice the registration window.
- `registration_timeout`: Optional positive setup read window. Without it the transport's own setup deadline applies.
- `env_pass`: Required list of quoted variable names. The whole child environment; values are resolved on the host.
- `command`: ACP only, required executable path. Absolute or beginning with the literal {workspace_root}.
- `args`: Optional quoted argument strings in order.
- `cwd`: Required for both kinds: a literal absolute or {workspace_root}-leading directory, or cwd from PARAMETER. The bound form requires a String parameter on every action served and validates the supplied directory at dispatch.
- `permission`: ACP only, required: deny or allow-once.
- `exit_grace`: ACP only, required shutdown duration. Zero seconds closes stdin and kills immediately.
- `binary`: Norn only, optional executable path. Without it the adapter resolves norn on PATH.


**Complete Norn worker declaration with a per-job directory**

```text
//! The second accepted `cwd` form: the directory arrives WITH the work.
//!
//! A worker that serves many jobs cannot name one tree in advance — which tree a
//! job concerns is a property of the job, not of the box the worker runs on. So
//! the harness binds its working directory to an action parameter, and the
//! checker proves that every action this harness actually serves declares that
//! parameter as a `String`.
//!
//! Nothing is softened by this. The document still has to SAY where the agent
//! stands; it just says it by naming the field the answer arrives in rather than
//! by writing a path only one machine could satisfy.
workflow review_a_tree
  input tree: String
  input question: String
  outcome answered: type Answer, route success

type Answer { reply: String }

/// The canonical agent-outcome record: the checker demands the STRUCTURE, not
/// a blessed name.
type Reply { text: String, final_message: String, stop_reason: String, session_id: String }

worker reviewers
  harness
    kind norn
    concurrency 2
    reconnect_initial_backoff 5s
    reconnect_max_backoff 1m
    reconnect_max_attempts 50
    env_pass "PATH", "HOME"
    args "--account", "default"
    cwd from repo
    binary "/usr/local/bin/norn"
  action review(repo: String, prompt: String) -> Reply
    agent

step review
  review(repo: tree, prompt: question) -> reply
  route answered(reply: reply.text)
```
