The effect plane for AI coding agents: kernel-enforced policy, system observability, and session backup, attached to the agent you already run, wherever it already runs.
$ actime run -- claudeYour engineers are running Claude Code, Codex, Gemini CLI, and OpenCode on company laptops, CI runners, and cloud sandboxes. Each one can spawn shells, rewrite files, reach the network, and burn a machine's CPU. When something goes wrong, the agent's own transcript is the only account of what happened — written by the thing you are trying to audit.
Actime attaches three planes to the agent's process tree, unmodified:
| Plane | Component | Question it answers |
|---|---|---|
| Policy | ActPlane (eBPF) | What is the agent allowed to do? |
| Observability | AgentSight (eBPF) | What did the agent actually do? |
| Backup | Akeep | What did the agent decide, and can we replay it? |
What you get back is not a log the agent wrote. It is what the kernel saw.
Actime does not manage sandboxes. Bring your own sandbox, or none at all. Actime attaches to the process tree either way.
The sandbox contains. Actime accounts.
That line describes roles, not position. The invariant that is always true is that Actime observes and enforces below the tool layer, at the syscall/effect boundary.
# 1. Install (Linux x86_64/aarch64; or build from source, see below)
curl -fsSL https://raw.githubusercontent.com/eunomia-bpf/actime/main/scripts/install.sh | sh
# 2. Check what your machine supports
actime doctor
# 3. Check which policy rules this host can actually enforce
# (no privileges needed)
actime policy check
# 4. A first run — works unprivileged, with no engines installed
actime run --policy off --no-backup -- /bin/echo hi
# 5. Read the record
actime reportactime policy check compiles the configured policy and prints one line per
rule: enforceable on this host, or not, with the missing engine feature named.
It loads nothing into the kernel. With the default balanced profile:
ok policy compiled from coding-agent-baseline · 2/2 rules enforceable on this host
RULE EFFECT ENFORCEABLE REASON
destructive-vcs kill yes
mass-deletion kill yes
That first run uses no eBPF and no privileges; it still produces a manifest and
a report, with the policy and observability planes marked Disabled and the reason
recorded. For the full three planes, install the engines Actime drives and run
your real agent:
cargo install actplane agentsight akeep
actime run -- claudeThere is nothing else to configure. actime run with no actime.yaml uses the
balanced profile and turns on every plane your kernel and privileges allow.
Whatever is unavailable degrades the run rather than aborting it, with one
exception: policy.mode: enforce fails closed. See
Degradation.
Every run ends with a report on the terminal and on disk. Real output of the quick-start run above, on a machine without the engines installed:
Actime run report
------------------------------------------------------------------------
Run id: 20260805-124610-f7db
Agent: command
Argv: /bin/echo hi
Duration: 1.7s
Exit code: 0
Profile: balanced
Target
------------------------------------------------------------------------
kind: command
spec: /bin/echo hi
host_pid: 3577921
note: launched as a host child process
Planes
------------------------------------------------------------------------
policy Disabled policy.mode is off
observability Degraded agentsight produced no process/file/network observatio…
backup Disabled backup.enabled is false
Summary
------------------------------------------------------------------------
violations=0 blocked=0 killed=0
processes=0 files_written=0 endpoints=0
llm_calls=0 tokens_in=0 tokens_out=0
peak_rss=0 B cpu=0.00s duration=1.7s
And with all three planes active on a real agent run (illustrative; this one
needs the engines and root or CAP_BPF):
Actime run report
------------------------------------------------------------------------
Run id: 20260804-153012-a3f1
Agent: claude
Argv: claude -p add retry logic to the uploader and run the tests
Duration: 4m12s
Exit code: 0
Profile: balanced
Target
------------------------------------------------------------------------
kind: command
spec: claude -p add retry logic to the uploader and run the tests
host_pid: 4124801
note: launched as a host child process
Planes
------------------------------------------------------------------------
policy Active
observability Active
backup Active
Summary
------------------------------------------------------------------------
violations=2 blocked=0 killed=2
processes=214 files_written=18 endpoints=6
llm_calls=37 tokens_in=411995 tokens_out=9102
peak_rss=1.9 GiB cpu=221.00s duration=4m12s
Policy violations (2)
------------------------------------------------------------------------
RULE EFFECT TARGET REASON
destructive-vcs kill /usr/bin/git Force-pushing, ha…
mass-deletion kill /usr/bin/rm Recursive deletio…
Next steps
------------------------------------------------------------------------
• actime report 20260804-153012-a3f1 --markdown
• actime report 20260804-153012-a3f1 --json
• Review blocked/killed violations in ~/.local/share/actime/runs/20260804-153012-a3f1/violations.jsonl
The full record lives in ~/.local/share/actime/runs/<run-id>/: the manifest,
the effective config, the exact policy that was loaded, every violation as
JSONL, the AgentSight observability database, and a rendered report.md. Override
the root with ACTIME_HOME. actime report <id> --markdown adds a timeline
section; --json emits the whole record for tooling.
Actime's position relative to a sandbox is a deployment choice, not an architectural constraint. All three are supported:
| Position | When to choose it | Tamper story | |
|---|---|---|---|
| A | Outside the sandbox — Actime on the host, attached to an existing container's process tree (actime attach --container, --pod) |
You own the host: workstations, CI runners, self-managed Kubernetes nodes. Needs root or CAP_BPF on the host |
Strongest: root inside the container cannot disable the recorder or edit the record |
| B | Inside the sandbox — Actime in the same container/VM as the agent (actime run -- claude, inside) |
You do not own the host: E2B, Daytona, AWS AgentCore, managed Kubernetes, someone else's microVM. Also how a sandbox vendor ships Actime in its image | Weaker: root inside the container can interfere. The container needs CAP_BPF (often plus CAP_PERFMON/CAP_SYS_ADMIN) granted to it |
| C | No sandbox at all — a plain process on a machine | The common workstation case | Same as host-side attach to a plain process tree |
Position B is the only option on managed sandbox platforms, and its weaker
tamper story is real: an agent with root in its own container can interfere
with a recorder running in the same container. We say so plainly wherever it
matters, and actime doctor detects the in-container case and tells you.
Never read a host-side guarantee into a position-B deployment.
The setup for each position — including the docker run --cap-add incantation
for B and host-side attach for A — is in
docs/deployment.md.
Most agent guardrails sit at the tool layer: the framework asks permission before it calls a tool. That works right up to the moment the agent writes a shell script, and a coding agent's whole job is writing shell scripts.
Actime enforces below the tool layer, at the syscall boundary, where the effect actually happens. This is independent of where Actime is deployed:
| The agent does | Tool-layer guardrail | Actime |
|---|---|---|
| calls a blocked tool | blocked | blocked |
bash -c the same thing |
passes | blocked |
| a Python subprocess does it | passes | blocked |
| a subagent it spawned does it | usually passes | blocked, lineage is inherited |
| reads a secret, then posts it from another process | invisible | expressible — see below; not enforceable with released ActPlane 0.1.8 |
The first four rows are what Actime enforces today: exec-level rules
(git --force, rm -rf, git push) that hold below the tool layer no matter
how the agent reached the syscall.
The last row is the design's core idea, and it is not a shipping capability
yet. The policy language does not just match calls, it can express where data
came from. A value read out of .env, copied into a temp file, piped through
jq, and sent by a subprocess is still labeled when it reaches the socket:
rule no-secret-egress:
kill connect endpoint "*" if AGENT and SECRET
because "This process holds data derived from a secret file and tried to open a network connection..."
No syscall allowlist can express that, because the offending syscall is an
ordinary connect. What makes it a violation is its history. That rule ships
in the information-flow pack — but enforcing it needs engine features
(file-source label propagation, path contains/suffix matchers) that released
ActPlane 0.1.8 does not provide on the attach path Actime uses, so today the
rule compiles, is reported as not enforceable by actime policy check, and
--policy enforce refuses to start a run that requests it. When the engine
enables those rule classes, the same pack becomes enforceable with no doc
change. docs/policies.md has the full story.
your agent, unmodified
claude · codex · gemini · opencode · any command
│
existing process tree
(a container you made, a pod, or a plain process)
│
┌─────────────────────▼─────────────────────┐
│ policy plane ActPlane (eBPF) │ ← constrains
│ observability plane AgentSight (eBPF) │ ← accounts
│ backup plane Akeep │ ← preserves
└─────────────────────┬─────────────────────┘
│
run record + report
Actime never creates, starts, stops, or removes a container or pod.
actime attach --container / --pod only resolve targets that already exist —
that is how Actime composes with other people's sandboxes.
Actime does not reimplement the planes. It composes three existing projects into one runtime, one config file, and one report:
| Plane | Project | What it contributes |
|---|---|---|
| Policy | ActPlane | kernel enforcement of policy rules: exec-level rules today, labeled information flow as the engine enables it |
| Observability | AgentSight | process, file, network, TLS, and resource observations |
| Backup | Akeep | versioned, restorable agent session history |
The eBPF instrumentation underneath comes from bpftime. Each project remains useful on its own; Actime is how you install, run, and operate them together.
Actime needs actplane ≥ 0.1.8, agentsight ≥ 0.2.60, and akeep ≥ 0.2.0.
actime doctor checks the versions it finds and tells you what to upgrade.
Policies are ActPlane rules over real OS effects. Actime ships three packs and you can add your own:
# actime.yaml
policy:
mode: enforce # off | observe | enforce
packs:
- coding-agent-baseline # destructive VCS, mass deletion — enforceable today
- no-vcs-write # the agent edits, the human publishes — enforceable today
- information-flow # file fences, secret-egress labels — needs engine
# features released ActPlane 0.1.8 does not ship
files:
- ./team-policy.dslWhich rules your host can actually enforce is a host property, not a pack
property. actime policy check is how you find out — it compiles the
configured policy, loads nothing, needs no privileges, and prints one line per
rule:
$ actime policy check # packs: [information-flow]
ok policy compiled from information-flow · 0/4 rules enforceable on this host
RULE EFFECT ENFORCEABLE REASON
credential-access notify no engine missing features required on attach/delta path: path contains matches, path suffix matches
run-record-integrity block no engine missing features required on attach/delta path: path contains matches, write sink rules
no-secret-egress kill no engine missing features required on attach/delta path: path contains matches, path suffix matches
system-fence block no engine missing features required on attach/delta path: write sink rules
With released ActPlane 0.1.8, exec-based rules (coding-agent-baseline,
no-vcs-write) install and fire; the file-sink and label-propagation rules in
information-flow — including no-secret-egress — do not. Two consequences:
--policy enforcefails closed: if any requested rule is not enforceable, the run aborts before the agent starts (exit 1) rather than silently enforcing a subset.--policy observeproceeds, but the unenforceable rules are recorded in the manifest and printed in the report, so the record never claims the run watched for something it did not.
actime policy list # packs and what each one forbids
actime policy show no-vcs-write
actime policy check # per-rule enforceability on this host
actime policy explain # how each clause lowers to kernel matcherscheck and explain call the installed actplane binary; they compile the
policy but never load it into the kernel, so they need no privileges.
Start with --policy observe. Nothing is blocked, everything is recorded, and
after a week you will know which rules you actually want. Then move them to
enforce one at a time.
When a rule fires, the agent is told why, in words, through ActPlane's feedback interface, so it corrects course instead of retrying the same blocked action.
See docs/policies.md.
Actime is built to be useful on a laptop with no root and no container runtime,
and stricter as the environment allows. Nothing below aborts an observe run:
| Missing | What happens |
|---|---|
root / CAP_BPF |
policy and observability planes disabled; backup still runs; doctor explains |
running inside a container without CAP_BPF |
same; doctor warns that this is deployment B without host-side tamper-resistance |
actplane |
policy plane disabled in observe mode; a hard failure in enforce (fail closed) |
agentsight |
observability plane disabled; process-level fallback still records argv, exit, duration |
akeep |
backup plane disabled |
| kernel < 5.10 | policy plane disabled, with your kernel version in the reason |
| a rule needs engine features the host lacks | enforce: the run aborts before the agent starts; observe: the run proceeds with the rule recorded as unenforceable in the manifest and report |
Every run produces a manifest and a report, even when only the fallback ran.
actime doctor tells you exactly which planes your machine supports and how to
turn on the rest.
- Linux. The policy and observability planes need kernel 5.10+ with BTF
(
/sys/kernel/btf/vmlinux); 6.1+ is recommended for the full runtime. The backup plane has no kernel requirement. - Root, or
CAP_BPF/CAP_PERFMONon the engine binaries, for the policy and observability planes only. Everything else runs unprivileged. - A container runtime (Docker/Podman) or
kubectlonly if you wantactime attach --container/--podto resolve those targets. Actime itself never starts a container.
macOS is not supported: the prebuilt binaries are Linux-only, and the eBPF planes need a Linux host kernel.
- Quick start
- Deployment positions: outside the sandbox, inside it, or no sandbox
- Configuration reference: every field of
actime.yaml - Policies: writing and testing your own rules
- Observability and reports: the run record, JSON, export
- Design: the architecture contract
- FAQ
Platform and security teams that already have coding agents inside the building, on machines the company owns — or in sandboxes someone else runs — and need to answer: which agents ran, what did they touch, what did they send where, what did they cost, and what stopped them. Actime is not a hosted sandbox service and does not want your code. It is local-first and sends nothing anywhere.
Actime deliberately does not compete with hosted agent-execution platforms (AWS AgentCore, E2B, Daytona): bring your own environment and Actime layers onto it — from the host where you own one, or inside the sandbox where you do not. It also does not sit at the identity or tool-authorization layer. It owns the layer between: what the agent's actions actually do to a machine, and the record of it.
Issues and pull requests are welcome. See CONTRIBUTING.md and SECURITY.md.
MIT. See LICENSE.