Open Harnessby condensate

detect → steer

Steer the coding agent you already run, on the subscription you already pay for.

A harness is two planes: control — what the agent does next — and capability — what it can reach. Every runtime already exposes both, as hooks and as MCP. Open Harness puts the steering brain server-side and rides in through those two seams, on any host. Advisory-only and content-free — it never carries your model traffic.

Install the hook shim Default mode is observe
One env var points the shim at the backend
session 4c9f · hook events · consent: annotate
PostToolUse  Grep {"pattern": "registerRoute"}                      
PostToolUse  Grep {"pattern": "registerRoute"}    signature repeat x2
PostToolUse  Grep {"pattern": "registerRoute"}    signature repeat x3
tool_loop fired  threshold 3 → template context_note_v1
inject "Open Harness: tool loop detected: Grep has been called 3 times
        in a row with identical arguments... vary the arguments."
PostToolUse  Read src/router.ts       signature changed — loop broken
ledger #4821  fire recorded · params hash only, no transcript
                
<50msshim overhead, test-asserted per event
0touches on your model traffic
5detectors, all deterministic
4consent tiers, observe by default
hooks

The control plane

The session's own hook points stream events out; verdicts come back and steer the trajectory. What to do next, when to redirect, when to stop.

mcp

The capability plane

One aggregated endpoint fans in the tool suite server-side, behind one auth and one meter. What the agent can reach.

together

A harness anywhere

A harness stops being an app you switch to and becomes a layer you attach — any host that speaks hooks and MCP. The model leg is never touched.

What it is

Your agent. Your subscription. One steering layer between them — that never touches the model leg.

You already pay for inference and you already run a harness. Open Harness adds the missing piece: a backend that watches the session's trajectory and corrects it in flight. It attaches through the two extension points every modern harness ships — nothing else is installed, and the model leg is never intercepted. Routing advice is applied by your harness through its own mechanisms.

01 A thin hook shim — the control surface

One dependency-free script your harness's own hook mechanism invokes on UserPromptSubmit, PreToolUse, PostToolUse, and Stop. Events go out, verdicts come back, and the shim renders them from its local template library. Backend unreachable? The shim exits as an identity hook — your agent never depends on Open Harness being up.

02 One MCP endpoint — the capability surface

A single streamable-HTTP server that fans in the whole tool suite server-side, behind one auth and one meter. The client contract stays small and stable; the detectors, composer, consent, and ledger live in the backend and iterate without you reinstalling anything.

The steering brain is server-side: deterministic detectors run over canonical session events, and verdicts degrade to what your harness can express. Design of record: the whitepaper.

Detectors

Your agent loops, thrashes, stalls, pads, and quits early. Something should notice.

Five detectors ship today. Every one is a pure state machine over hook events — signature compares, counters, and overlap ratios. No model reads your session to decide an intervention, and injected notes are composed only from a fixed template library.

tool_loop detector

Same tool, identical canonical arguments, N times in a row. A context note names the loop and asks for a different approach.

edit_thrash detector

The same file edited back and forth, each edit reversing the last. The note says: re-read, decide, then edit once.

progress_stall detector

A window of tool results that are all repeats of results the session has already seen — activity without a new outcome.

premature_stop detector

A Stop while the session's own task state still shows open work. In autonomous mode, the Stop hook re-drives the session.

filler_inflation detector

Consecutive replies that restate each other with no tool activity between them — words accumulating without action.

composer templates only

Verdicts carry a template_id plus scalar params; the shim renders them locally. No free-form generation, ever.

Every fire is idempotency-keyed (one decision per episode), ledgered append-only, and excluded from detector inputs — Open Harness never counts its own notes as filler.

Content-free

Sees the session's shape. Keeps none of its words.

never your model traffic

Routing is advisory only, by design, not configuration. Model requests terminate at your own endpoints under your own auth — Open Harness is not in that path.

digests, not transcripts

The ledger stores signal names, template ids, and a hash of the parameters — never prompt or tool-result text. Metrics are counts and durations with hashed principals.

no path from content to steering text

Detectors emit booleans and counts; the composer speaks only from the fixed template library. A poisoned tool result cannot write the words that steer you.

fail-open, measured

Missing key, backend down, timeout, bad verdict — the shim exits 0 with empty output, an identity hook. Its own overhead is instrumented and test-asserted under 50ms per event.

every write is attributed

Injected turns carry an explicit Open Harness prefix and a ledger id. You can diff every intervention against your own transcript.

Quickstart

Three steps, one of them optional.

01 Install the hook shim

Clone the repo; the shim is a single dependency-free Bun script. Point your harness's hooks at it — the settings block on the right is complete.

02 Set two env vars

CONDENSATE_URL is the backend (self-host default is http://localhost:4787); CONDENSATE_KEY is your API key. The key never appears in a payload — only its digest is sent.

03 Pick a tier

Self-hosting? Set CONDENSATE_CONSENT_TIER=observe on the backend and watch the ledger before you allow annotate, steer, or autonomous.

config
# the shim is one dependency-free Bun script
git clone https://github.com/dextracker/condensate
# point the shim at the backend (shell profile or settings env block)
export CONDENSATE_URL=https://oh.condensate.dev
export CONDENSATE_KEY=<your API key>

The shim's own 800ms fetch budget sits well inside the hook timeout, so the shim — not the harness — always decides the outcome. Full contract: hook-contract.md · tiers: consent-tiers.md.

The condensate family

two products, one company

Open Harness is the harness-steering half of condensate — this page. The MCP capability half ships too: the backend's aggregated /mcp endpoint is verified live end-to-end, and the first resident suite — 22 onchain tools — lives at onchain.condensate.dev. Same identity, same metering, same content-free posture.