ablative docs
↑↓ move↵ openesc close
Stack Notebook ablative.com.au

AWL workers and placement

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

Open .md

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 awl 4

Names a typed task-queue contract in a workflow, or opens a worker document implementing that queue.

  • form declaration
  • positions top-level
//! The worker block is a typed requirement on the `greeter` task queue.
workflow greet_politely
  input name: String
  outcome done: type Greeting, route success

type Greeting { text: String }

worker greeter
  action greet(name: String) -> Greeting

step greet
  greet(name: name) -> reply
  route done(reply)
action awl 4

Declares one wire contract on a worker: named parameters, one return type, and at most one config line.

  • form header-clause
  • positions worker-block, role-block
//! Each action line is one wire contract: named parameters, one return.
workflow inspect_repo
  input repo: String
  outcome done: type Report, route success

type Report { summary: String }

worker inspectors
  action inspect(repo: String) -> Report

step inspect
  inspect(repo: repo) -> report
  route done(report)
timeout awl 4

Bounds the workflow run in the header, one activity on an action or call, or one `wait` — three distinct places.

  • form statement
  • positions workflow-header, worker-block, role-block, step-body, signal-reference
//! The header timeout bounds the whole run.
workflow nightly_sweep
  timeout 2h
  input target: String
  outcome done: type String, route success

step sweep
  route done("swept " + target)
retry awl 4

Sets an action's retry policy, as `retry N every DURATION` or `retry N backoff MIN..MAX`.

  • form header-clause
  • positions worker-block, role-block
//! Retry the flaky pull three times before the step faults.
workflow sync_mirror
  input remote: String
  outcome done: type Synced, route success

type Synced { revision: String }

worker mirrors
  action pull(remote: String) -> Synced
    retry 3 every 30s

step pull
  pull(remote: remote) -> synced
  route done(synced)
fallback awl 4

Declares the ordered task-queue chain consulted after a provider policy refusal.

  • form header-clause
  • positions worker-block, role-block
//! Route policy refusals through the declared queue chain.
workflow route_provider
  input prompt: String
  outcome done: type String, route success

worker agents
  action run(prompt: String) -> String
    fallback norn, claude

step run
  run(prompt: prompt) -> answer
  route done(answer)
advisory awl 4

Marks an action whose failure never faults its calling step; it can bind no result and be no pipe stage.

  • form header-clause
  • positions worker-block, role-block
//! An advisory announcement can fail without faulting the run.
workflow ship_build
  input version: String
  outcome done: type String, route success

worker notifier
  action announce(version: String) -> Nil
    advisory, timeout 30s

step ship
  announce(version: version)
  route done(version)
agent awl 4

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.

  • form header-clause
  • positions worker-block, role-block
//! An agent action hands its prompt to a harness and binds the outcome
//! record: accumulated `text`, the last answer as `final_message`, the canonical
//! `stop_reason`, and the `session_id` handle of the conversation that produced it.
workflow ask_reviewer
  input question: String
  outcome done: type String, route success

type Reply { text: String, final_message: String, stop_reason: String, session_id: String }

worker assistants
  action ask(prompt: String) -> Reply
    agent, timeout 10m

step ask
  ask(prompt: question) -> reply
  route done(reply.text)
every awl 4

Sets a fixed retry interval, or the cadence that arms a workloop.

  • form header-clause
  • positions workloop-header, worker-block, role-block
//! `every` fixes the interval between retries: ten seconds, each time.
workflow ping_service
  input url: String
  outcome done: type Pong, route success

type Pong { latency_ms: Int }

worker probes
  action ping(url: String) -> Pong
    retry 5 every 10s

step ping
  ping(url: url) -> pong
  route done(pong)
backoff awl 4

Sets the growing retry interval in `retry N backoff MIN..MAX`.

  • form header-clause
  • positions worker-block, role-block
