Harness Docs / Deployment

Three Shapes

Proxy, Sidecar, SDK. Pick the shape that matches your control over the agent runtime. Same wire protocol, same policy packs, same audit ledger across all three.

01 / Compare

When to use which

ShapeUse whenTrade-off
ProxyYou can put an HTTP fronting layer between the agent and its tools, and the agent has no idea the harness is there. Useful for legacy agents you can't modify.Only governs HTTP-shaped tool calls. Stdio / direct-syscall tool calls bypass.
SidecarYou run the agent in a container or pod and can add a co-located process. Sidecar exposes /api/protect on localhost; the agent calls it explicitly. K8s + ECS + nomad friendly.Requires the agent to opt-in (call the sidecar before each tool). Loss of policy-vs-bypass attestation if the agent forgets a call.
SDKYou own the agent code. The harness is a library: every tool call goes through HarnessClient.evaluate_or_raise(...) as a guard. Lowest latency (no HTTP hop if using local-eval mode), highest control.Requires source access. Doesn't help with third-party agents.
02 / Proxy

Proxy shape

Run the reference daemon as the front door for a wrapped agent. The agent's HTTP traffic goes through the harness; non-allowed actions are rejected with 401.

Run the daemon:

./aiegis-harness \
  --port 18081 \
  --audit-db /var/lib/aiegis/audit.db \
  --policy-pack /etc/aiegis/pii-block.json \
  --policy-pack /etc/aiegis/tool-allowlist.json \
  --policy-pack /etc/aiegis/rate-limit.json

nginx fronting example — agent talks to https://agent.example.com/tools, every request first hits /api/protect via auth_request:

server {
  listen 443 ssl;
  server_name agent.example.com;

  # Sub-request: every tool call is harness-gated.
  location = /_aiegis_protect {
    internal;
    proxy_pass http://127.0.0.1:18081/api/protect;
    proxy_pass_request_body on;
    proxy_set_header Content-Type application/json;
  }

  location /tools/ {
    auth_request /_aiegis_protect;
    auth_request_set $aiegis_token $upstream_http_x_aegis_token;
    proxy_set_header X-AEGIS-Token $aiegis_token;
    proxy_pass http://upstream_tools/;
  }
}
03 / Sidecar

Sidecar shape

Run the reference daemon as a sidecar next to the agent process. The agent explicitly calls http://127.0.0.1:18081/api/protect before each tool action.

Kubernetes pod spec (excerpt):

apiVersion: v1
kind: Pod
metadata:
  name: my-agent
spec:
  containers:
    - name: agent
      image: my-org/my-agent:latest
      env:
        - name: HARNESS_URL
          value: "http://127.0.0.1:18081"
    - name: aiegis-harness
      image: aiegis/harness:0.1.0-reference-rs
      args:
        - "--port=18081"
        - "--audit-db=/audit/audit.db"
        - "--policy-pack=/packs/pii-block.json"
        - "--policy-pack=/packs/tool-allowlist.json"
      volumeMounts:
        - name: packs
          mountPath: /packs
          readOnly: true
        - name: audit
          mountPath: /audit
  volumes:
    - name: packs
      configMap:
        name: aiegis-policy-packs
    - name: audit
      persistentVolumeClaim:
        claimName: aiegis-audit-pvc

docker-compose equivalent:

services:
  agent:
    image: my-org/my-agent:latest
    environment:
      HARNESS_URL: http://harness:18081
    depends_on: [harness]
  harness:
    image: aiegis/harness:0.1.0-reference-rs
    command:
      - --port=18081
      - --audit-db=/audit/audit.db
      - --policy-pack=/packs/pii-block.json
      - --policy-pack=/packs/tool-allowlist.json
    volumes:
      - ./packs:/packs:ro
      - audit:/audit
volumes:
  audit:
04 / SDK

SDK shape

The agent code imports the harness as a library. Every tool call is wrapped in evaluate_or_raise(...). Lowest latency, highest control. Three bindings ship today: Rust, Python, Node.

Python:

from aiegis_harness import HarnessClient, HarnessDenied

client = HarnessClient(
    base_url="http://127.0.0.1:18081",   # local daemon
    # OR base_url="https://aiegis.ie", api_token=os.environ["AEGIS_KEY"],
    timeout_s=10,
)

def safe_read_file(path: str) -> str:
    client.evaluate_or_raise(
        action="tool.read_file",
        target=path,
        context={"agent_did": MY_AGENT_DID},
    )
    return open(path).read()

Node:

import { HarnessClient } from 'aiegis-harness';

const client = new HarnessClient('http://127.0.0.1:18081');

export async function safeReadFile(path) {
  await client.evaluateOrThrow(
    'tool.read_file',
    path,
    '',
    JSON.stringify({ agent_did: MY_AGENT_DID })
  );
  return fs.readFileSync(path, 'utf8');
}

Rust: in-process via harness-core. Skip the HTTP hop entirely — call harness_core::eval::evaluate_packs directly with loaded packs. Useful for embedded agents and CI gates.

05 / Common

Across all three shapes

  • Same wire protocol: POST /api/protect with {action, target, input, context} body.
  • Same policy-pack format — see Policy-Pack Format.
  • Same response shape — {decision, reason, layer, deciding_pack, deciding_rule, decision_ms, agent_did, receipt_id}.
  • Same audit-ledger entry — append-only with tamper-rejection triggers.
  • Same Day-2 hardening path: signed binaries, forced-routing protocol adoption.