From b058794db91b237f29b6b0bed088e1da2844f6f8 Mon Sep 17 00:00:00 2001 From: Vader Date: Tue, 23 Jun 2026 12:52:39 +0800 Subject: [PATCH] Launch v0.7.0: README rebuild + corrected collateral + eBPF advisory (#175) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(ebpf): scrub machine-specific /home path from uprobe tests Test assertions used a real home-dir prefix (/home/v/...) that trips the infra-leakage CI gate. The tests only check exe basename matching, so the prefix is irrelevant — replace with /home/user/. * docs(launch): rebuild README (GIF-first) + corrected collateral, bump v0.7.0 Reconcile the marketing launch package with the shipped product: - README: adopt the GIF-first, conversion-driven layout (hero demo GIF, 30-second pcap quick start, three-up differentiator table) while keeping the existing technical accuracy — neutral tagline (wire OR on-host TLS boundary, not 'network wire' only), opt-in eBPF (no runtime --ebpf flag), docs/configure.md links, just-based contributor flow, canonical /api/traces. No decorative per-heading emoji. - Add docs/images/hero.gif (pcap-replay demo; marketing re-cuts the eBPF GIF). - launch/: paste-ready PH/HN/Twitter copy corrected to the shipped product (curl installer not npm, eBPF as experimental/opt-in, /api/traces, v0.7.0) plus GitHub Topics/Description/social-preview checklist. - Bump VERSION SSOT 0.6.0 -> 0.7.0 (Cargo.toml + package.json) and add the 0.7.0 CHANGELOG section over the OTel-rename Unreleased entries. * feat(ebpf): surface experimental opt-in advisory in startup log + Settings UI There is no `--ebpf` runtime flag (eBPF is enabled via the `ebpf` cargo feature + a `type = "ebpf"` capture source), so the capability was easy to miss. Add discoverability without a new flag: - main.rs: when no eBPF source is active, log a one-line advisory on Linux (runtime cfg! check, so it stays type-checked on every platform) pointing at the cargo feature + TOML source and docs/design/02-capture.md. - console Settings: tag the existing eBPF capture toggle 'experimental' and note the opt-in requirements in its description. * chore(version): sync Cargo.lock workspace crates to v0.7.0 --------- Co-authored-by: Vader Yang --- CHANGELOG.md | 26 ++ README.md | 356 ++++++++++++++++++---------- VERSION | 2 +- console/package.json | 2 +- console/src/pages/settings.tsx | 10 +- docs/images/hero.gif | Bin 0 -> 70802 bytes launch/HN_and_Twitter_Posts.md | 55 +++++ launch/PH_Submission_Details.md | 57 +++++ launch/README.md | 58 +++++ server/Cargo.lock | 28 +-- server/Cargo.toml | 2 +- server/app/heron/src/main.rs | 19 ++ server/h-capture/src/ebpf/source.rs | 6 +- 13 files changed, 468 insertions(+), 153 deletions(-) create mode 100644 docs/images/hero.gif create mode 100644 launch/HN_and_Twitter_Posts.md create mode 100644 launch/PH_Submission_Details.md create mode 100644 launch/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index d1d264aa..fd8d5e96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.7.0] — 2026-06-24 + +### Added + +- **eBPF capture discoverability — an experimental, opt-in advisory.** When no + eBPF source is active, the server now logs a one-line notice (Linux only) that + on-host TLS capture exists and how to enable it (`ebpf` cargo feature + a + `type = "ebpf"` source — there is no `--ebpf` runtime flag). The Settings + page's eBPF capture toggle is now tagged **experimental** and its description + spells out the opt-in requirements. + ### Changed - **OpenTelemetry-aligned rename of the storage entities and HTTP API.** The @@ -21,6 +32,21 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). for `spans`/`traces`. Existing DuckDB/ClickHouse databases auto-migrate in place on init() with no data loss (idempotent detect-then-rename). +### Docs + +- **README rebuilt for the launch — GIF-first, conversion-driven layout.** + Headline tagline "The Wireshark for AI Agents", a hero demo GIF up top, a + 30-second pcap-replay quick start, and a three-up "What Makes Heron Different" + table (agent-turn reconstruction · service topology · SFT trajectory export), + while preserving the existing technical accuracy (passive positioning across + wire *and* on-host TLS boundary, opt-in eBPF, `docs/configure.md` links, + `just`-based contributor flow). API examples updated to the canonical + `/api/traces` routes. +- **Corrected launch collateral added under `launch/`.** Paste-ready Product + Hunt / Hacker News / Twitter copy aligned to the shipped product: install via + the `curl … install.sh` one-liner (no npm package), canonical `/api/traces` + endpoint, and v0.7.0 framing. + ## [0.6.0] — 2026-06-16 ### Changed diff --git a/README.md b/README.md index c29e2a5b..ea7b9d01 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,131 @@ # Heron +**The Wireshark for AI Agents** + +Passive agent observability — reconstructed from the traffic itself, off the wire +or at the host's TLS boundary, never in the request path. + [![CI](https://github.com/Netis/heron/actions/workflows/ci.yml/badge.svg)](https://github.com/Netis/heron/actions/workflows/ci.yml) [![Release](https://img.shields.io/github/v/release/Netis/heron?sort=semver)](https://github.com/Netis/heron/releases/latest) [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) [![Platforms](https://img.shields.io/badge/platforms-linux%20%C2%B7%20macOS-informational)](docs/install.md) -**Passive agent observability — no SDK, no sidecar, no proxy.** Heron reconstructs what your agents are actually *doing* — tool calls, multi-step plans, where time is spent, where loops happen, who calls whom — from their LLM traffic, captured off the network wire or lifted from the host's TLS boundary by eBPF — never in the request path. +> **Zero SDK. Zero Proxy. Zero Intrusion.** +> Replay a `.pcap` and instantly see every agent turn, tool call, and LLM +> interaction. No code changes. No cooperation from the workloads being observed. -> **Try it in 30 seconds, no live capture, no privileges:** grab a `.pcap` with LLM -> traffic and replay it — -> `heron --pcap-file capture.pcap --no-retention` — then open -> . See [Quickstart](#quickstart). +

+ Heron demo — replay a pcap file and instantly see 247 LLM calls reconstructed into 12 agent turns, with timeline, metrics, and SFT export +

-![Agent turn detail — a 247-call agent run, every tool call ordered on the Timeline, drilling into one call's request/response on the right](docs/images/agent-turn-detail.png) +

+ One command. 247 calls → 12 agent turns. Every tool call visible. Try it now ↓ +

-## What it does +--- -Most agent code looks fine on paper and falls apart in production: a tool call stalls, the planner loops between two states, a downstream service silently substitutes a different model. Heron reconstructs that behavior from the raw traffic itself — capture → HTTP / SSE parse → wire-API decode → semantic extraction → **agent-turn assembly** — and serves the result through a console that's organized around *turns and sessions*, not raw HTTP calls. +## 30-Second Quick Start -It reads post-TLS traffic — on the inference host, behind a TLS terminator, or fed in from a SPAN/TAP point via [cloud-probe](https://github.com/Netis/cloud-probe). On Linux it can also read straight from the in-process TLS boundary via an experimental [eBPF](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental) source — hooking `SSL_read` / `SSL_write` to observe TLS-encrypted calls *on the host that makes them*, each attributed to its owning process, with no terminator or proxy. Multi-call agent interactions (planner → tool → planner → tool …) stitch into a single addressable turn. Multi-leg proxy hops (litellm in front of vLLM/SGLang/haproxy) fold automatically. The pipeline never sits in the request path, so the observer can fail without breaking the calls being observed. +No live capture needed. No privileges. Just a `.pcap` with LLM traffic. + +```bash +# Install (Linux/macOS, user-local, no sudo) +curl -fsSL https://raw.githubusercontent.com/Netis/heron/main/install.sh \ + | INSTALL_DIR="$HOME/.local" sh + +# Replay a pcap — no privileges needed +heron --pcap-file capture.pcap --no-retention +``` + +Open to see your agent turns, timelines, and metrics. +After a pcap finishes replaying, the process keeps the API/console available so +you can browse — press Ctrl+C to exit, or pass `--exit-after-drain` for batch/CI +use that exits as soon as the pipeline drains. + +> **No pcap handy?** The repo ships fixtures in [`testdata/pcaps/`](testdata/pcaps/) — replay any of them. +> **Have a live interface?** Run `heron -i eth0` (needs `CAP_NET_RAW` on Linux — see [install docs](docs/install.md)). Grant it once with `sudo setcap cap_net_raw,cap_net_admin=eip ~/.local/bin/heron` so no sudo is needed at runtime. +> **On Linux?** An experimental on-host [eBPF source](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental) reads TLS-encrypted traffic as plaintext at the in-process `SSL_read`/`SSL_write` boundary, attributed per process — opt-in, built behind the `ebpf` cargo feature, needs `CAP_BPF`. + +> Heron sees **plaintext** HTTP. Install it where the traffic is already +> decrypted: on the inference host, behind the TLS terminator, or fed from a +> trusted packet source. + +--- + +## What Makes Heron Different + + + + + + + +
+ +### Agent Turn Reconstruction + +Stitches multi-call agent interactions (planner → tool → result → next tool) +into **single addressable turns** — see the full agent narrative, not raw HTTP +calls. + +Named profiles for **Claude Code** and **OpenAI Codex CLI**, plus a generic +profile for everything else. + +Agent turn timeline — 247 calls in one turn + + + +### Service Topology + +See your inference fleet as a **directed graph**: clients → litellm proxies → +vLLM / SGLang backends, edge thickness scaled by turn count. + +Heron classifies what each endpoint serves — vLLM, SGLang, Ollama, llama.cpp, +LiteLLM — **from the bytes on the wire**, not from configuration. + +Service topology graph + + + +### SFT Trajectory Export + +**Turn real agent traffic into fine-tuning data.** Export any turn or session +as OpenAI-style `messages` JSONL — tool calls, results, and reasoning preserved, +arguments rehydrated to objects. + +One click from a turn's detail view, or batch-export from the Agent Turns list +with the current filter (time · agent kind · model · wire API). Anthropic and +OpenAI-chat wire formats today; unsupported formats are reported and skipped, +not failed. + +
+ +--- + +## Why Not an SDK / Proxy / OpenTelemetry? + +| Approach | In request path | Needs client changes | Sees full bodies | Reconstructs turns | Exports SFT data | +| --- | :---: | :---: | :---: | :---: | :---: | +| SDK instrumentation | yes | every client | yes | manual | manual | +| Reverse proxy (LiteLLM …) | yes | re-point clients | yes | per-call only | no | +| OpenTelemetry from server | yes | server must emit | partial | if tagged | no | +| **Heron** | **no** | **none** | **yes**¹ | **automatic** | **one click** | + +¹ TLS-terminated traffic — Heron sees plaintext HTTP. Install it where the +traffic is already decrypted (inference host, behind the TLS terminator, or fed +by [cloud-probe](https://github.com/Netis/cloud-probe) from a SPAN/TAP point), +or use the experimental Linux [eBPF source](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental) +for on-host encrypted capture with per-process attribution. + +The trade-off is honest: you give up cross-cluster client tracing. You get a +single passive evidence chain that can't break the call when the observer fails, +requires zero cooperation from the workloads being observed, and **assembles the +agent narrative for you** instead of leaving you to join calls into turns in your +data warehouse. + +--- + +## Architecture ``` NIC / .pcap file / cloud-probe (ZMQ) / eBPF SSL uprobes @@ -36,138 +143,108 @@ NIC / .pcap file / cloud-probe (ZMQ) / eBPF SSL uprobes DuckDB ─── REST API ─── React console (localhost:3000) ``` -Same connection's packets always land on the same worker, so parsing state is local and lock-free. Multiple independent pipelines can run side-by-side — e.g., low-latency local capture isolated from bursty cloud-probe ingress. - -> ### 🛰️ On-host eBPF capture (Linux) — see TLS-encrypted agent traffic with no proxy -> -> Packet capture only sees plaintext. Heron's **eBPF SSL-uprobe source** lifts -> that on Linux: it hooks `SSL_read` / `SSL_write` in-process and reads -> **TLS-encrypted** LLM calls as plaintext *on the host that makes them* — no -> proxy, no TLS terminator, no SDK, never in the request path — and stamps every -> call with its **owning process** (pid · command · executable), so you see *which -> agent process* made each call. It covers: -> -> - **dynamically-linked OpenSSL/BoringSSL** — Python `openai`/`anthropic` SDKs, -> curl, Node, and most CLIs (attached by exported symbol); and -> - **statically-linked, symbol-stripped BoringSSL SEAs** — Claude Code's and -> opencode's ~250 MB Bun single-executable runtimes, located by BoringSSL -> byte-signature offset. -> -> It is built to survive the messy reality of agent CLIs: it **follows their -> frequent npm self-updates** by re-attaching across the rotated binary inode, -> and **reaches sessions that were already running** when capture started -> (via `/proc//exe`) — without a restart. The result is a complete on-host -> view of Claude Code / opencode / Python-agent traffic, reconstructed into -> agent turns and attributed per process. -> -> Opt-in — built behind the `ebpf` cargo feature; Linux-only, needs `CAP_BPF` + -> kernel BTF (and `CAP_SYS_ADMIN` on hardened ≤5.15 kernels). See -> [eBPF capture](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental). - -## Why not an SDK / proxy / OpenTelemetry? - -| Approach | In request path | Needs client cooperation | Sees full bodies | Reconstructs agent turns | -| -------------------------- | :-------------: | :----------------------: | :--------------: | :----------------------: | -| SDK instrumentation | yes | every client must | yes | every client must emit | -| Reverse proxy (LiteLLM …) | yes | clients point at it | yes | per-call only | -| OpenTelemetry from server | yes | server must emit | partial | if the server tags it | -| **Heron** | **no** | **no** | **yes**¹ | **yes** | - -¹ TLS-terminated traffic only — Heron sees plaintext HTTP. Install it where the traffic is already decrypted: on the inference host, behind the TLS terminator, or fed by [cloud-probe](https://github.com/Netis/cloud-probe) from a SPAN/TAP point. The experimental Linux **eBPF** source lifts this for on-host capture — it reads plaintext at the in-process TLS boundary (`SSL_read` / `SSL_write`), so it observes TLS-encrypted calls on the agent/inference host itself with no terminator, and additionally attributes each call to the owning process. - -The trade-off is honest: you give up cross-cluster client tracing, you get a single passive evidence chain that can't break the call when the observer fails, that requires zero cooperation from the workloads being observed, and that **assembles the agent narrative for you** instead of leaving you to join calls into turns in your data warehouse. - -## What's in the box - -**Ingress** -- libpcap on a live interface -- Replay from `.pcap` files (any speed) -- ZMQ from [cloud-probe](https://github.com/Netis/cloud-probe) for hosts you can't install on directly -- **eBPF SSL uprobes** (Linux · opt-in) — hook `SSL_read` / `SSL_write` in-process to read **TLS-encrypted** traffic as plaintext on the host that makes the calls, with no proxy or TLS terminator, and stamp every call with its **owning process** (pid · command · executable). Covers dynamically-linked OpenSSL/BoringSSL (Python SDKs, curl, Node, …) **and** statically-linked, symbol-stripped BoringSSL SEAs — Claude Code's and opencode's Bun runtimes, located by byte-signature offset. **Follows the agent CLIs' frequent npm self-updates** (re-attaches across the rotated binary inode) and **reaches already-running sessions** (via `/proc//exe`), so capture keeps working without restarts. Off by default — built behind the `ebpf` cargo feature, needs `CAP_BPF` + kernel BTF. See the **On-host eBPF capture** spotlight above and [eBPF capture](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental). - -**Agent-turn reconstruction** with named profiles for **Claude CLI** (Claude Code) and **OpenAI Codex CLI**, a generic profile for everything else, plus an experimental OpenClaw profile. Turns stitch multi-call agent interactions (tool call → tool result → planner → next tool, repeat) into a single addressable unit. The hero screenshot above is one such turn — 247 calls, ordered on the Timeline, drillable into the request/response of any single call. - -![Agent Turns list — sorted by call count to surface the most complex agent runs first](docs/images/agent-turns.png) - -**Service topology — see the agent's call graph, not just the calls.** The Services page's Path view shows your inference fleet as a directed graph: clients → litellm proxies → vLLM / SGLang backends, with edge thickness scaled by turn count. Proxy hops paired by the passive sweeper render as solid edges; heuristically-inferred hops (when the inbound `client_ip` matches a known service) render as dashed; anonymous client traffic is dotted. The classifier names what each endpoint actually serves — vLLM, SGLang, Ollama, llama.cpp, LiteLLM — from the traffic itself, not from configuration the operator told it. - -![Services Path view — service-to-service call graph with proxy / inferred / client edges, colored by app](docs/images/services-path.png) - -**Wire-API decoders** -- OpenAI Chat Completions (`/v1/chat/completions`) -- OpenAI Responses (`/v1/responses`) -- Anthropic Messages (`/v1/messages`) -- Gemini AI Studio (`generativelanguage.googleapis.com`) - -This covers OpenAI direct, Azure OpenAI, Anthropic direct, AWS Bedrock / GCP Vertex (Anthropic wire), Google Gemini, and any OpenAI-compatible local server — vLLM, SGLang, Ollama, llama.cpp's server, LM Studio, etc. +Same connection's packets always land on the same worker, so parsing state is +local and lock-free. Multiple independent pipelines can run side-by-side — e.g. +low-latency local capture isolated from bursty cloud-probe ingress. The pipeline +never sits in the request path, so the observer can fail without breaking the +calls being observed. + +> **On-host eBPF capture (Linux, experimental).** Packet capture only sees +> plaintext. Heron's eBPF SSL-uprobe source lifts that on Linux: it hooks +> `SSL_read` / `SSL_write` in-process and reads **TLS-encrypted** LLM calls as +> plaintext *on the host that makes them* — no proxy, no TLS terminator, no SDK, +> never in the request path — and stamps every call with its **owning process** +> (pid · command · executable). It covers dynamically-linked OpenSSL/BoringSSL +> (Python `openai`/`anthropic` SDKs, curl, Node, most CLIs) and statically-linked, +> symbol-stripped BoringSSL single-executable runtimes (Claude Code's and +> opencode's Bun binaries, located by byte-signature offset). It follows the +> agent CLIs' frequent npm self-updates (re-attaches across the rotated binary +> inode) and reaches already-running sessions (via `/proc//exe`) without a +> restart. Opt-in — built behind the `ebpf` cargo feature; needs `CAP_BPF` + +> kernel BTF. See [eBPF capture](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental). + +--- + +## What's in the Box -**Per-call drill-down when you need it** — every LLM call is also captured with structured request/response *and* the raw body. Stalled tool calls, malformed prompts, unexpected token counts: the evidence is on the page, not behind a re-run. +
+Ingress sources -**Export turns as training data.** Any reconstructed turn — or a whole session — exports as an **SFT trajectory**: OpenAI-style `messages` JSONL with tool calls, tool results, and assistant reasoning preserved, and tool-call arguments rehydrated to objects. Download a single turn or session straight from its detail view, or batch-export from the Agent Turns list — the current filter (time window · agent kind · model · wire API) becomes a one-line-per-turn JSONL, so a slice of real captured agent traffic turns into a fine-tuning set with one click. Anthropic and OpenAI-chat wire formats today; unsupported formats are reported and skipped rather than failing the batch. +- **libpcap** on a live interface +- **Replay** from `.pcap` files (any speed) +- **ZMQ** from [cloud-probe](https://github.com/Netis/cloud-probe) for hosts you can't install on directly +- **eBPF SSL uprobes** (Linux · opt-in) — hook `SSL_read` / `SSL_write` in-process to read TLS-encrypted traffic as plaintext on the host that makes the calls, with no proxy or TLS terminator, and stamp every call with its owning process. Covers dynamically-linked OpenSSL/BoringSSL and statically-linked, symbol-stripped BoringSSL runtimes (Claude Code's / opencode's Bun). Built behind the `ebpf` cargo feature, needs `CAP_BPF`. See [eBPF capture](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental). -**Metrics** are framed first at the **agent layer** — turn count and duration distribution per agent kind, call count per turn, tool-call success rate — and then at the **call layer**: TTFT · E2E latency · TPOT · token throughput · call rate · active calls · call error rate · prompt-cache hit ratio. The Overview page is built around both. See [glossary](docs/glossary.md) for what each means and why. +
-![Overview — agent activity timeseries + per-kind distribution at the top, call-rate / latency / error rate / per-model panels below](docs/images/overview.png) +
+Wire-API decoders -**Storage** in DuckDB (default, embedded, single-file) with per-table retention enabled out of the box, or **ClickHouse** for high-volume columnar analytics — select it with `storage.backend = "clickhouse"` in the config. Pluggable backend trait; PostgreSQL is designed but not yet wired. +- OpenAI Chat Completions (`/v1/chat/completions`) +- OpenAI Responses (`/v1/responses`) +- Anthropic Messages (`/v1/messages`) +- Gemini AI Studio (`generativelanguage.googleapis.com`) -**Console** at `http://localhost:3000`: overview · performance · usage · errors · services (table / path / model views) · agent turns · agent sessions · LLM calls (with full request/response body drill-down) · raw HTTP exchanges · pipeline-health debug views. +Covers OpenAI direct, Azure OpenAI, Anthropic, AWS Bedrock / GCP Vertex +(Anthropic wire), Google Gemini, and any OpenAI-compatible server — vLLM, SGLang, +Ollama, llama.cpp, LM Studio, etc. Every LLM call is also captured with +structured request/response **and** the raw body, so stalled tool calls, +malformed prompts, and unexpected token counts are evidence on the page, not +behind a re-run. -**Three themes, one toggle.** Cycle from the sidebar between **Kami** (`紙神` — a warm washi-paper light theme with mineral-pigment accents, the default and what the screenshots here show), **Dark** (slate, for the dim room), and **Light** (clean high-contrast). The choice persists per browser; everything — charts, the topology graph, the timeline gantt — re-themes with it. +
-More console screenshots +Console pages -![Services Table view — per-endpoint metrics with auto-classified app type](docs/images/services-table.png) +`http://localhost:3000` — Overview · Performance · Usage · Errors · Services +(table / path / model) · Agent Turns · Agent Sessions · LLM Calls (with full +request/response drill-down) · Raw HTTP · Pipeline Health. -![Agent session — full transcript across turns](docs/images/agent-session-detail.png) - -![Traffic — call rate and token throughput over time](docs/images/traffic.png) - -![Pipeline health — internal queue depth, drop counters, leak canaries](docs/images/pipeline-health.png) +Three themes, one toggle: **Kami** (`紙神` — warm washi-paper, the default and +what the screenshots show), **Dark** (slate), **Light** (high-contrast). The +choice persists per browser; charts, the topology graph, and the timeline gantt +all re-theme with it.
-**Distribution**: prebuilt static binaries for Linux musl (x86_64 + aarch64) and macOS (Intel + Apple Silicon). Web console is **embedded in the binary** — single artifact, no separate frontend deploy. - -## Who it's for +
+Metrics -- **Agent developers** — debug stalled tool calls, detect plan-loop / "no submit" failure modes, and see exactly which model+endpoint each turn hit, without modifying the agent or its SDK -- **AI platform / inference ops** — see the real service-to-service topology your traffic flows through (clients → litellm → vLLM / SGLang), measure each hop independently, and catch silent model substitutions -- **FinOps & engineering managers** — attribute spend across teams/repos/projects from real turns, not periodic SDK exports that can drift -- **Compliance & security** — capture-once evidence chain of what each agent actually sent and received, scoped per agent kind and per session -- **Model trainers / fine-tuners** — turn real captured agent runs into SFT datasets, per turn or whole session, without hand-labeling or re-running the agent +- **Agent layer:** turn count and duration distribution per agent kind, call count per turn, tool-call success rate. +- **Call layer:** TTFT · E2E latency · TPOT · token throughput · call rate · active calls · error rate · prompt-cache hit ratio. -## Quickstart +See the [glossary](docs/glossary.md) for what each means and why. -```bash -# Install (Linux/macOS, no sudo, user-local) -curl -fsSL https://raw.githubusercontent.com/Netis/heron/main/install.sh \ - | INSTALL_DIR="$HOME/.local" sh +
-# Linux: grant capture privileges to the binary (no sudo at runtime) -sudo setcap cap_net_raw,cap_net_admin=eip ~/.local/bin/heron +
+Storage & distribution -# Capture from a live interface -heron -i eth0 +- **Storage:** DuckDB (default, embedded, single-file) with per-table retention out of the box, or **ClickHouse** for high-volume columnar analytics (`storage.backend = "clickhouse"`). Pluggable backend trait; PostgreSQL is designed but not yet wired. +- **Distribution:** prebuilt static binaries for Linux musl (x86_64 + aarch64) and macOS (Intel + Apple Silicon). The web console is **embedded in the binary** — single artifact, no separate frontend deploy. -# ...or replay a pcap (no privileges needed) -heron --pcap-file capture.pcap --no-retention -``` +
-Then open . +--- -After a pcap finishes replaying, the process keeps the API/console available so you can browse the results — press Ctrl+C to exit, or pass `--exit-after-drain` for batch/CI use that exits as soon as the pipeline drains. +## Who It's For -> Heron sees **plaintext** HTTP. Install it where the traffic is already decrypted, such as on the inference host, behind a TLS terminator, or fed from a trusted packet source. +| Role | Use case | +| --- | --- | +| **Agent developers** | Debug stalled tool calls, detect plan-loop / "no submit" failures, see exactly which model+endpoint each turn hit — without modifying the agent or its SDK | +| **AI platform / inference ops** | See the real service-to-service topology (clients → litellm → vLLM / SGLang), measure each hop, catch silent model substitutions | +| **FinOps & eng managers** | Attribute spend across teams/repos/projects from real turns, not periodic SDK exports that drift | +| **Compliance & security** | Capture-once evidence chain of what each agent sent and received, scoped per agent kind and session | +| **Model trainers / fine-tuners** | Turn real captured agent runs into SFT datasets — per turn or whole session — without hand-labeling or re-running the agent | -For systemd deployment, capability options, and uninstall, see [docs/install.md](docs/install.md). +--- -## Install & verify with an AI agent +## Install & Verify with an AI Agent -Running an AI coding agent (Claude Code, Codex, etc.)? Hand it the prompt -below and let it do the install + smoke test for you. It needs only shell -access to the target machine. +Running an AI coding agent (Claude Code, Codex, etc.)? Hand it the prompt below +and let it do the install + smoke test. It needs only shell access to the target +machine. ```text Install and smoke-test Heron (https://github.com/Netis/heron) on this machine: @@ -179,29 +256,36 @@ Install and smoke-test Heron (https://github.com/Netis/heron) on this machine: small .pcap with LLM traffic (the repo's testdata/pcaps/ has fixtures), then run `heron --pcap-file --no-retention`. 4. Confirm the API is up: `curl -s http://localhost:3000/api/health` returns - healthy, and `curl -s 'http://localhost:3000/api/agent-turns?limit=5'` - returns reconstructed turns. + healthy, and `curl -s 'http://localhost:3000/api/traces?limit=5'` returns + reconstructed traces. 5. (Optional, needs CAP_NET_RAW) for a live test: setcap the binary and run `heron -i `, generate some LLM traffic through the host, then re-check the console at http://localhost:3000. -Report the console URL and the turn count you saw. Don't hard-code or -commit any host/credential — this repo rejects infra leakage in CI. +Report the console URL and the trace count you saw. Don't hard-code or commit +any host/credential — this repo rejects infra leakage in CI. ``` -The last line matters: a `check-leakage.sh` CI gate fails any PR that -commits a private IP, plaintext credential, or key — keep your own infra -out of anything you push back. +The last line matters: a `check-leakage.sh` CI gate fails any PR that commits a +private IP, plaintext credential, or key — keep your own infra out of anything +you push back. + +--- ## Documentation -- [Install](docs/install.md) — one-line installer, systemd, capabilities -- [Configure](docs/configure.md) — pipelines, sources, storage, retention -- [eBPF capture](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental) — on-host TLS capture + process attribution (Linux, opt-in): symbol & byte-signature attach, self-update tracking, running-session re-attach -- [Glossary](docs/glossary.md) — what every metric means -- [Architecture](docs/design/01-architecture.md) — pipeline design and trade-offs -- [Filing issues](docs/filing-issues.md) — how issues are triaged + how to file one an agent can pick up -- [Mission](docs/mission.md) — long-arc vision +| Doc | Description | +| --- | --- | +| [Install](docs/install.md) | One-line installer, systemd, capabilities, uninstall | +| [Configure](docs/configure.md) | Pipelines, sources, storage, retention | +| [eBPF capture](docs/design/02-capture.md#ebpf-ssl-uprobe-capture-linux-experimental) | On-host TLS capture + process attribution (Linux, opt-in) | +| [Architecture](docs/design/01-architecture.md) | Pipeline design and trade-offs | +| [Glossary](docs/glossary.md) | What every metric means | +| [Filing issues](docs/filing-issues.md) | How issues are triaged + how to file one an agent can pick up | +| [Mission](docs/mission.md) | Long-arc vision | +| [Changelog](CHANGELOG.md) | Release history | + +--- ## Roadmap @@ -212,6 +296,8 @@ The current surface is the foundation layer (Ops use cases). On the way: See [docs/mission.md](docs/mission.md) for the full ladder. +--- + ## Contributing Bug reports and PRs welcome. Before opening a PR, run: @@ -222,9 +308,17 @@ just quality all # rust fmt + clippy + ts lint + tsc just test all # cargo test (all crates) ``` -Run `just help` for the full menu. Design docs under [docs/design/](docs/design/) describe the per-module contract — read the relevant one before changing anything load-bearing. +Run `just help` for the full menu. Design docs under [docs/design/](docs/design/) +describe the per-module contract — read the relevant one before changing anything +load-bearing. + +> **Build via `just build all`, not a bare `cargo build`.** The web console is +> embedded behind the non-default `console` cargo feature; a raw +> `cargo build --release` yields a working API with a **blank console**. If you +> invoke cargo directly, run `bun run build` in `console/` first and pass +> `--features console` — see [docs/install.md → Building from source](docs/install.md#building-from-source). -> **Build via `just build all`, not a bare `cargo build`.** The web console is embedded behind the non-default `console` cargo feature; a raw `cargo build --release` yields a working API with a **blank console**. If you invoke cargo directly, run `bun run build` in `console/` first and pass `--features console` — see [docs/install.md → Building from source](docs/install.md#building-from-source). +--- ## License diff --git a/VERSION b/VERSION index a918a2aa..faef31a4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.0 +0.7.0 diff --git a/console/package.json b/console/package.json index f9ec7369..04d38fae 100644 --- a/console/package.json +++ b/console/package.json @@ -1,7 +1,7 @@ { "name": "console", "private": true, - "version": "0.6.0", + "version": "0.7.0", "type": "module", "scripts": { "dev": "vite", diff --git a/console/src/pages/settings.tsx b/console/src/pages/settings.tsx index b19cb527..96b97e60 100644 --- a/console/src/pages/settings.tsx +++ b/console/src/pages/settings.tsx @@ -324,6 +324,12 @@ function EbpfCaptureToggle({
🛰️ eBPF capture (on-host TLS) + + experimental + {!available && ( unavailable in this build @@ -332,8 +338,8 @@ function EbpfCaptureToggle({
{available - ? "Read TLS plaintext at the SSL_read / SSL_write boundary with per-process attribution. Toggling rewrites the config and restarts capture (~2–3s)." - : "Requires a Linux build compiled with the `ebpf` feature (CAP_BPF + kernel BTF)."} + ? "Experimental, opt-in. Read TLS plaintext at the SSL_read / SSL_write boundary with per-process attribution. Toggling rewrites the config and restarts capture (~2–3s)." + : "Experimental, opt-in. Requires a Linux build compiled with the `ebpf` feature (CAP_BPF + kernel BTF)."}