Skip to content

Operating the Harness

Audience: the administrator responsible for what the agents are allowed to do, who can see what, and whether the record can be trusted.

What works today. All of it. The safety model is implemented and tested, the services that expose it are running, and every control below is reachable from the console or the API.


1. What you are administering

The harness runs AI agents that investigate security alerts. Your job is the envelope they operate inside: how much autonomy they have, which systems they may touch, and what evidence survives afterwards.

Three things are true by construction and are not settings you can relax:

  1. No agent can act on operational technology. Power, cooling, building and industrial controls are capped at recommend-only, in platform code.
  2. Nothing changes state without a human, until that specific action type has earned the right through a clean record.
  3. Everything is recorded in an append-only, hash-chained log.

2. Autonomy tiers

Tier The agent Typical use
T0 Observe Reads, analyses, reports Default for anything physical
T1 Recommend Proposes with evidence; a human decides High-impact actions
T2 Approve-to-act Executes after a human approves Contained, reversible actions
T3 Autonomous Acts alone within guardrails Low-risk only, and earned

How a tier is decided

The effective tier is the lowest of every applicable limit:

effective = min(
    what the playbook permits,      # customer judgment — a ceiling, never a floor
    what the asset class allows,    # OT is capped at T1
    what the action type has earned # from the autonomy ledger
)

Each limit is a named rule, so every decision records which one bound it. The console shows that rule to the analyst — "held at T1 by ot-cap" rather than an unexplained refusal.

Additional limits apply when relevant: a maintenance window holds state-changing actions, and the kill switch drops everything to T0.

Rules you cannot override

Rule id Effect
ot-cap Anything on an OT-classified asset is capped at T1.
asset-class-unknown An asset that cannot be classified is treated as OT.
kill-switch All agent activity halts.
maintenance-window State-changing actions are held for a human.
earned-autonomy An action type cannot exceed what it has earned. Default T2.
playbook-max The customer's declared ceiling.

Two of these deserve emphasis because they are deliberately inconvenient:

Unclassified assets are treated as OT. When the asset inventory cannot say what something is, the system assumes the most consequential answer. In production this will occasionally block a legitimate action because the inventory is incomplete. That is the intended trade: not knowing what a target is must never be safer than knowing.

Autonomy defaults to T2, not T3. An action type with no evaluation record waits for a human. Silence from the ledger is not consent.

3. The audit chain

Every prompt, tool call, decision, approval, action and model choice is appended to a per-organisation chain. Each event's hash covers its own content plus the previous event's hash, so altering anything invalidates every hash after it.

What it gives you

  • Tamper detection, located — verification reports the first event that fails.
  • Replay — any incident can be walked step by step.
  • Attribution — every event names the organisation, the actor and the incident.
  • A resume point — events are densely numbered, so a reconnecting client picks up exactly where it left off with no gap and no duplicate.

Be precise about the claim

The chain is tamper-evident, not tamper-proof. Someone holding a trusted chain head can prove history was not altered. Without an external anchor, someone with write access to the entire store could rewrite every hash consistently. Anchoring the chain head is planned work, not a current property — describing this as "immutable" would overstate it, and a technical audience will test that claim.

Secrets never reach the chain

Payloads carry prompts and tool arguments, so a credential can arrive through entirely ordinary code. Redaction therefore runs before the hash is computed: the stored bytes and the hashed bytes are the same, and there is no window in which an unredacted value exists in the log.

This ordering matters more than it looks. If redaction ran afterwards, removing a leaked secret would require rewriting the chain — destroying exactly the property the chain exists to provide. Two independent mechanisms run: known secret values are masked wherever they appear, and values under sensitive key names (authorization, api_key, password, token, …) are replaced wholesale.

Verifying

./deploy/bin/harness verify-chain

Re-walks every tenant's chain and reports the first event that does not hold. Idempotent and safe to run at any time. The console shows the same result as a banner on the Audit & replay screen, so an analyst can see the check pass without taking anyone's word for it.

4. Tenant isolation

Each organisation has its own chain, held by the audit-store service — which is the sole writer, because a chain with two writers is not a chain: the sequence races and the hash links stop holding. Isolation is visible rather than inferred — the files are separate, and one organisation's process never opens another's.

