Repository navigation
Integrations Falco
Experimental: this works and is tested, but may change and gets less hardening than the stable core. Linux only. Tested: alert lines shaped as Falco's source writes them, imported into a real signer; not yet run on a live Falco (#312).
Falco watches system calls from the kernel and raises an alert when one
matches a rule. tracekit sensor import reads Falco's JSON alerts of the rules below and sends each one of an agent's
process to the v2 signer, which signs it into the agent's run as an effect.observed record, the same way it does
Tetragon's events. It works whatever sandbox the agent runs in, or none.
| Falco | Tracekit | |
|---|---|---|
| What it does | Matches system calls against rules, and writes an alert for each match | Signs each alert of a tracekit rule into the run of the agent that caused it, joined to the tool call when the process names one, and signs a gap for the drops Falco reports |
| Where | A DaemonSet (or a host service) with its kernel driver | The import next to Falco, the signer outside the agent |
| What a third party can check later | Nothing signed: alerts in a file or another output | A signed, hash-chained bundle, verified offline |
1. Falco (/etc/falco/config.d/tracekit.yaml): JSON alerts with their fields and tags, to a file, and every
drop reported:
json_output: true
json_include_output_fields_property: true
json_include_tags_property: true
priority: debug # the drop alert is a debug-priority rule
file_output:
enabled: true
keep_alive: true
filename: /var/log/falco/tracekit.json
syscall_event_drops:
threshold: 0 # any drop, not only above 10 % of a second's events
actions: [log, alert]
rate: 1 # a report every second a drop happens, not one every 30 s
max_burst: 10Or program_output with keep_alive: true and program: tracekit sensor import --config /etc/tracekit/sensor.yaml,
which reads stdin. Container and Kubernetes fields come from Falco's container plugin (on in its Linux packages).
2. Rules (/etc/falco/rules.d/tracekit.yaml). The import records only alerts of rules tagged tracekit, from the
fields their output names, so each rule's output names all of them:
- macro: tracekit_agent
condition: k8s.ns.name = agents # your agents: a namespace, a container name, a uid
- rule: Tracekit agent exec
desc: A program an agent started
condition: evt.type in (execve, execveat) and evt.dir = < and evt.arg.res = 0 and tracekit_agent
output: >
agent exec type=%evt.type pid=%proc.pid exe=%proc.exepath cmdline=%proc.cmdline uid=%user.uid
container=%container.id ns=%k8s.ns.name pod=%k8s.pod.name call=%proc.env[CODEX_TOOL_CALL_ID]
priority: INFORMATIONAL
tags: [tracekit]
- rule: Tracekit agent connect
desc: An agent opened a network connection
condition: >
evt.type = connect and evt.dir = < and fd.type in (ipv4, ipv6) and (evt.rawres >= 0 or evt.res = EINPROGRESS)
and tracekit_agent
output: >
agent connect type=%evt.type pid=%proc.pid exe=%proc.exepath to=%fd.sip port=%fd.sport uid=%user.uid
container=%container.id ns=%k8s.ns.name pod=%k8s.pod.name call=%proc.env[CODEX_TOOL_CALL_ID]
priority: INFORMATIONAL
tags: [tracekit]
- rule: Tracekit agent write outside the workspace
desc: An agent opened a file outside its workspace for writing
condition: >
evt.type in (open, openat, openat2) and evt.dir = < and evt.is_open_write = true and fd.num >= 0 and fd.type = file
and not fd.name startswith /workspace/ and not fd.name startswith /tmp/ and tracekit_agent
output: >
agent write type=%evt.type pid=%proc.pid exe=%proc.exepath file=%fd.name uid=%user.uid
container=%container.id ns=%k8s.ns.name pod=%k8s.pod.name call=%proc.env[CODEX_TOOL_CALL_ID]
priority: INFORMATIONAL
tags: [tracekit]Put your own workspace path in the third rule. Each rule matches a call that succeeded (an exec that ran, a connect under way, an open that returned a descriptor), so an attempt the kernel refused isn't recorded as an effect.
3. The signer gives each node's import its own identity and the observe_effect grant, as for
Tetragon: one identity is one process.
4. The import, on each node (sensor.yaml):
sensor: falco
signer: https://signer.internal:8443
runs:
- match: {namespace: agents, pod: "coder-*"} # globs over namespace, pod, container (id), uid
caller: k8s_sa:system:serviceaccount:agents:codertracekit sensor import --config sensor.yaml --follow /var/log/falco/tracekit.jsonFalco's container.id is the short (12 character) id.
One effect.observed per alert of a tracekit rule (sensor: falco, format 1.4,
format v2), attributed as for Tetragon:
evt.type |
kind |
Fields |
|---|---|---|
execve, execveat
|
exec |
binary (proc.exepath), pid, args_commitment (proc.cmdline, committed to, never stored) |
connect |
connect |
host (fd.sip), port (fd.sport) |
open, openat, openat2
|
file |
path (fd.name) |
Falco has no exit events in these rules, and no process id across executions (no exec_id). Alerts of other rules
aren't recorded. proc.env[CODEX_TOOL_CALL_ID] joins a record to the Codex tool call that started it
(Tetragon says how, and what the join is worth).
tracekit analyze --v2 checks the records against the run's calls as for
Tetragon (TK-X206, TK-X207), with one difference: Falco names no parent
process, so a process a call left running and what it starts after that call's window are TK-X206 findings, and a
process's connections and writes are joined to it by pid and time.
Falco numbers no alerts. It reports drops between its kernel driver and itself as the alert
Falco internal: syscall event drop, with that second's counts (n_drops, n_evts): the import sends it as lost,
a signed capture.gap{observer_lost} in each run it covers, after which their matrix says processes not observed
(Tetragon says how). With Falco's defaults it reports a second only when more than 10 % of its
events were dropped, and at most one second in 30: the settings above report every second with a drop. Alerts Falco
drops from a full output queue (outputs_queue.capacity) show only in its log and its metric
falcosecurity_falco_outputs_queue_num_drops_total: alert on it in your monitoring. A Falco restart writes no alert,
so what happened while it was down is missing with no gap: alert on its restarts too.
-
Sees: the alerts of the
tracekitrules for the agents' processes, as Falco wrote them, and the drops Falco reports. -
Doesn't see: system calls the rules don't match, alerts with a field the rule's output doesn't name (the import
can't attribute them, so they're skipped, or counted as lost when the process is an agent's but the effect can't be
built), a connect to a unix socket (
fd.sipnull: skipped and counted on stderr, no loss), and anything before the import's first heartbeat. - Doesn't check: that Falco's alerts are true. The records are the import's assertion of what Falco said, and a root user on the node can change Falco, its output or the import.
Limits lists these with what to do. A bundle with these records needs verifier
1.4.0 or later; an older one reports it UNVERIFIABLE (needs tracekit >= 1.4.0). Verify it with
uvx --from "tracekit-ai>=1.4.0" tracekit verify run.tkb --trust trust.json,
npx -y @cygnuxlabs/tracekit@latest verify run.tkb --trust trust.json, or the browser page
(verdicts).
Generated from docs/ at v1.4.1. Edit the docs in the repository, not here.
Get started
- Quickstart: the v2 signer
- Quickstarts
- Quickstart: Claude Agent SDK
- Quickstart: a custom agent
- Quickstart: LangChain and LangGraph
- Quickstart: MCP client
- Quickstart: OpenAI Agents SDK
- Coding agents other than Claude Code
- tracekit doctor
- Walkthrough: Tracekit end to end
How it works
- How Tracekit works
- Overview
- The life of a tool call
- The evidence format
- Verification and assurance
- Witnesses and monitoring
- Policy
- Approvals
- Detection and containment
- Capture and completeness
- Custody
- Provenance and tracekit why
- Deployment and isolation
- Storage, durability and performance
- Integrations
- Security model
- Architecture
- tracekit why: architecture
Integrations
- Integrations
- Adapters
- OpenTelemetry
- Remote clients
- Kubernetes agent-sandbox
- agentgateway
- agentsh and Tracekit
- Browser Use
- Claude Agent SDK
- Claude Code's sandbox
- Codex's sandbox
- CrewAI
- Docker MCP Gateway
- E2B
- Falco
- Gemini CLI's sandbox
- Google ADK
- Haystack
- LangChain v1
- LiteLLM
- LlamaIndex
- MCP client
- microsandbox
- Microsoft Agent Framework
- OpenAI Agents SDK
- NVIDIA OpenShell
- Pydantic AI
- sandbox-runtime's proxy on its own
- Strands Agents
- Tetragon
- Vercel AI SDK
- Wassette
Policy and approvals
- Policy reference
- Approvals
- Findings
- Reading the model's reasoning
- Incidents and containment
- Webhooks
Deploy and operate
- Deploying the signer
- The signer as a container
- The signer on Kubernetes
- The compose stack
- Identity
- Tool executor
- MCP gateway
- LLM gateway
- Egress observation
- Witnesses
- Log monitor
- Record-key issuer
- Signer observability
- Viewer
- tracekit why: causal investigation and replay
- Migrating
- Platforms
Verify the evidence
- Reading a v2 verify report
- Evidence format v2
- Auditor guide
- Sample evidence bundle
- Signing
- What Tracekit guarantees
Security and privacy
- Threat model: the v2 signer
- Threat model: the v1 laptop signer
- HTTP security checklist
- Threat-model review packet
- Privacy
- Known limits and trade-offs
- What's stable
Compliance
- Compliance mapping
- EU AI Act
- ISO/IEC 42001
- NIST AI RMF and the Generative AI Profile
- OWASP Top 10 lists for LLM and agentic applications
Evaluation
Demos
- Demos
- Agent approvers within bounds
- Completeness and tamper evidence
- Detection and containment
- Network coverage: an egress observer
- Guardrails: allow, deny, or ask a person
- MCP tools, gated and recorded
- Prompt injection held by provenance
- Why: which input caused the action
Help