npx archal init generates one for you at ./.archal/harness.mjs (run with
node, no extra tooling). Prefer TypeScript? Put it at ./.archal/harness.ts
and run it with tsx instead - the runner accepts harness.{mjs,js,ts,cjs}.
Template
./.archal/harness.ts
What Archal reads from stdout
Archal extracts the final answer from stdout in this order:- One JSON object. Archal reads
payloads[]ortext. Recommended: - JSON object in mixed stdout. Works, but logs can make this brittle.
- NDJSON. Useful if your harness streams events.
- Plain text. Archal joins non-empty stdout lines outside JSON blocks.
Environment variables
Archal sets these on the harness process before it spawns:| Variable | Description |
|---|---|
AGENT_TASK | The full task text (scenario prompt or --task "..."). |
AGENT_CLONE_URLS | JSON map of clone names to REST base URLs for local harnesses. |
AGENT_ROUTE_HEADERS | JSON headers to include when a local harness calls an AGENT_CLONE_URLS endpoint. |
NODE_EXTRA_CA_CERTS | Path to the short-lived CA cert when the runtime cannot rely on the system trust store. |
OPENAI_API_KEY,
ANTHROPIC_API_KEY, and similar secrets in .env or CI secrets.
Exit-code contract
| Code | Meaning |
|---|---|
0 | Run succeeded, final answer printed to stdout. Evaluator scores the trace. |
| non-zero | Runtime error. The run is marked failed; [P] criteria are not evaluated. |
How to route service traffic
Use the same SDKs, service domains, and normal credential env vars your agent would use in production. For example, use Octokit againstapi.github.com.
Transparently routing unmodified SDKs that call real service domains (like
Octokit against api.github.com) requires Docker or sandbox mode, so Archal can
control DNS and TLS trust. A harness that instead calls the clone URL from
AGENT_CLONE_URLS directly is scored without either (see the minimal example
below).
For a local harness that calls the clone directly instead of using Docker or
sandbox routing, point the SDK at the matching URL in AGENT_CLONE_URLS and merge
AGENT_ROUTE_HEADERS into each clone request. Keep the normal service
authorization header too, for example Authorization: Bearer <test-token> for
GitHub REST.
Minimal clone-calling harness (no agent framework)
If you do not have an agent yet, the fastest path to a first score is a harness that calls the clone’s REST API directly. Archal injectsAGENT_CLONE_URLS and
AGENT_ROUTE_HEADERS when it starts the run, so the harness needs no Archal
SDK. This one matches the scenarios/first-run.md that archal init scaffolds
- list and summarize GitHub issues, read-only:
./.archal/harness.mjs
AGENT_ROUTE_HEADERS
(x-route-authorization) authenticates you to Archal, while the normal
service Authorization header is what the clone validates - keep both. The
default bootstrap token for each service is listed in
Authentication. Once you have a real agent, swap this
for a call into it and let it use normal SDKs.
Check it locally
Run the entrypoint directly without provisioning clones:0. (The clone-calling example above
prints No GitHub clone URL was provided. here - that is expected; the clone
URLs only exist during archal run.) If it hangs or crashes, archal run will
too.