Launched this week
Heron
Wireshark for AI Agents: passive eBPF observability
115 followers
Wireshark for AI Agents: passive eBPF observability
115 followers
Heron is a passive network analyzer that reconstructs what your AI agents are actually doing. Zero SDKs. Zero proxy. Hook eBPF to see TLS-encrypted LLM calls and identify which agent process made them.









Heron
Hey PH! 👋 I'm sharing Heron today on behalf of the engineering team at Netis.
We built Heron because our team got tired of our AI agent loops looking like 200 OK in the logs while the actual agent was stuck replaying the same tool call for 47 seconds straight.
What Heron does: Heron is a passive analyzer that reconstructs what your AI agents are actually doing — from the network traffic itself. No SDK, no proxy, nothing in the request path. It captures LLM traffic (OpenAI, Anthropic, Gemini, vLLM, SGLang, Ollama…), parses the wire protocol, and stitches multi-call interactions into agent turns you can actually debug.
What's new in v0.7.0 (just shipped): 🌌 OpenTelemetry Native — We completely aligned our architecture with OTel standards. Agent turns are now traces, and LLM calls are now spans.
🔥 eBPF capture discoverability — hook SSL_read/SSL_write to see TLS-encrypted agent traffic as plaintext, with process attribution (which agent process made which call). No proxy, no TLS terminator.
📊 We discovered that ~73% of Claude Code's Opus turns in our production capture were hidden security-monitor sidecars — Heron now filters them automatically so you see real agent work, not housekeeping noise.
🧬 One-click SFT trajectory export — turn your production agent traffic into fine-tuning training data without re-running anything.
Built in Rust, ships as a single binary with the React console embedded. Apache-2.0. Would love your feedback!
🦩 Try it: curl -fsSL https://raw.githubusercontent.com/Netis/heron/main/install.sh | sh ⭐ GitHub: https://github.com/Netis/heron
The eBPF plaintext reconstruction is impressive. The flip side is you now hold a store of decrypted prompts and responses, which in production often carry PII, secrets, or customer data, plus a one click path to turn that into training data. How do you handle access control and redaction on the captured payloads, so the observability layer doesn't quietly become your most sensitive data store?
Heron
@angelika_dev You’re absolutely right — this is the core security trade-off of passive evidence.
Heron can reconstruct prompts and responses, which is what makes it useful for debugging, audit, agent-turn reconstruction, and trajectory export. But that also means the Heron store must be treated as highly sensitive infrastructure, not as ordinary logs.
Our intended production model is private/self-hosted deployment inside the same security boundary as the LLM gateway or inference stack. Today that means keeping the API/console private, using retention policies and body caps, and being deliberate about who can access raw payloads or exports.
But that is not the full end-state. For serious production use, this needs redaction before storage, metadata-only capture modes, RBAC for raw payload access, explicit permissions for SFT/trajectory export, and audit logs for viewing/exporting sensitive traces.
The one-click export path is powerful, but it should be governed like access to raw production data. Our goal is for Heron to be a controlled evidence layer — not an ungoverned warehouse of decrypted prompts and customer data.
The eBPF SSL_read/SSL_write uprobe approach to read TLS-encrypted agent traffic as plaintext is the clever part here, since it sidesteps the SDK and proxy tax entirely. Before pointing it at production I'd want to know where the reconstructed plaintext (prompts/completions that can carry secrets or PII) actually lives, does it stay on the local host as part of the single binary, or get shipped off-box anywhere? And since uprobes hook a known libssl, how does it handle agents on statically-linked Go (crypto/tls) or Rust/rustls that never call SSL_read/SSL_write, silent miss or is there a fallback capture path?
Heron
@hi_i_am_mimo Two separate boundaries here.
On data residency: by default, reconstructed calls live in Heron’s configured storage, usually the local embedded DuckDB file next to the Heron deployment. The console is embedded in the single binary, but the captured data is stored in the local/self-managed storage backend, not sent to a Heron cloud service. There is no hosted telemetry path by default.
Data only leaves that box if you configure it to: for example using ClickHouse as the storage backend, forwarding packets from cloud-probe to a central Heron instance, or explicitly exporting SFT/pcap artifacts. We treat those prompts/responses as sensitive production telemetry.
On TLS coverage: the `SSL_read` / `SSL_write` uprobe path is intentionally scoped. It covers OpenSSL/BoringSSL-style clients, including dynamically linked libssl and the statically linked BoringSSL case we built for Bun/Claude Code. It does not automatically cover runtimes that never call those functions, such as Go `crypto/tls` or Rust `rustls`.
For those, Heron will not magically reconstruct plaintext through the SSL uprobe path. The fallback is to capture at a point where traffic is already observable: after TLS termination, at a gateway, from a pcap/live interface with plaintext HTTP, or through cloud-probe. Native Go/Rust TLS support would require separate probes for those TLS stacks, and we should treat that as explicit compatibility work rather than claim universal coverage today.
Really clear, thanks, and the local-DuckDB-by-default residency is exactly the boundary I wanted. On the fallback path: when I capture post-termination at a gateway or from pcap for a Go/rustls agent, do I still get the same per-call request/response correlation and SFT-ready labeling the uprobe path gives, or does losing the syscall boundary mean I cannot reliably tie a reconstructed payload back to a specific process or agent?
Heron
@hi_i_am_mimo Exactly — this is the tradeoff.
The post-termination / pcap / cloud-probe path can still do request/response correlation and SFT-ready reconstruction, as long as Heron can see plaintext HTTP traffic and the provider payload shape is one it understands. That part does not depend on the syscall boundary; it comes from reconstructing the HTTP stream, LLM call, streaming response, tool-call structure, and agent turn.
What you lose without the eBPF path is the native OS process attribution: `pid`, `comm`, and executable path. Packet capture can tell us “this HTTP flow / gateway route / source probe / tenant / service sent this call,” but it cannot magically recover “this exact local process made it” unless that identity exists somewhere in the observable metadata.
So for Go/rustls agents behind a gateway, the best setup is to preserve an agent identity at the capture point: source/probe identity, gateway route, workspace/tenant, Kubernetes pod/service, mTLS identity, or a stable header if your gateway already has one. If multiple agents send indistinguishable HTTP traffic through the same gateway to the same endpoint with no distinguishing metadata, Heron can still reconstruct the calls, but it should not claim reliable per-process attribution.
Short version: same call/turn/SFT reconstruction when plaintext is visible; eBPF adds process attribution. Without eBPF, attribution depends on what identity your capture point exposes.
That header-based identity path is the part I'd lean on, since most of my agents already go through one gateway. Can Heron be configured to key attribution off a custom header the gateway injects (say an x-agent-id) and map it to a named agent in the console, so I get reliable per-agent grouping at the capture point without eBPF? Or is gateway-route/tenant the finest grain it correlates on there?
Seeing TLS encrypted LLM calls without proxies sounds impressive I'd to understand the technical boundaries and what information remains inaccessible due to encryption or process isolation.
Heron
@gordon_bennett Totally fair question. The important boundary is: Heron is not doing generic TLS decryption on the network, and it is not a MITM/proxy.
There are two capture surfaces. With pcap/live network capture, Heron can parse full LLM payloads only where the traffic is already plaintext, for example behind a TLS terminator, on an inference host, in local/dev traffic, or from a trusted packet source after termination. If all Heron has is encrypted TLS packets on the wire, it can still see transport-level signals like endpoints, timing, sizes, retries, and flow shape, but not prompts, responses, or tool payloads.
The eBPF path is different: on Linux, Heron can attach to the host-side TLS library boundary, e.g. `SSL_read` / `SSL_write`, where the process already sees plaintext before encryption or after decryption. That enables payload reconstruction and process attribution (`pid`, command, executable) without a proxy, but only for processes/containers/runtimes on hosts you are authorized to instrument and for TLS stacks Heron supports.
What remains inaccessible: traffic from hosts we are not running on, processes isolated from our permissions, payloads that never cross an observed boundary, unsupported TLS/protocol paths, and data the provider never returns to the client. So the design is passive and no-proxy, but it is not magic remote TLS breaking.
If I've got a swarm of agent processes all calling out to the same LLM endpoint from one box, how do you disambiguate which process initiated which call at the eBPF layer, is it PID tracking through the syscall, or are you also correlating with something at the process tree level?
Heron
@ansari_adin Process ID can be distingushed, it is an advantage of ebpf mode. But even there is no ebpf enabled, Heron has the ability to correlate the Agentic turns through signature of the body automagiclly.
The one-click SFT trajectory export is the part I didn't see coming. Turning production agent traffic into fine-tuning data without re-running anything is a genuinely useful shortcut, especially if you're running high-volume agent loops and want to improve model behavior from real usage. Does it have any mechanism to strip sensitive content from prompts before export, or is that left to the user?
Heron
@xavier_macia Yes — that is the right caveat.
Today, Heron does not automatically strip PII or secrets before SFT export. The export is explicit, and the resulting JSONL should be treated as a sensitive artifact. If the captured traffic may contain customer data, credentials, or proprietary context, it should go through a redaction/de-identification/review step before being used for training.
The controls we have today are more about exposure reduction: local/self-managed storage, retention policies, stored-body caps, and explicit operator-driven export. First-class redaction policies before export are the right next step, and we are adding that to the roadmap.
If you have a strong view on what the redaction policy should look like — rule-based filters, schema-aware tool-result filtering, allowlists, or review gates — I’d love to capture that in an issue or PR.
Debugging AI agent behavior has been painful for our team because we're always working backward from logs after something breaks. The passive observability angle here is interesting — if it captures what's happening without requiring changes to the agent code, that removes a real barrier to adoption. Does Heron work with cloud-hosted agents or only local/on-prem setups?
Heron
@kudiff Yes, with one important distinction: Heron does not need changes inside the agent code, but it still needs a capture point you control.
If your agents run on your own cloud infrastructure — VMs, Kubernetes nodes, inference hosts, gateways, or behind a TLS terminator — Heron can work there. You can run it on the relevant host, feed it traffic through cloud-probe/pcap, or use the opt-in eBPF mode on the Linux host where the agent process makes the LLM calls.
If by “cloud-hosted” you mean a fully managed third-party agent where you cannot access the host, network path, TLS boundary, or any log/export stream, Heron cannot observe it from the outside.
So the short version is: cloud infra you control, yes; opaque managed SaaS agents, only if they expose a capture or export point.