agentrec docs
The kernel-level flight recorder for AI agents. Deploy a node agent, record what your agents actually do, and ship attributed sessions to the control plane — with no changes to the agent itself.
Introduction
agentrec attaches to the Linux kernel with eBPF and records every process, file access, command, and network connection an AI agent triggers — each one attributed to the exact tool call that caused it. The agent declares intent (a tool call); the kernel records consequence (syscalls); agentrec joins the two into one replayable, unforgeable record.
The system has two halves: a node agent (the eBPF collector, runs on your Linux hosts) and a control plane (the API + console, where recordings land and are reviewed). This page covers deploying the agent and using the API.
pid → {session, tool_call} map that propagates on every fork, so a tag set on the agent survives exec, nested shells, and interpreter chains. Attribution follows process lineage, not wall-clock.Requirements
- Linux kernel 5.8+ with BTF enabled — check for
/sys/kernel/btf/vmlinux. The probe is CO-RE, so one build runs across kernels. - Privileges:
CAP_BPF+CAP_PERFMON(or run privileged) to load eBPF programs. - Host PID namespace when containerized (
--pid=host/hostPID: true). The kernel reports init-namespace pids; without this, attribution can't match and the agent self-tests and refuses to run rather than recording nothing. - Not macOS/Windows. eBPF is Linux-only — target CI runners, cloud dev environments, and production agent hosts.
Quickstart
1 — Get a token
Open the console and click Create a demo token, or call the API directly:
# create an org and an ingest token curl -X POST https://agentrec-api.adisingh925.workers.dev/v1/signup \ -H 'Content-Type: application/json' \ -d '{"name":"My workspace"}'
2 — Record and ship a workload
Point the agent at your control plane and wrap the agent command. It records everything the process tree does and uploads the attributed session when it finishes.
export AGENTREC_ENDPOINT=https://agentrec-api.adisingh925.workers.dev export AGENTREC_TOKEN=ar_live_… agentrec trace -- ./your-coding-agent
3 — Review it
Open the console, paste your token, and click the session to replay its attributed timeline and findings.
CI & wrappers
The simplest, fully-supported deployment: wrap the agent invocation in your pipeline. One recorded session per run, shipped on completion.
# GitHub Actions step - name: Run agent under agentrec run: agentrec trace --session "pr-${{ github.event.number }}" -- ./agent env: AGENTREC_ENDPOINT: https://agentrec-api.adisingh925.workers.dev AGENTREC_TOKEN: ${{ secrets.AGENTREC_TOKEN }}
If a run happens offline, record to a file and push it later:
agentrec trace --no-upload --out rec.json -- ./agent # later, from anywhere with the token: agentrec push rec.json # or: agentrec push - < rec.json
VMs & runners
Install the binary and a token config on a host with the installer:
curl -fsSL https://agentrec-site.pages.dev/install.sh | sudo sh -s -- \ --token ar_live_… \ --endpoint https://agentrec-api.adisingh925.workers.dev
This drops /etc/agentrec/agent.env with your token. Load it, then record:
set -a; . /etc/agentrec/agent.env; set +a agentrec trace -- ./your-agent
Kubernetes
Deploy one privileged, hostPID pod per node with Helm:
helm install agentrec ./deploy/helm \ --namespace agentrec --create-namespace \ --set ingest.token=ar_live_… \ --set image.repository=ghcr.io/OWNER/agentrec
Or apply the raw manifest after creating the secret:
kubectl create namespace agentrec kubectl -n agentrec create secret generic agentrec-ingest \ --from-literal=token=ar_live_… \ --from-literal=endpoint=https://agentrec-api.adisingh925.workers.dev kubectl apply -f deploy/agentrec-daemonset.yaml
CLI reference
agentrec trace [flags] -- <command>
Record a command and everything it spawns; upload if an endpoint and token are set.
| Flag | Description |
|---|---|
--session NAME | Name for the recording (default session) |
--endpoint URL | Ingest base URL (or AGENTREC_ENDPOINT); enables auto-upload |
--token TOKEN | Ingest token ar_live_… (or AGENTREC_TOKEN) |
--no-upload | Record locally but skip upload even if an endpoint is set |
--out FILE | Write the structured recording as JSON |
--jsonl FILE | Write one JSON object per kernel event (always unfiltered) |
--all | Include linker/libc noise filtered by default |
--no-resolve | Skip reverse DNS on network destinations |
--no-color | Plain output |
agentrec push [flags] <rec.json>
Upload a recording that already exists on disk (or - for stdin). Takes --endpoint / --token or the matching env vars.
agentrec mark <label>
Open a new tool call in the active recording. This is what an agent's PreToolUse hook or MCP interceptor calls to declare intent before acting.
agentrec info
Print kernel / BTF / tracefs diagnostics.
HTTP API
Base URL: https://agentrec-api.adisingh925.workers.dev. Authenticated endpoints take Authorization: Bearer ar_live_….
Create an org and an ingest token. Body: {"name": "..."}.
{ "org_id": "org_…", "name": "My workspace", "token": "ar_live_…" }Upload a recording (the agentrec trace --out format). Findings are computed server-side and returned.
curl -X POST $AGENTREC_ENDPOINT/v1/ingest \ -H "Authorization: Bearer $AGENTREC_TOKEN" \ -H 'Content-Type: application/json' \ --data-binary @rec.json → { "session_id":"…", "event_count":305, "finding_count":4, "crit_count":3, "findings":[…] }
List recent sessions for the org (metadata only).
Full recording plus its findings.
Findings across the org, most-severe first.
Recording format
A recording is a session with an array of tool calls; each call carries the kernel events attributed to it.
{
"session": "prod-agent",
"root_pid": 20572,
"duration_s": 1.33,
"calls": [
{
"seq": 4,
"label": "bash: check CI configuration",
"events": [
{ "type":"open", "path":"/root/.aws/credentials", "write":false,
"comm":"cat", "pid":20609, "t":0.917 },
{ "type":"connect", "family":"unix", "dest":"/var/run/docker.sock" }
]
}
]
}Event type is one of fork, exec, exit, open, connect, unlink.
Findings
The control plane scores each event and surfaces findings most-severe first. Severity 3 is critical.
| Sev | Finding | Triggered by |
|---|---|---|
| 3 | credential file read / write | open of .aws/credentials, .ssh/id_*, .npmrc, .env, kubeconfig, … |
| 3 | container runtime socket accessed | connect to docker.sock / containerd.sock |
| 3 | piped remote script to a shell | curl … | sh and interpreter variants |
| 3 | credential file deleted | unlink of a secret path |
| 2 | privilege escalation | exec of sudo / su |
| 1 | file deleted | any unlink |
Limitations
These are real boundaries, stated plainly.
- Host PID namespace required in containers — the agent self-tests and refuses to run silently otherwise.
- Records actions, not payloads. Which file, which host, which command — not file contents or request bodies. Payload/TLS visibility needs
SSL_read/SSL_writeuprobes. - Network destinations are IPs (best-effort reverse DNS); hostname capture from DNS is a later addition.
- Observe-only today. Kernel-level blocking (BPF-LSM) is on the roadmap, not shipped.
- Marks are cooperative. An agent that doesn't call
markis still fully recorded — everything lands under call 0 — but loses the intent join. - Linux only.