//! `backoff` grows the retry interval from ten seconds toward two minutes.
workflow fetch_upstream
  input source: String
  outcome done: type Fetched, route success

type Fetched { bytes: Int }

worker fetchers
  action fetch(source: String) -> Fetched
    retry 4 backoff 10s..2m

step fetch
  fetch(source: source) -> fetched
  route done(fetched)
node awl 4

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.

  • form header-clause
  • positions worker-block, role-block
//! Pin an action's dispatch to the named worker node.
workflow build_release
  input tag: String
  outcome done: type Build, route success

type Build { artifact: String }

worker builders
  action build(tag: String) -> Build
    node group linux_large

step build
  build(tag: tag) -> built
  route done(built)
affinity awl 4

Keeps unpinned actions from this worker block on the node of its first unpinned lease. An explicit selector wins for that action.

  • form header-clause
  • positions worker-block
//! Keep this run's build actions on the node that serves its first lease.
workflow affinity_build
  input tag: String
  outcome done: type Build, route success

type Build { artifact: String }

worker builders
  affinity run
  action build(tag: String) -> Build
  action sign(artifact: String) -> Build
    node group signing_hsm

step build_and_sign
  build(tag: tag) -> built
  sign(artifact: built.artifact) -> signed
  route done(signed)
run awl 4

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.

  • form header-clause
  • positions worker-block
//! The document is the implementation: the server runs the command itself.
workflow greet_by_hand
  input name: String
  outcome done: type Stdout, route success

type Stdout { stdout: String }

worker shell
  action greet(name: String) -> Stdout
    run "echo hello {{name}}"

step greet
  greet(name: name) -> out
  route done(out)

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 awl 21

Selects the node recorded for another step in `node same as STEP`.

  • form statement
  • positions worker-block, role-block, step-body
//! Keep a build and its signature together, with review elsewhere.
workflow relative_build
  outcome done: type Nil, route success

worker builders
  action build() -> Nil
  action sign() -> Nil
  action review() -> Nil

step build
  build()
    node group release

step sign
  sign()
    node same as build

step review
  review() -> done
    node different from build
  route done
as awl 21

Joins `same` to its step name in `node same as STEP`.

  • form statement
  • positions worker-block, role-block, step-body
//! Keep a build and its signature together, with review elsewhere.
workflow relative_build
  outcome done: type Nil, route success

worker builders
  action build() -> Nil
  action sign() -> Nil
  action review() -> Nil

step build
  build()
    node group release

step sign
  sign()
    node same as build

step review
  review() -> done
    node different from build
  route done
different awl 21

Excludes the node recorded for another step in `node different from STEP`.

  • form statement
  • positions worker-block, role-block, step-body
//! Keep a build and its signature together, with review elsewhere.
workflow relative_build
  outcome done: type Nil, route success

worker builders
  action build() -> Nil
  action sign() -> Nil
  action review() -> Nil

step build
  build()
    node group release

step sign
  sign()
    node same as build

step review
  review() -> done
    node different from build
  route done
from awl 21

Names the reference step in `node different from STEP`, or opens a runtime binding path after `node`.

  • form statement
  • positions worker-block, role-block, step-body
//! Keep a build and its signature together, with review elsewhere.
workflow relative_build
  outcome done: type Nil, route success

worker builders
  action build() -> Nil
  action sign() -> Nil
  action review() -> Nil

step build
  build()
    node group release

step sign
  sign()
    node same as build

step review
  review() -> done
    node different from build
  route done
group awl 21

Keeps actions with the same run-scoped label on their group's recorded node.

  • form statement
  • positions worker-block, role-block, step-body
//! Keep a build and its signature together, with review elsewhere.
workflow relative_build
  outcome done: type Nil, route success

worker builders
  action build() -> Nil
  action sign() -> Nil
  action review() -> Nil

step build
  build()
    node group release

step sign
  sign()
    node same as build

step review
  review() -> done
    node different from build
  route done

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 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.
//! 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)