./.archal/harness.ts for new integrations. npx archal init
generates one for you; this page is the reference for writing or extending one
by hand.
Template
./.archal/harness.ts
Stdout contract
Archal extracts the final answer from stdout with this precedence (cli/src/runner/execution/response-extraction.ts:200):
- Whole stdout parses as a single JSON object. Archal reads the
payloads[]ortextfield. Recommended shape for structured output: - JSON object embedded in mixed stdout. Archal scans for any outermost
{...}block containingpayloadsortext. Works when your agent prints logs and then a final JSON payload, but is fragile — prefer option 1. - NDJSON (one JSON object per line). Archal parses each line and picks
the object with a usable
payloads/textfield. Useful when your harness streams intermediate events. - Plain text fallback. If nothing above matches, Archal joins trimmed non-empty stdout lines outside JSON blocks. Any log lines you wrote to stdout end up in the “answer”. Keep logs on stderr if you rely on this path.
console.log(JSON.stringify({ text: result }))
is the right default.
Environment variables Archal injects
Archal sets these on the harness process before it spawns:| Variable | Description |
|---|---|
ARCHAL_ENGINE_TASK | The full task text (scenario prompt or --task "..."). |
ARCHAL_PREFLIGHT | Set to 1 during the boot preflight. Short-circuit and exit 0. |
ARCHAL_<TWIN>_URL | Per-twin MCP endpoint (e.g. ARCHAL_GITHUB_URL). |
ARCHAL_<TWIN>_BASE_URL | Per-twin REST base URL (e.g. ARCHAL_GITHUB_BASE_URL). |
ARCHAL_TWIN_NAMES | Comma-separated list of twins in this run. |
ARCHAL_MCP_CONFIG | Path to an MCP server config JSON, if your runtime wants to mount MCP servers directly. |
ARCHAL_TOKEN | Bearer token, if you need to call hosted twin APIs directly. |
HTTPS_PROXY | Present when the TLS proxy is on. |
NODE_EXTRA_CA_CERTS | Path to the proxy’s short-lived CA cert (present when the proxy is on). |
OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) are not
injected by Archal. Put them in .env or your CI secret store and read them
in the harness.
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. |
[D] criteria about
twin state are still checked either way as long as the run produced a trace.
How to route traffic to the twins
Two options, both supported side-by-side:- Direct HTTP to the injected endpoints. Read
ARCHAL_<TWIN>_BASE_URL/ARCHAL_<TWIN>_URLand pass them to your SDK (new Octokit({ baseUrl: process.env.ARCHAL_GITHUB_BASE_URL })). This is the preferred path — explicit, no TLS hijacking. - TLS proxy (route mode). When your runtime has hardcoded service
domains you can’t override (for example SDKs calling
oauth2.googleapis.comdirectly), Archal starts a TLS proxy and setsHTTPS_PROXY/NODE_EXTRA_CA_CERTSon the harness process. Calls to known twin domains get intercepted transparently. The proxy is on by default for local harness runs — pass--no-proxyto disable it. See Route-mode trust and safety.
Sanity-check the harness in isolation
Reproduce the preflight without running a scenario:OK and exit 0. If it hangs or crashes, archal run
will too — fix the harness first.
