Skip to main content

Run a server and workers

Run the API server and worker processes on a durable Runtime, and talk to the server from the CLI.

Prerequisites​

  • a config/ folder with a validated flow, its agents and its models. See Your first flow.
  • a store plugin and a broker plugin installed for your chosen backend, for example afe-postgres and afe-redis.

Steps​

  1. Name a store and a broker in a Runtime manifest (see Running in production).

    A Runtime makes tickets and checkpoints durable. With a broker it also lets several processes share the work. Without a Runtime, the engine keeps tickets and checkpoints in memory and loses them when the process ends. The server does not start without a Runtime that names a store and a broker.

  2. Export the API token, then start the server and the workers.

    The server does not start without AFE_API_TOKEN. It listens on 127.0.0.1 unless you pass --host. afe serve is API only: it accepts a request, validates it, records the ticket and queues the job. It never runs a node. afe worker processes execute the queued jobs.

    export AFE_API_TOKEN=$(openssl rand -hex 32)
    afe serve -c config/ # listens on 127.0.0.1:8765
    afe worker -c config/ # in another terminal: runs the queued tickets
    afe worker -c config/ --concurrency 4 # up to four tickets at once
  3. Start several workers against the same store and broker.

    A ticket's lock is held by the worker that runs it. Two workers never run the same ticket at once. A job delivered twice never opens the ticket twice, and never repeats a paid model call. A resume is bound to the request it answers, so a duplicate resume never applies a stale answer to a later pause.

    afe serve -c ./config # the API, one process
    afe worker -c ./config # runs queued tickets, one at a time
    afe worker -c ./config -concurrency 4 # up to four tickets at once
    afe workers # live workers and queue metrics
  4. Add an operations listener with --ops-port N on afe serve or afe worker.

    It serves /livez, /readyz and /metrics, on 127.0.0.1 unless --ops-host says otherwise. Without --ops-port, nothing else listens (see Running in production).

  5. Serve the web UI with afe serve --ui, on the API's own host and port.

    Without it, only the API, the auth endpoints and /rpc answer (see Web UI).

Commands​

The other commands talk to the server. --url defaults to ws://127.0.0.1:8765/rpc:

CommandDoes
afe validate -c DIRChecks every manifest and prints all the issues (works on files, no server).
afe run FLOW -i INPUT.yaml [--revision ID]Starts a ticket and follows it until it ends or waits for a person.
afe rerun TICKETStarts a new ticket with the flow, input, project and revision of an existing one, and follows it.
afe resume TICKET [ACTION] [--comment …]Answers a waiting ticket (or restarts it) and follows it.
afe inspect TICKETState, revision, totals, the question it waits on, artifacts.
afe tickets [--state STATE]Lists tickets, with the first 12 characters of their revision.
afe workersLive workers and queue metrics.
afe cancel TICKETCancels a ticket. Its artifacts are kept.

When a flow works on a project (requiresWorkspace is not none), afe run takes --project NAME. The project must exist and match the flow's workspace type. afe inspect prints it.

Exit codes: 0 when the ticket is done, 2 when it waits for a person, 1 otherwise. Without a terminal, afe run does not ask anything. It exits with 2 and prints the afe resume command to use.

Notes​

  • afe worker --dry runs every agent on the dry harness, which fills each artifact from its Schema at zero cost.
  • A browser session for the web UI lives in an HttpOnly cookie:
    • POST /auth/login with {"token": "…"} sets it. The token is compared in constant time.
    • POST /auth/logout clears it.
    • GET /auth/session answers {"expires_at": …} or 401.
    • --session-hours sets how long a session lasts, 8 hours by default.
    • The /rpc WebSocket also accepts that cookie, but only when the request's Origin is the server's own. The CLI keeps using the Bearer token, never the cookie.
  • afe worker stops cleanly on SIGINT or SIGTERM. It stops claiming new tickets, waits for the ones it is running, releases its locks and exits.

Troubleshooting​

Symptom: afe serve exits with "set AFE_API_TOKEN: the server does not start without a token". Cause: the token was not exported in this shell before afe serve ran. Fix: export AFE_API_TOKEN again, then start afe serve.

Symptom: afe run never returns, or afe workers shows no live worker. Cause: no afe worker process is running against the same store and broker. Fix: start at least one afe worker -c config/ in another terminal.

Symptom: two afe worker processes both try to run the same ticket. Cause: this cannot happen against a shared Runtime. It signals the workers are pointed at different stores, for example one still using an in-memory Runtime. Fix: check both workers load the same config/ folder and the same store DSN.

See also​