1 executor harness
~larandar edited this page 2026-09-09 13:34:00 +02:00

← Home

executor-harness

How a workflow step reaches an agent. The harness starts and supervises steps over ting-a2a through two transport families — the DSH loopback HTTP transport and sandboxed external CLI dispatches — and normalizes every outcome into one shape for step bookkeeping. Failures are ToolFailures classified by ToolFailureKind, converted into executor_core::WorkflowError::Harness at the boundary.

DSH loopback transport (dsh)

ADR 0003: the DSH endpoint is reached over HTTP on loopback. Requests are sent without Origin headers; responses decode as JSON-RPC (JsonRpcRequest / JsonRpcResponse / JsonRpcError). The transport is DshTransport; an HttpResponse is the raw wire view.

Hardening (hardening)

The loopback boundary is enforced, not assumed:

  • validate_loopback_url / is_loopback_host — only loopback URLs are accepted.
  • Userinfo in the URL is rejected.
  • reject_redirect — redirects are refused; a loopback client does not follow them elsewhere.
  • validate_args — arguments are validated before dispatch.
  • ToolFailure / ToolFailureKind — typed classification of what went wrong.

External CLI transports (cli)

Three vendor CLIs are first-class transports: Claude Code (claude), Pi (pi), OpenAI Codex (codex) — ExternalCli::all(). Each dispatch runs the CLI as a sandboxed child process:

  • no shell — direct argv;
  • scrubbed environment;
  • hard byte budgets (CliLimits) on stdin, stdout, and stderr, so a chatty CLI can never exhaust the harness; oversized stdin is rejected before the process starts;
  • a wall-clock timeout per dispatch.

The raw process result is normalized into a NormalizedOutcome with an OutcomeStatus, which is the only thing step bookkeeping sees.