Adds remote execution across all three harnesses. Each provider can now run its CLI through an AgentHarness.Exec implementation instead of a local port: the provider protocol (streaming, questions, approvals, cancellation) stays in your application's node, and only the CLI process moves. AgentHarness.Exec.Local is the default and reproduces local behavior; an application-provided exec module can place the process in a remote sandbox or behind an SSH channel. One implementation covers all three providers, because the contract is byte-level and protocol-free.
Selection is per session. Pi and Codex take provider_options: %{auth: :inherit, exec: {module, opts}}; Claude selects it through the claude_code adapter option. Remote execution requires auth: :inherit, since the fail-closed :subscription mode verifies local CLI state that says nothing about the environment the exec would run the process in.
A new guide, Writing an Exec implementation, walks through building a sandbox adapter using E2B as the example: exactly-once exit delivery, kill reaching the remote process rather than just the stream, writes queued until the remote pid is known, spec translation, and credential redaction.
Also in this release:
- Credential redaction throughout:
SessionConfiginspects safely, and every provider session scrubs its raw state viaformat_status/1, so crash reports rendered with Erlang~pformatting cannot leak session env values, API keys, or exec options (which routinely carry sandbox tokens). - Pi turns settle again on current pi releases, which removed the
agent_settledframe the session used as its settle point. Without the fix, every turn hung until the harness timeout regardless of transport. codex_sdk0.19.0, which fixes interrupted app-server streams waiting indefinitely.
No breaking changes. Existing Codex, Claude, and Pi sessions run exactly as before; remote execution is opt-in.
{:agent_harness, "~> 0.3.0"}