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.
| Shape | Use when | Trade-off |
|---|---|---|
| Proxy | You 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. |
| Sidecar | You 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. |
| SDK | You 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. |
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/;
}
}
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:
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.
POST /api/protect with {action, target, input, context} body.{decision, reason, layer, deciding_pack, deciding_rule, decision_ms, agent_did, receipt_id}.