Skip to main content

Runtime Tracing

AgentVisor™ provides runtime tracing to monitor syscall activity within gVisor sandboxes. This gives you deep visibility into agent behavior for security monitoring, debugging, and compliance.

Overview

When agents run inside a gVisor sandbox, every system call they make is intercepted by gVisor's Sentry (userspace kernel). AgentVisor's trace system captures these syscall events, enriches them with context (thread ID, principal, run ID), classifies them by severity, and routes them to configurable output sinks.

Key Benefits

Security Monitoring

  • Detect suspicious file access patterns (reading /etc/passwd, SSH keys, credentials)
  • Alert on process execution (shells, interpreters, security tools)
  • Monitor network connection attempts
  • Track privilege escalation attempts

Debugging

  • Understand what your agent is actually doing at the syscall level
  • Correlate syscalls with specific threads, runs, and principals
  • Identify performance bottlenecks from filesystem or network operations

Compliance & Audit

  • Complete audit trail of agent system interactions
  • Attribution to authenticated principals
  • Structured logs for SIEM integration

Trace Categories

AgentVisor groups syscalls into categories for easier configuration:

CategorySyscallsDescription
file_accessopen, openat, read, write, close, stat, fstat, lstat, accessFile operations
processexecve, execveat, fork, clone, exit, exit_groupProcess lifecycle
networksocket, connect, bind, listen, accept, sendto, recvfromNetwork operations
identitysetuid, setgid, setreuid, setregid, capsetIdentity/privilege changes
filesystemchdir, chroot, mount, umount, pivot_rootFilesystem operations

Severity Classification

Every trace event is assigned a severity level based on the syscall type and its arguments:

SeverityDescriptionExamples
InfoNormal operationsread, write, close, stat, mmap
WarningPotentially concerningsocket, connect, unlink, chmod, kill
AlertRequires immediate attentionexecve, setuid, ptrace, mount, chroot

Static Rules

The base severity comes from the syscall itself:

openat → info (normal file operation)
connect → warning (network activity)
execve → alert (process execution)

Pattern Rules

Pattern rules can upgrade severity based on arguments (never downgrade):

openat("/etc/passwd") → alert (sensitive file)
openat("/tmp/cache.txt") → info (no pattern match)
connect("192.168.1.100:443") → warning (private network)
connect("93.184.216.34:443") → warning (external network)

Built-in Pattern Rules

AgentVisor includes 20 built-in pattern rules for common security concerns. These run unconditionally and only ever affect severity — they do not populate rule_matches or tags on the event. Those two fields are populated only by the optional Rego rules engine described below.

