glas-harness/docs/harness-contract.md
tegwick 97a50fc780
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Define the harness contract (GLAS-WP-0001-T01)
start_session/dispatch_tool/end_session, mirroring sand-boxer's
SandboxExtension ABC one layer up: sand-boxer establishes where work
runs, this contract governs how an agent session runs on top of it.
Unblocks the rein-aharness parity proof (T04) and rein-openweights
bootstrap (T05).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 12:37:59 +02:00

4 KiB

Harness contract

The interface a concrete harness backend ("rein") implements so glas-harness can route to it, per docs/adr/ADR-001-rein-harness-family.md. Mirrors sand-boxer's SandboxExtension ABC (provision/wait_ready/teardown) at the harness level, one layer up: sand-boxer establishes where dangerous work runs, this contract governs how an agent session runs on top of it.

Interface

class Rein(ABC):
    """Base class for concrete harness backends (reins)."""

    @abstractmethod
    def start_session(
        self, profile: HarnessProfile, inputs: dict[str, str], sandbox: SandboxHandle
    ) -> dict[str, str]:
        """Begin an agent session bound to a sandbox. Returns a session handle."""

    @abstractmethod
    def dispatch_tool(
        self, session: dict[str, str], tool_call: ToolCall
    ) -> ToolResult:
        """Run one tool call under the session's policy. Returns result + audit envelope."""

    @abstractmethod
    def end_session(self, session: dict[str, str]) -> dict[str, str]:
        """Close the session. Returns a summary (commit sha, tokens, duration, outcome)."""
  • start_session resolves the rein's own setup (persona/blueprint loading, credential acquisition) against the sandbox handle glas-harness already obtained from sand-boxer — the rein never provisions or tears down a sandbox itself.
  • dispatch_tool enforces the tool-profile allow-list glas-harness resolved (the same allow-list concept rein-aharness's profiles.py already implements today, just invoked through the contract instead of only the rein's own CLI).
  • end_session is where the existing "commit exists = success" signal (rein-aharness) or an equivalent per-rein success criterion is reported back to glas-harness for State Hub posting. glas-harness posts the audit event; the rein returns the facts.

Session lifecycle (who calls what)

glas-harness                              rein                    sand-boxer
────────────                              ────                    ──────────
resolve harness.* profile
request sandbox                    ──────────────────────────────▶ create()
receive sandbox handle             ◀──────────────────────────────
start_session(profile, in, sbx)  ─▶ acquire creds, load persona
                                  ◀─ session handle
dispatch_tool(session, call)     ─▶ run under allow-list
                                  ◀─ result + audit envelope
  (repeat dispatch_tool ...)
end_session(session)             ─▶ verify success, summarize
                                  ◀─ summary
post State Hub event
request sandbox teardown           ──────────────────────────────▶ destroy()

glas-harness owns the outer loop (profile resolution, sandbox request/teardown, State Hub reporting, actor attribution). The rein owns the inner loop (its own agentic reasoning, whatever that looks like — Claude Code CLI subprocess for rein-aharness, a direct OpenRouter tool-use loop for rein-openweights).

Actor attribution

Every dispatch_tool call and lifecycle transition carries an actor (adm/agt/atm) per glas-harness INTENT.md's audit requirement. glas-harness stamps this at dispatch time; reins do not need their own actor model.

Open questions this contract does not resolve yet

  • Whether start_session also carries scheduling/blueprint-sourcing parameters (kaizen-agentic blueprint id, activity-core task id) as part of inputs, or whether that stays entirely rein-side — tracked in rein-aharness/workplans/HARNESS-WP-0002-T04.
  • The exact SandboxHandle/ToolCall/ToolResult field shapes — sketched here at the level needed to unblock GLAS-WP-0001-T04 (the rein-aharness parity proof); refine once that task is underway rather than speculatively now.