Every request derives its organisation from the authenticated caller. A parameter can narrow that scope but never widen it, which is what makes isolation a structural property rather than a rule each endpoint has to remember.

For a proof of concept this is physical separation. A production system would use logical separation — a shared database with per-organisation schemas or row-level security. The property that survives that change is the chain; the mechanism does not. Worth stating plainly rather than letting a demonstration imply a stronger guarantee than the product will ship.

5. Controls

Control Effect Where
Kill switch Halts all agent activity. No further work is admitted; an incident already waiting at the approval gate cannot be approved through. Console status bar, or POST /v1/control/kill
Air-gap mode Blocks all outbound traffic and forces the local model. ./deploy/bin/harness up-airgap, or HARNESS_AIRGAP
Model backend Switches between stub, recorded, hosted and local. HARNESS_MODEL_MODE
Maintenance window Holds state-changing actions for a human. Policy input; not yet surfaced in the console

"Immediately" for the kill switch means the next admission is refused and no further work starts — asserted as semantics rather than as a wall-clock promise, which would be unfalsifiable on a loaded machine and meaningless on a cluster.

Every one of these is an audited event. Flipping a control is itself part of the record.

Egress

Outbound traffic has exactly one path: a proxy that is the only container with a route to the internet. It enforces an allow-list held as data, not code, and logs every attempt — allowed or refused — attributed to an organisation, an agent and an incident.

Air-gap mode is demonstrated three ways, deliberately: the router refuses non-local backends, the proxy denies everything, and in the strongest form the proxy's external network is removed entirely so no container has any route off the host. The first two are operational toggles; the third is architectural. They are different strengths of claim and should be described as such.

6. Routine tasks

Task How
Start, stop, reset ./deploy/bin/harness up · down · reset
Check the stack is the code ./deploy/bin/harness stale — compares the running version to this working tree. demo refuses if they differ.
Put identity back to its file ./deploy/bin/harness reset-id (or ./deploy/bin/harness reset-identity) — discards every local account, password and session, then re-imports the realm. Asks first.
Prove the network topology ./deploy/bin/harness verify
Verify every audit chain ./deploy/bin/harness verify-chain
Show that the chain is tamper-evident ./deploy/bin/harness verify-tamper — alters an exported copy and names the first event that no longer verifies. The real chain is not touched.
Report which acceptance criteria are proven ./deploy/bin/harness criteria — runs the suite and reports a criterion green only when every proof named for it in eval/criteria.yaml passed in that run
Run the demonstration ./deploy/bin/harness demo
Gate it before showing anyone ./deploy/bin/harness dry-run — three clean runs from reset
Go air-gapped ./deploy/bin/harness up-airgap
Fetch local model weights ./deploy/bin/harness pull-model
See what is running ./deploy/bin/harness ps · logs [svc] · shell <svc>
Check the safety model holds uv run pytest -m "unit or property"
Check no customer content is in platform code python3 tools/boundary-check/boundary_check.py
Check an acceptance criterion uv run pytest -k a4

6a. What a reset keeps

Two commands, and the difference is what was produced against what was provisioned.

reset reset-id
Incidents and the audit chain discarded kept
Model weights kept kept
Local accounts, passwords, sessions kept discarded
The realm kept as it stands re-imported from deploy/keycloak/realm-harness.json

reset keeps identity for the same reason it keeps the model weights: accounts are something put into the system, not something it produced. An administrator whose password reverted on every reset would not be an administrator.

The consequence is that the realm file seeds a new database and stops being authoritative — Keycloak skips the import once the realm exists, which is exactly what makes a password change persist. reset-id is the way back when the file and reality have drifted, and it asks first because it discards every local change with them.


7. What this system deliberately does not do

Knowing the boundaries is part of operating it safely. In its current proof-of-concept form there is no brokering to an external directory (Keycloak can do it; it is not configured), no user management, registration, password reset or MFA, no role management beyond the three fixed roles, no TLS, no backup or retention policy, no high availability, no metrics stack, and no connectors to real security products. It runs on synthetic data only, and the lab accounts are not credentials.

It is not a production security platform and should not be pointed at one.