Sensitive Files (→ Alert)

  • System auth: /etc/passwd, /etc/shadow, /etc/sudoers
  • SSH keys: ~/.ssh/*, ssh_host_*_key
  • Cloud credentials: ~/.aws/credentials, ~/.kube/config, ~/.docker/config.json
  • Private keys: *.pem, *.key, *.p12, *.pfx, *.jks
  • Browser data: ~/.mozilla/*/cookies, ~/.chrome/*/logins
  • Crypto wallets: ~/.bitcoin/wallet.dat, ~/.gnupg/secring

Dangerous Executables (execve → Alert)

  • Shells: /bin/bash, /bin/sh, /usr/bin/zsh
  • Interpreters: /usr/bin/python*, /usr/bin/perl, /usr/bin/node
  • Network tools: /usr/bin/curl, /usr/bin/wget, /usr/bin/ssh, /usr/bin/nmap
  • Security tools: /usr/bin/sqlmap, /usr/bin/hydra, /usr/bin/john
  • Package managers: /usr/bin/apt, /usr/bin/pip, /usr/bin/npm
  • Privilege escalation: /usr/bin/sudo, /usr/bin/su, /bin/mount

System Directories (→ Warning)

  • /etc/*, /proc/*, /sys/*

External Network (connect → Warning)

  • Any non-private IP (not 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 127.x.x.x)

Rego Rules Engine (Optional)

Enabling trace.rules.enabled: true layers a Rego policy evaluation on top of the static classifier above. It can upgrade severity, attach rule_matches/ tags to the event, and set an alert flag that floors severity at alert. A built-in default policy is available (trace.rules.use_default_policy: true), or bring your own via policy_files/policy_inline. See Rego Rules Engine in the Security Monitoring Guide for the full default rule ID list and config.

Event Data Model

Each trace event contains:

// Core syscall information
Timestamp time.Time // When the syscall occurred
Syscall string // Syscall name (e.g., "openat")
SyscallNumber int32 // Syscall number
SyscallArgs map[string]any // Syscall arguments

// gVisor context
ContainerID string // gVisor container ID
ProcessID int32 // PID within sandbox
ProcessName string // Process name (e.g., "python3")

// AgentVisor context (injected by guest runtime)
// Empty unless exactly one run is active at syscall time — see the
// attribution caveat under Output Sinks below.
ThreadID string // Conversation thread UUID
Principal string // Authenticated user (JWT subject)
RunID string // Current run ID
AgentID string // Agent/graph identifier

// Derived by classifier
Severity string // "info", "warning", "alert"
Category string // "file_access", "process", etc.
RuleMatches []string // Rego rule IDs matched (empty unless trace.rules.enabled)
Tags []string // Rego-assigned labels (empty unless trace.rules.enabled)

// Optional enriched data
FilePath string // Resolved file path
RemoteAddr string // Network destination (IP:port)
Credentials string // UID/GID context

Output Sinks

Trace events are routed to one or more output sinks:

Log Sink

Outputs events as structured log messages:

{
"time": "2026-02-18T11:18:35Z",
"level": "ERROR",
"msg": "syscall event",
"syscall": "openat",
"category": "file_access",
"severity": "alert",
"thread_id": "550e8400-e29b-41d4-a716-446655440000",
"run_id": "run-12345",
"agent_id": "research-agent",
"principal": "user@example.com",
"process": "python3",
"pid": 1234,
"path": "/etc/passwd"
}

rule_matches is only present when trace.rules.enabled: true (see Rego Rules Engine). The log sink never emits tags at all, even when the Rego rules engine populates them — none of the log, store, webhook, or gRPC sinks carry tags; only the SSE stream does.

Severity is mapped to log levels:

  • Alert → ERROR
  • Warning → WARN
  • Info → INFO (or DEBUG, configurable)

The log sink rate-limits itself (1000 events/sec, burst 100) to prevent log flooding; this is currently fixed and not exposed as config — see Rate Limiting for alternatives at high volume.

Metrics Sink

Exports Prometheus metrics on the standard /metrics endpoint for dashboards and alerting — see Prometheus Metrics for the full metric list and the pre-built Grafana dashboard. The core counter:

MetricTypeLabelsDescription
agentvisor_trace_events_totalCountersyscall, category, severity, agent_id*Total trace events

* agent_id is included by default; there is currently no config knob to disable it for high-cardinality environments. It may still be empty on a given event — see the Attribution Caveat below.

agentvisor_trace_rule_matches_total (labeled rule_name, severity) is a separate metric that only populates when the Rego rules engine is enabled.

OTEL Sink

Exports events as OpenTelemetry spans, correlating syscall activity with distributed traces.

gRPC Sink

Streams events to an external gRPC collector in real time, for consumers that need a push-based feed rather than scraping metrics or tailing logs.

Webhook Sink

Batches events and POSTs them to an HTTP endpoint (e.g. a SIEM ingestion API), with retry and circuit-breaker protection against a failing endpoint.

Store Sink

Persists events to a file-based store on disk for replay and audit-trail queries, with configurable retention and pruning. There is currently no SQLite (or other database) backend for trace events.

Real-Time Streaming (SSE)

Independent of the sinks above, GET /traces/events/stream lets an external client subscribe directly to the event stream over Server-Sent Events, filterable by thread/run/agent/severity/category/syscall. See Real-Time Streaming (SSE) for query parameters and example usage.

Attribution Caveat

thread_id, run_id, agent_id, and principal are populated only when exactly one agent run is active on this AgentVisor instance at the moment the syscall occurs — gVisor reports a container ID, but AgentVisor runs one sandbox per instance, so mapping a syscall to a specific run is ambiguous with zero or more than one concurrent run. In that case these fields are left empty rather than guessing. The same conservatism applies at run boundaries: an event received before the active run started (e.g. a tail event of the previous run still in flight) is left unattributed rather than credited to the wrong run. This applies uniformly across every sink, not just the log sink.

Ring Buffer

Events pass through a ring buffer before reaching sinks. This:

  • Decouples event production from sink processing
  • Prevents blocking if a sink is slow
  • Handles bursts without losing critical events

Buffer behavior when full:

PolicyDescription
oldestDrop oldest events (default)
newestDrop incoming events
blockBlock until space available (may impact agent)

Security Considerations

What Data is Captured

Trace events capture syscall metadata, not payload data:

  • File paths, not file contents
  • Network addresses, not packet payloads
  • Process arguments, not stdin/stdout

Privacy Implications

Consider the sensitivity of traced data:

  • File paths may reveal user activity patterns
  • Network destinations may indicate services accessed
  • Process names and arguments may contain parameters

Use appropriate access controls on log storage and configure log retention policies.

Socket Security

The trace receiver uses a Unix domain socket within the gVisor sandbox, inaccessible from outside the sandbox. Events flow from gVisor's Sentry to the host runtime over the existing secure channel.

Relationship to Other Observability

FeaturePurposeData Source
Runtime TracingSyscall-level visibilitygVisor seccheck
Application LogsAgent business logicPython logging
Distributed TracingRequest flow across servicesOTLP spans
MetricsPerformance and healthPrometheus

Runtime tracing complements these by providing the lowest-level view of what agents actually do at the OS level, independent of what they log or report.

Platform Requirements

note

Runtime tracing is only available with the gvisor sandbox mode. Other sandbox modes (docker, none) do not have access to gVisor's seccheck mechanism. Setting trace.enabled: true under docker or none does not fail startup — it logs a warning and tracing is simply disabled.

Next Steps