When an OpenClaw Agent Breaks Its Declaration, eBPF Blocks the Syscall at the Kernel
There's a peculiar unease that sets in after deploying an AI agent to production. The code itself runs fine, but you can't be 100% sure the agent will only behave the way you intend. When I first ran a multi-agent pipeline, I found myself wondering, "Could this agent touch my SSH keys?" — and it's becoming increasingly clear that worry isn't unfounded. And I wasn't alone in feeling it. The back-to-back arrival of the AgentSight paper, the open-sourcing of Microsoft's Agent Governance Toolkit, and the publication of the OWASP Agentic AI Top 10 between 2025 and 2026 signals that the entire industry has started asking the same question.
OpenClaw is an open-source AI agent framework. The OpenClaw runtime governance ecosystem — including AccuKnox's KnoxClaw — is an architecture that delivers a kernel-level answer to precisely that unease. When an LLM instructs an agent to "open this file," eBPF intercepts the actual syscalls the agent generates, cross-references them against policy in real time, and if the agent steps out of bounds, blocks the syscall outright or terminates the process. By reading this article, you'll gain a concrete understanding of why eBPF is a game changer for AI agent security and how to apply it in practice within an OpenClaw environment.
One thing to mention upfront: the primary audience for this article is backend and infrastructure engineers running container-based agents. If Kubernetes sidecar patterns and the concept of syscalls are unfamiliar territory, the code examples in the latter half may feel a bit foreign — a brief guide to non-Kubernetes paths is included in the closing section for those readers.
Core Concepts
The 'Semantic Gap' Between LLM Intent and Syscalls
If you had to distill the core problem of agent security into a single phrase, it would be the semantic gap. An LLM generates a high-level intent like "organize my emails," and agent code translates that intent into actual system calls. But when that translation process is exposed to prompt injection or supply chain tampering, the agent can end up reading ~/.ssh/id_rsa while still believing it's "organizing emails."
Traditional security tools (WAFs, API gateways) don't see this layer. The agent framework's internal logic has no way of knowing whether it has been tampered with. The only vantage point outside the agent code from which all behavior can be observed is the kernel's syscall layer.
eBPF (extended Berkeley Packet Filter): A Linux technology that allows you to programmatically observe and control kernel-internal events (file I/O, network connections, process execution, etc.) without recompiling kernel code or loading a kernel module. Because it operates entirely independently of agent code, no matter how cleverly an agent attempts to circumvent it, there is no escaping the syscall layer.
Skill Manifest — A Cryptographic Contract for Agent Behavior
The heart of the OpenClaw governance model is a permission declaration format called clawmanifest.json. Before deploying an agent plugin (Skill), developers must enumerate in this file every resource that Skill is allowed to access.
{
"skill_id": "email-cleaner-v1",
"version": "1.2.0",
"permissions": {
"filesystem": {
"read": ["~/Maildir/**"],
"write": ["~/Maildir/.trash/**"]
},
"network": {
"egress": ["imap.example.com:993", "smtp.example.com:587"]
},
"exec": []
},
"hashes": {
"main.py": "sha256:a3f2c1d9e8b7...",
"utils/parser.py": "sha256:f1e2d3c4b5a6..."
},
"signature": {
"algorithm": "Ed25519",
"value": "3045022100...",
"signed_by": "dev@example.com"
}
}The hashes field is used to guarantee file integrity at deployment time. Detecting whether code has been dynamically tampered with during runtime requires a separate inotify-based file watcher or an additional eBPF layer — that responsibility falls to solutions like KnoxClaw. Because the signature field signs the entire Manifest with an Ed25519 asymmetric key, if someone secretly modifies the permission scope after deployment, it is immediately detected at the signature verification step. That's where supply chain attacks get stopped.
Key Insight: Manifest signing goes beyond simple access control — it's a supply chain integrity guarantee. It cryptographically proves that "this agent code has not been tampered with since the time of deployment."
Real-Time Policy Evaluation Flow of the eBPF Hook
When I first drew this diagram, there was one part that confused me: the phrasing "send SIGKILL before the syscall completes." That's technically imprecise. The actual mechanism splits into two paths.
First: An eBPF LSM (Linux Security Module) hook blocks the syscall itself. When the kernel asks the LSM whether to permit a file access, if the eBPF program returns an error code like -EPERM, the syscall terminates immediately with an error without executing. The process remains alive, but the operation is blocked.
Second: Calling the bpf_send_signal(9) helper schedules a SIGKILL signal asynchronously. The signal is delivered shortly after, but this is a different flow from "blocking before the syscall executes." Tetragon's Sigkill action uses this approach.
Agent Process
│
│ syscall: open("/home/user/.ssh/id_rsa", O_RDONLY)
▼
┌──────────────────────────────────────────────────┐
│ eBPF LSM hook (inside kernel) │
│ │
│ 1. Lookup Process ID → Skill ID mapping │
│ 2. Cross-reference clawmanifest.json permissions│
│ 3. "/home/user/.ssh/id_rsa" ∉ allowed list │
│ │
│ → Method A: return -EPERM → syscall blocked │
│ → Method B: bpf_send_signal(9) → SIGKILL queued │
└──────────────────────────────────────────────────┘
│
▼
Audit log entry:
timestamp: 2026-05-06T14:23:01.003Z
pid: 18432
skill_id: email-cleaner-v1
action: open
path: /home/user/.ssh/id_rsa
verdict: BLOCK
evidence_hash: sha256:7c3f...There are three possible verdicts: allow, block, and require_approval. On block, a signed evidence artifact is automatically generated and forwarded to SIEM and compliance systems.
LSM (Linux Security Module): The kernel's security policy enforcement interface. AppArmor and SELinux are canonical LSM implementations; eBPF enables writing custom LSM policies via the
BPF_PROG_TYPE_LSMtype. KubeArmor leverages both traditional LSMs and eBPF to control not just file access but a broader range of system calls including process execution and network socket connections.
AgentSight: Causal Correlation of LLM Traffic and Syscalls
Honestly, at first I thought "isn't syscall-level monitoring enough on its own?" Then I read the AgentSight paper (arXiv:2508.02736) and changed my mind.
Watching syscalls alone tells you what was done, but makes it difficult to understand why it was done. AgentSight goes one step further: it uses eBPF uprobes to intercept TLS-encrypted LLM API traffic (the SSL_read/SSL_write functions), then connects the agent's intent (LLM response) and actions (syscalls) in a causal graph.
A quick terminology note: a kprobe hooks into a kernel function entry point, while a uprobe hooks into a user-space function (like OpenSSL's SSL_read). The reason uprobes are needed to intercept TLS traffic is precisely this distinction — the decryption happens in user space.
# AgentSight causal correlation example (conceptual code — may differ from actual API)
# Maps LLM response stream and syscall events by timeline
correlation_engine.correlate(
llm_event={
"timestamp": "2026-05-06T14:23:00.991Z",
"agent_id": "email-cleaner",
"llm_output": "I'll clean up old emails in ~/Maildir..."
},
syscall_events=[
{
"ts": "2026-05-06T14:23:01.003Z",
"call": "open",
"path": "/home/user/.ssh/id_rsa"
},
]
)
# → Detect semantic mismatch between LLM response and actual syscall
# → Anomaly: LLM declared Maildir access, agent attempted SSH key accessThis approach, published by the UC Berkeley and eunomia-bpf teams, operates with under 3% CPU and memory overhead and requires no code changes. In experiments targeting 6 Claude sub-agents, it reportedly captured 3,153 events and automatically identified prompt injection attacks and cost-wasting reasoning loops.
Practical Application
Example 1: Kubernetes Sidecar Deployment with KnoxClaw
The fastest pattern to apply in production is the Kubernetes sidecar. AccuKnox's KnoxClaw auto-generates KubeArmor + eBPF policies from a single knoxclaw.yaml file.
The first problem I ran into when trying this configuration was permissions. Loading an eBPF program into the kernel requires elevated privileges somewhere — the key question is where to grant them.
# knoxclaw.yaml
apiVersion: security.knoxclaw.io/v1
kind: AgentPolicy
metadata:
name: email-cleaner-policy
namespace: ai-agents
spec:
selector:
matchLabels:
app: email-cleaner-agent
manifest: "./clawmanifest.json"
enforcement:
mode: enforce # enforce | audit | permissive
onViolation: SIGKILL
auditLog:
enabled: true
destination: "accuknox-spm"
filesystem:
allowedPaths:
- path: "/home/*/Maildir/**"
ops: [read, write]
network:
egress:
- cidr: "0.0.0.0/0"
ports: [993, 587]
protocol: TCP
denyAll: true # Any undeclared destination is blocked entirely# agent-deployment.yaml (sidecar pattern)
apiVersion: apps/v1
kind: Deployment
metadata:
name: email-cleaner-agent
spec:
template:
spec:
initContainers:
- name: knoxclaw-init
image: accuknox/knoxclaw:latest
securityContext:
privileged: true # Unavoidable for eBPF kernel load — reason it's isolated from the agent container
volumeMounts:
- name: ebpf-fs
mountPath: /sys/fs/bpf
containers:
- name: agent
image: myorg/email-cleaner:1.2.0
# Agent container runs with least privilege, no privileged flag
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
- name: knoxclaw-enforcer
image: accuknox/knoxclaw-enforcer:latest
securityContext:
capabilities:
add: [SYS_ADMIN, NET_ADMIN]That's exactly why privileged: true appears in knoxclaw-init. Pinning the eBPF program to /sys/fs/bpf and installing kernel hooks requires elevated kernel privileges. The important thing is that these privileges are scoped to the init container only — the agent container that actually runs the code carries no capabilities at all via drop: ["ALL"]. It is by design that the governance tooling holds higher privileges than the agent.
| Component | Role |
|---|---|
knoxclaw-init |
Init container that loads the eBPF program into the kernel (exits after completion) |
knoxclaw-enforcer |
Runtime policy enforcement sidecar, shares the network namespace with the agent pod |
agent |
Runs with least privilege; the eBPF enforcer monitors it externally |
denyAll: true |
Whitelist-based network policy; any undeclared destination is automatically blocked |
Example 2: CI/CD Compliance Automation with Microsoft Agent Governance Toolkit
Microsoft AGT automatically maps agent execution traces to HIPAA, SOC2, and EU AI Act requirements and computes a governance grade (A–F). Integrating it into a CI/CD pipeline lets you automatically block deployments on policy violations.
The code below is pseudocode illustrating the AGT concept. It may differ from the actual AGT CLI and REST API-based interface, so refer to the latest API documentation on the official GitHub when adopting it.
# pipeline_compliance_check.py (conceptual code — may differ from actual AGT API)
import asyncio
async def check_agent_compliance(execution_trace: dict) -> bool:
# In practice, AGT is invoked via CLI or REST API
# This is pseudocode to illustrate the conceptual flow
result = await agt_client.evaluate(
trace=execution_trace,
standards=["hipaa", "soc2", "eu-ai-act"],
enforcement_mode="strict"
)
print(f"Governance grade: {result.grade}") # A ~ F
print(f"Violations: {result.violations}")
if result.grade in ["D", "F"]:
raise Exception(
f"Deployment blocked: governance grade {result.grade}. "
f"Violations: {', '.join(result.violations)}"
)
return True
asyncio.run(check_agent_compliance(trace))# .github/workflows/deploy.yml
- name: Agent Compliance Check
run: |
agt check \
--trace-file ./agent-execution-trace.json \
--standards hipaa,soc2,eu-ai-act \
--fail-on D,F
env:
AGT_POLICY_STRICTNESS: highThe advantage of this approach is that sub-millisecond policy decisions (p99 < 0.1 ms) introduce virtually no additional latency to the overall deployment pipeline. Python, TypeScript, Rust, Go, and .NET are all supported, so there are no language mismatch issues with existing pipelines.
Example 3: Detection-Blocking Redundancy with Falco + Tetragon
Combining detection-oriented Falco with blocking-oriented Tetragon enables finer-grained control. The division of labor — Tetragon blocks while Falco provides alerts and contextual information — works well.
The matchBinaries path in the Tetragon policy below (/usr/bin/python3) may vary per container image. Verify the actual path in your image with which python3 (e.g., python3.11, /usr/local/bin/python3) and adjust accordingly.
# tetragon-tracing-policy.yaml (handles blocking)
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: agent-file-access-policy
spec:
kprobes:
- call: "security_file_open"
syscall: false
return: false
args:
- index: 0
type: "file"
selectors:
- matchBinaries:
- operator: "In"
# Verify python3 path in actual container image
values: ["/usr/bin/python3"]
matchArgs:
- index: 0
operator: "Prefix"
values: ["/home/"]
matchActions:
- action: Sigkill # Terminate process for any path outside the allow list# falco-rules.yaml (handles detection and alerting)
- rule: AI Agent Suspicious File Access
desc: AI agent attempted access to an undeclared sensitive path
condition: >
open_read and
proc.name in (agent_binaries) and
not fd.name pmatch (allowed_agent_paths)
output: >
Anomalous file access detected from agent
(user=%user.name pid=%proc.pid path=%fd.name cmd=%proc.cmdline)
priority: CRITICAL
tags: [ai-agent, data-exfiltration]Falco alone can only detect, not block — but combined with Tetragon, you get a dual defense line where "Falco alerts first, Tetragon blocks." When first setting up this combination, I was worried about duplicate event handling, but since the two tools operate on independent pipelines, it wasn't an issue in practice.
Pros and Cons Analysis
Advantages
| Item | Details |
|---|---|
| Zero code changes | Observe and block from outside without modifying agent code or framework |
| Sub-millisecond latency | Kernel-level intercept delivers p99 < 0.1 ms policy decisions |
| Low overhead | Under 3% CPU and memory overhead per AgentSight benchmarks |
| Cryptographic trust | Ed25519 signatures detect supply chain tampering; tamper-proof after deployment |
| Automated audit trail | Signed artifact auto-generated on block; immediate compliance integration |
| Framework-agnostic | Applicable to any agent framework: LangChain, OpenClaw, AutoGen, etc. |
Disadvantages and Caveats
| Item | Details | Mitigation |
|---|---|---|
| Non-deterministic agent behavior | Access paths vary per prompt, creating a dilemma of overly strict or overly loose whitelists | Run require_approval mode — see separate explanation below |
| TLS traffic complexity | LLM API communication is TLS-encrypted, preventing simple network inspection | Intercept at the application layer using SSL_read/SSL_write uprobes as AgentSight does |
| Manifest maintenance burden | Re-signing required on every Skill addition or change | Integrate automated signing step into CI/CD pipeline; automate Manifest drift detection |
| Kernel version dependency | Some eBPF features require Linux 5.8+ | Fall back to Falco's kernel module mode on older kernel environments |
| Semantic gap unresolved | Syscall-level visibility cannot directly capture high-level agent intent | Supplement with AgentSight's LLM traffic ↔ syscall causal correlation analysis |
To elaborate on require_approval mode: the first time I turned on enforce mode, the agent kept getting SIGKILLed because it was touching unexpected paths. It turned out the agent's pattern for writing temporary cache files varied between runs. require_approval mode queues these "gray area" requests in an operator approval queue instead of blocking them immediately — it's enormously useful during the initial period when you're learning the patterns. The most stable approach in practice was to analyze two to four weeks of accumulated approval patterns, refine the Manifest, and then switch to enforce mode.
The Most Common Mistakes in Practice
-
Declaring the Manifest too broadly — When initial setup is tedious, it's tempting to use wildcards like
"filesystem": {"read": ["/**"]}, but this defeats the purpose of governance entirely. Declare only the paths each Skill actually uses, and use strace-based auto-analysis tooling at the CI stage to generate a least-privilege Manifest draft. -
Failing to transition from audit mode to enforce mode — Starting with
mode: auditis the right approach, but it's common to keep saying "let's watch a bit longer" even after sufficient data has accumulated, rendering the audit logs useless. It's effective to codify a team policy mandating an enforce transition after a 2–4 week audit period. -
Leaving SYS_ADMIN on the agent container itself — A common mistake is granting the privileges needed by the eBPF enforcer sidecar to the agent container directly. As shown in the example code, privileges must be isolated to the init container and sidecar only — the agent container should always run with
drop: ["ALL"], as the design intends.
Closing Thoughts
From the moment an AI agent touches real system resources, eBPF-based runtime governance — observing behavior at the kernel level from outside the agent code — is no longer an optional security enhancement, but a mandatory layer of production infrastructure.
That unease I mentioned at the start of this article — I think it's a little easier to let go of now. Once you have a structure in place where the kernel prevents the agent from touching ~/.ssh/id_rsa, regardless of what the LLM instructs, control at the syscall boundary stays on our side.
Three steps you can start with right now:
-
You can start by observing your current agent behavior with AgentSight. No changes to agent code required whatsoever. Run
git clone https://github.com/eunomia-bpf/agentsight && cd agentsight && docker compose upto see an audit log of the actual syscalls your agent generates in a local environment. A Kubernetes environment is not required. -
Based on your observations, you can draft a
clawmanifest.json. Using the actual file access paths and network destinations collected by AgentSight, write a least-privilege Manifest and walk through the process of signing it with aned25519key. Getting a feel for it locally before connecting the signing pipeline to CI will make subsequent work considerably easier. -
If you're on Kubernetes, you can deploy a single Cilium Tetragon
TracingPolicyinmode: audit. Runkubectl apply -f https://raw.githubusercontent.com/cilium/tetragon/main/examples/tracingpolicy/file-monitoring-filtered.yamlto start audit-mode monitoring immediately, and it's recommended to agree with your team in advance on a schedule to transition toenforcemode after accumulating 2–4 weeks of data. For non-Kubernetes environments, standalone Falco has a much lower barrier to entry.
References
- Announcing KnoxClaw - Kernel Sandboxing For OpenClaw Instances | AccuKnox
- AgentSight: System-Level Observability for AI Agents Using eBPF | arXiv:2508.02736
- AgentSight GitHub Repository | eunomia-bpf
- AgentSight: Keeping Your AI Agents Under Control with eBPF | eunomia.dev
- Introducing the Agent Governance Toolkit | Microsoft Open Source Blog
- GitHub: microsoft/agent-governance-toolkit
- eBPF for AI Agent Enforcement: What Kernel-Level Security Catches (and What It Misses) | ARMO
- Tetragon - eBPF-based Security Observability and Runtime Enforcement | Cilium
- OpenClaw Is a Preview of Why Governance Matters More Than Ever | CloudBees
- Taming OpenClaw: Security Analysis | arXiv:2603.11619
- eBPF Foundation 2025 Year in Review | eBPF Foundation