Skip to content
This text was generated by an LLM (how cgwalters uses LLMs). cgwalters has not reviewed it yet.

The binary

agentic-job is the interface. The reusable workflow is a wrapper that moves files between jobs. Another CI system would run the same commands. The workflow fetches a checksummed static release binary when its source digest matches the pinned commit; otherwise it builds that source. build-binary: true forces a build.

Commands

CommandRuns asDoes
policy --allow FILE --repo OWNER/NAME --clone-url URL --base BRANCH --kind branch|analysis --outputs LIST --max-outputs NanyoneChecks one run's request against the caller's bounds and prints policy.json. --outputs takes all and --max-outputs takes max, for whatever the bounds allow.
config [--host] [--from FILE] [--string TABLE.KEY=VALUE]... [--integer ...]... [--boolean ...]... [--list ...]...anyoneWrites TOML from a file and individual settings. --host checks only the host configuration.
sandbox setup --config FILErootPrepares the host the agent runs on, and copies the configuration to /etc/agentic-job/.
sandbox check [--record|--unless-passed]the runner's userProbes the sandbox as the sandbox user, each probe with a positive control. --record (secure-host's) leaves a record when all probes pass, and --unless-passed (run's) probes nothing when it finds that record, against the same configuration, with nothing having entered the sandbox user since (sandbox-check.md).
run --policy FILE --task FILE --meta FILE --out DIRthe runner's userRuns the agent in the sandbox and takes what it hands back.
collect --policy FILE --outputs DIR --collected FILEanyoneValidates and sanitizes the handed-back requests as gh-aw's collector does, in check.yml and for a caller off GitHub (safe-outputs.md). Exit 1 if it refused a line.
check --policy FILE --outputs DIR --collected FILE [--report FILE]anyoneChecks handed-back outputs and patch against the policy.
apply --forge forgejo --server URL --repo OWNER/NAME --policy FILE --checked DIR --run-url URL [--comment-target N] [--push-repo OWNER/NAME]the apply jobPublishes checked comments, and a pull request from the bounds' fork, to Forgejo with FORGEJO_TOKEN (safe outputs).
event --allow FILE --event-name NAME --event FILE --actor LOGIN --repository OWNER/NAME --out DIRtrusted policy jobDecides event admission. Optional files: --actor-permission, --pull-request, --task. See events.md.
workflows check [--root DIR] [--exemptions FILE]anyoneRefuses workflow files whose jobs neither run secure-host nor call the reusable workflow, and the other shapes in workflows-check.md. Exit 1 names each file, job and step.
acp-drive start|prompt|events|cancel|status|stopa run's agentStarts the run's child agent and drives it over ACP (harness.md).
session connect ENDPOINT [--json]an operator or their agentJoins a session run's conversation: each line of standard input is a prompt, and it prints what the agent says, or with --json each message from the bridge as one line (session runs).
audit DIR [--json]anyoneInspects downloaded artifacts offline. Findings do not cause a refusal exit code. See workflow.md.

Internal commands are hidden: launch-agent (what run has the session start, as the sandbox user), sandbox probe-local (what sandbox check runs as the sandbox user), and helper, the root-owned entry point for privileged operations after setup.

sandbox check and run are the supervisor. It runs as the runner's user, whose general sudo access setup removes by default. A narrow sudo rule permits the root-owned helper to enter the sandbox with run0, reap its processes and read the proxy's fixed log. Without --runner-home, everything it does in the agent's files (the clone, git, reading the outcome and the requests) it does as the sandbox user, so that a link the agent planted cannot make it read the runner's files. The reusable workflow, by default (agent-user: runner), and review.yml pass --runner-home: run uses no sandbox user, the agent is the runner's user and can read and change the transcript and the limits, read run's environment and stop run, cleanup is the agent's process group only, and the token probes do not run. What separates the agent there is the job's read-only tokens, no id-token and no secret but the run token, secure-host's deprivileging and the check on another machine (requirements.md). sandbox-check.md describes the helper, and the action's lock its limits.

check is half the check on purpose. Which request types exist, how many of each, and the sanitizing of their text are gh-aw's rules, which collect ports and is held to by fixtures. --collected is what collect made of the outputs, and is given by path so that it is never taken from what the agent's machine uploaded. safe-outputs.md has both halves.

config exists because a workflow gets a run's settings as strings from whoever called it. Each setting is the value of its one key and is never read as TOML, so an input that holds a quote or a table header cannot add a key. Empty settings leave the file unchanged. Use --host when composing a configuration for secure-host without an agent.

Files read

--allow, the caller's bounds: the hosts a clone URL may name, globs for repositories and base branches, a ceiling per output type and in all, the patch's size and file limits. This repository's is an example.

--config, TOML with these tables. A key that is not known is refused. run reads only the copy sandbox setup left in /etc/agentic-job/, which the sandbox user cannot change and which holds no secret.

TableHolds
[sandbox]the sandbox user and its groups, directories to close, services to stop; [sandbox.check] has what the probes need and what they accept, before-agent, fetch-repo and containers (sandbox-check.md)
[egress]proxy (whether the egress proxy runs), direct (addresses reached without it), policy, rust-proxy (the binary's own proxy in place of mitmproxy; on by default, false needs python3-venv in [setup] packages)
[setup]packages, npm, agents (pinned in the binary), and a script for toolchains; optional tools for a caller-pinned installer (toolchains); repo-packages only in a file given to agentic-job config, which adds the --repo entry to packages
[inference]url; register, one of github-oidc, plain and token-file, with no default; audience; token-file; identity-proxy; anthropic-url and openai-url
[agent]name, model, and config-repo, config-ref, config-path for a public repository holding its configuration; skills to install the built-in skills
[child-agent]name (only vibe) and model of a second agent the agent may drive; needs limits.max-requests and a sandbox user (run --runner-home refuses it)
[limits]timeout-minutes, max-requests, max-tasks, budget, uncapped; max-repeats (repeated tool calls, off by default)
[mcp.NAME]url, secret (only MCP_TOKEN) and allowed of one remote MCP server run serves the agent with a credential it never holds
[session]listen, operators, origins, capability (a Tailscale app capability that lets tagged nodes in) and idle-minutes for a conversation; watch-item and watch-seconds to send the agent updates of the run's item (off by default)
[commit]author and trailers of the hand-back's commit; a bounds file's commit_author (safe outputs) takes the place of author

[limits] without a timeout is refused, and so is one that caps neither model requests nor spending unless it says uncapped = true. A cap on model requests that nothing counts is refused too (harness.md). hosted.toml is a configuration for GitHub's ubuntu-26.04.

--meta, JSON about the run from the CI system, copied into summary.json. Its run_id names the patch, so a run has to be given one.

Files written

policy prints policy.json: the request as allowed, the clone URL for run, and the configuration collect and gh-aw's handlers run with.

run writes under --out, in the names and schemas of the tree this replaces so that its readers keep working: run/ (summary.json, summary.md, condensed.log, outcome.json), transcript.tar.zst, and safe-outputs/ if something was handed back. They exist only for a run that passed the gate on uploads. workflow.md describes the artifacts.

check --report writes the verdict as JSON, with the reasons for a refusal and the files the patch names.

Exit states

Callers branch on these, so they are part of the interface.

StaterunThe other commands
0the agent ended its turnaccepted; every probe passed
1the agent failed or cancelled, or a signal stopped runrefused; a probe failed
2bad arguments, an internal error, results that did not pass the gate, or a run that could not be cleaned up afterbad arguments or an internal error
3a request, task or spending limit stopped the agent, or it handed back after a turn that ended on an error
4the run never started: something before the agent failed (the check of where the binary is, the agent's configuration, the clone, the registration at the proxy, the probe of the run token); trying again is safe
124the timeout stopped the agent

For 3 and 124, summary.json says whether the agent handed back. A session that ends in an internal error still exits 2, but its results are taken as a failure that hands nothing back, so a run that passes the gate leaves a summary saying why.

What the binary knows of GitHub

Little, and on purpose: the clone URL comes in through the policy, and the check that the target is public needs the forge's API, so the workflow does it. The binary reads the ACTIONS_ID_TOKEN_REQUEST_* variables to register with github-oidc, and RUNNER_TEMP, RUNNER_WORKSPACE and GITHUB_WORKSPACE in sandbox check, to probe the job's work directories. It starts nothing with the job's ACTIONS_* variables in its environment, and keeps whatever the agent chose from being read as a command by GitHub's runner on its way to the job log.

No wrapper for another CI system exists. Event admission reads GitHub payloads but leaves API calls to the trusted workflow.