Tetragon Agent Normalization
Current Status
src/RuntimeInstrumentation/StellaOps.Agent.Tetragon/ is now a buildable optional Linux Tetragon bridge. It is not the Stella Ops Linux agent and it is not a production runtime-observation publisher. It adapts local Tetragon export output into Agent.Core RuntimeObservation records for the Linux host agent when explicitly enabled.
The folder contains:
StellaOps.Agent.Tetragon.csproj- a normalnet10.0project with warnings as errors.TetragonExportClient- a factory-managed local Tetragon export client usingIHttpClientFactory.TetragonRuntimeObservationSource- optional Agent.CoreIRuntimeObservationSourcethat maps supported local Tetragon event output to normalized runtime observations.Tests/StellaOps.Agent.Tetragon.Tests.csproj- focused offline unit tests for health, NDJSON stream parsing, bounded response failure, optional/disabled behavior, event adaptation, backpressure, malformed events, event-size drops, disconnect handling, and health counters.TASKS.md- historical blockers from the quarantined slice; remaining items should be reconciled or retired by the orchestrator.
The legacy loose TetragonAgentCapability.cs source was removed because it carried local placeholder contracts for IAgentCapability, task models, and health models, direct production DateTimeOffset.UtcNow usage, and unresolved RuntimeInstrumentation bridge dependencies. The replacement bridge uses Agent.Core contracts directly and injects TimeProvider.
Supported Behavior
TetragonExportClient can:
- create HTTP clients through
IHttpClientFactory; - apply a configured absolute local Tetragon export endpoint;
- read
/v1/healthand/v1/policieswith bounded response sizes; - stream
/v1/eventsas NDJSON, preserving raw JSON and exposing only stable top-leveltypeandtimefields.
TetragonRuntimeObservationSource can:
- remain fully disabled unless
RuntimeInstrumentation:LinuxAgent:TetragonBridge:Enabled=true; - connect to the local Tetragon export endpoint through
TetragonExportClient; - map supported process, network, and file event types into Agent.Core
RuntimeObservationvalues; - preserve Tetragon-specific details only as observation attributes, not as Agent.Core types;
- report observed, malformed, dropped, and disconnected event counts through bridge health;
- rely on pull-based
IAsyncEnumerable<RuntimeObservation>behavior for consumer backpressure.
The bridge deliberately does not resolve image digests, publish evidence, sign evidence, or call downstream services. The Linux agent remains responsible for agent identity, local runtime status authority, digest gating, health snapshots, spool state, and future evidence publication.
Stack Trace Capture (Sprint 022 PHASE-C)
The bridge maps Tetragon process_kprobe events that carry user and/or kernel stack-trace arrays into the Agent.Core RuntimeObservation stack-frame payload (Sprint 022 PHASE-B contract).
Mapped Tetragon fields
process_kprobe.process— process identity (PID, binary, pod metadata). The bridge hoists this object to populateRuntimeObservation.ProcessId,RuntimeObservation.ProcessName, andRuntimeObservation.ContainerId.process_kprobe.function_name— kprobe hook name. Drives theRuntimeObservationKindmapping (see “Kind derivation” below) and is surfaced unchanged as thefunction.nameobservation attribute.process_kprobe.stack_trace_user— list of user-space frames. Each frame must carry anaddressfield (hex string, optionally0x-prefixed, or decimal);offset,module, andsymbolare optional. The bridge populatesRuntimeObservation.UserStackwith parsed frames.process_kprobe.stack_trace_kernel— list of kernel-space frames. Same shape as the user list. The bridge populatesRuntimeObservation.KernelStack.
Both flattened ({type: "process_kprobe", process: {...}, ...}) and canonical-Tetragon-nested ({process_kprobe: {process: {...}, ...}}) JSON shapes are accepted. The flattened shape continues to be used by some older Tetragon exporter configurations and by the bridge’s unit-test fixtures; the nested shape matches Tetragon’s upstream protobuf JSON.
Frame parsing rules
addressis parsed asulong. Hex strings with the0xprefix, bare hex strings, and decimal strings are all accepted; integer JSON numbers are also accepted. Frames whoseaddresscannot be parsed are silently dropped from the resulting list — the observation is still emitted with the remaining frames.- Lists are capped at 256 frames per (user, kernel) list. Overflow frames are dropped; the truncation count is surfaced via:
- the per-observation attribute
stack.truncated(decimal string), and - the bridge
TetragonBridgeHealthSnapshot.TruncatedStackFramescounter (Details keytruncatedStackFrames).
- the per-observation attribute
- The combined stack-frame payload is additionally bounded at 16 KB by
AgentCoreValidation.MaxStackPayloadBytes. Bridge-side truncation aims to keep observations within this budget before they reach the digest-gated publication path.
StackCaptureMode derivation
The bridge sets RuntimeObservation.StackCaptureMode from the resolved- symbol coverage of all frames across both stack lists:
| Frame symbol coverage | StackCaptureMode wire value |
|---|---|
Zero frames present (no stack_trace_* arrays attached) | null (field omitted) |
Frames present, no frame has a symbol | addresses-only |
Frames present, some have symbol, some do not | partial-symbols |
Frames present, all have symbol | full-symbols |
The none wire value is reserved for producers that explicitly attest “no stack frames will ever attach”; the bridge does not emit it (a kprobe without stack arrays simply leaves StackCaptureMode null and both stack lists null, which is wire-compatible with the pre-PHASE-B contract).
Symbol resolution is best-effort and remains the responsibility of the Stella Ops Linux agent’s symbol resolver (Sprint 022 PHASE-D). The bridge ships whatever the Tetragon export endpoint provides. A future PHASE-D pass may upgrade an observation from addresses-only to partial-symbols or full-symbols by resolving frames against /proc/<pid>/maps and the matching ELF symbol tables; the bridge itself never performs ELF lookups.
Kind derivation for kprobe events
The bridge maps the kprobe function_name to a RuntimeObservationKind using a small allow-list keyed off the default Stella Ops TracingPolicy:
Tetragon function_name (case-insensitive) | RuntimeObservationKind |
|---|---|
sys_execve, __x64_sys_execve, do_execve, do_execveat_common | ProcessStarted |
tcp_connect, __sys_connect, inet_csk_accept | NetworkConnection |
do_filp_open, do_sys_openat2, sys_openat, __x64_sys_openat | FileAccess |
sys_exit, sys_exit_group, do_exit, __x64_sys_exit | ProcessExited |
anything else (or function_name absent) | ProcessStarted (default) |
Default TracingPolicy
A narrow-scope tracing policy ships at devops/agents-targets/tetragon/tracing-policy-stellaops-default.yaml. It enables user + kernel stack-trace collection on sys_execve, tcp_connect, and do_filp_open. Operators may extend this policy, but broader hook surfaces (e.g. high-frequency vfs_read/vfs_write) will require commensurate tuning of the digest gate, spool, and publication pipeline on the consuming Stella Ops Linux agent.
Remaining Blockers
The olderResolved (Sprint 20260513_023, commit TBD): the five dead Tetragon-specific source files (StellaOps.RuntimeInstrumentation.Tetragonproject shape still contains historical Tetragon-specific runtime models and Kubernetes-era source code; new bridge work must preferStellaOps.Agent.Tetragonand Agent.Core contracts.TetragonEventAdapter.cs,TetragonFrameCanonicalizer.cs,TetragonHotSymbolBridge.cs,TetragonPrivacyFilter.cs,TetragonWitnessBridge.cs) and the five orphaned tests underStellaOps.RuntimeInstrumentation.Tetragon.Tests/were removed — none were compiled by any.csproj. The canonical Tetragon bridge is nowStellaOps.Agent.Tetragon. The folderStellaOps.RuntimeInstrumentation.Tetragon/retains only the six load-bearing Kubernetes-era runtime-status-source files (ContainerImageDigestResolver.cs,RuntimeContainerImageStatusCommandSource.cs,RuntimeContainerImageStatusKubernetesApiSource.cs,RuntimeContainerImageStatusKubernetesWatchSource.cs,RuntimeContainerImageStatusSnapshots.cs,RuntimeContainerImageStatusHosting.cs) that are linked intoStellaOps.RuntimeInstrumentation.Workerand its tests; the folder name is a historical misnomer and is documented as such by theREADME.mdin that folder.- Optional Linux integration testing against a real Tetragon/eBPF-enabled runner remains future CI work. Mandatory unit/fixture tests do not require Tetragon to be installed.
- Digest-gated evidence publication is owned by the Linux host agent through Agent.Core
IRuntimeEvidencePublisher; the Tetragon bridge must continue to hand observations to the Linux agent only.
