
Founding engineer at yeet, working on kernel-side observability and the tooling around it. I write about eBPF, Linux internals, and why your telemetry bill looks the way it does.
Last updated: October 2026
Quick answer. Install a daemon on the host that can read the network from the kernel, and let the agent query it or write a probe against it, instead of handing the agent a dashboard or a shell. On Linux that is what yeet does:
yeetdruns on each box, exposes a read-only graph of processes, containers and interfaces that an agent queries withyeet graph query, and runs the eBPF scripts the agent writes withyeet run. The agent then reads TCP resets with their direction, every outbound connection tied to the process that dialed it, HTTP and gRPC decoded off the wire, and the hostname in every TLS handshake, on the production host. The agentic NetOps products from NetBrain, Cisco and Selector reason over telemetry your devices already exported, and a Wireshark MCP server reads a pcap. Neither sees the packet that nobody collected.
Most of the network incidents that page somebody at 2am are questions the monitoring stack was not told to ask. A 502 with a spotless access log. Three percent of connections reset, uncorrelated with anything. A DNS answer that changed under a pool that still held the old address. The dashboards say green because a dashboard is a summary of what somebody chose to collect before the incident, and the deciding fact is on the wire. An AI agent pointed at the same dashboards reaches the same dead end faster: it correlates well, forms a plausible story, and proposes a fix you then have to test in production. The input never contained the answer. The useful question is not which model to use. It is what the agent can read.
I build the kernel-side tooling this post describes and I spend most of my week watching engineers point agents at infrastructure for the first time. I do not run a 3,000-device campus or a carrier core, and the vendors who sell agentic NetOps into those estates know things I do not. What I see, on Linux hosts, is a narrower and more common failure: an agent with every chart and no access to the wire, told to explain a reset it cannot see.
Because all three are records somebody decided to write in advance, and the failures that survive to production are the ones nobody anticipated. Logs, metrics and traces share one property: you had to know the question before it showed up, instrument for it, and ship the data to a store, which is why yeet's founder describes the three pillars as the same option three times. A record that was never written is not a weak signal in the agent's evidence. It is an absent one, and no amount of reasoning over the other records recovers it.
The network is where this bites hardest, because the events that matter happen below the application. A load balancer that drops an idle connection without a FIN produces no log line in your service; the next request gets a TCP reset and the client logs a 502 from a service that never saw the request. AWS documents that its Network Load Balancer does exactly this after 350 idle seconds. A resolver that starts returning a different A record produces no event anywhere unless something was recording DNS answers. A server rejecting a client certificate is a bad_certificate alert on the wire, and often nothing in the log at all. Each of those is what an engineer eventually finds after a tcpdump session that had to be running at the right moment.
Five things, all of which exist in the kernel of the host and almost none of which exist in a monitoring stack:
RST says whether this host sent it or received it.dig cannot tell you because dig reports what the resolver gives you, now.A sixth item makes the first five useful to an agent rather than a human: a typed interface instead of a terminal, so the agent spends its reasoning on the question rather than on parsing ss -tanp columns.
With yeet the agent asks the host directly, in two ways. The first is a query against the graph yeetd already exposes. yeet graph dump prints the schema, so the agent discovers what exists rather than being told, and yeet graph query returns JSON:
yeet graph dump # the full schema, as SDL
yeet graph query '{ procs { pid comm cpu_time } }' # JSON on stdout
yeet graph query '{ docker { list_containers { name image state } } }'
The graph covers processes, per-interface counters, containers, CPU, memory and kernel state. It is the inventory an investigation starts from, and it is read-only in the structural sense: the schema has no mutation type, so a single allow rule for yeet graph query covers the whole diagnostic surface in a coding agent's permission config.
The second way answers the question nobody anticipated. yeet is a JavaScript runtime for Linux ops: a V8 isolate inside the daemon, bound to that graph, with eBPF programs the script loads and reads. An agent that writes JavaScript all day writes a probe the same way:
yeet run gh:yeet-src/pktscope -- --port=8443 # a ready-made tool from GitHub
yeet run -T ./rst-watch.js | jq . # one the agent wrote; pipe mode, one line per console.log
When stdout is a pipe, yeet run emits one line per console.log call, the shape an agent consumes without parsing a screen. The loop is: describe what you want to see, the model writes the script, yeet runs it next to the data, the model reads the result. yeet service keeps a probe running past the session and serves it as a page the on-call human can also open. One thing yeet does not have, stated because people ask: there is no MCP server today. An MCP server exposes data a vendor already collected; yeet has the agent write and run the probe itself on the host.
They reason over telemetry your network devices and tools already export, and their own descriptions say so. NetBrain's Agentic NetOps release of February 2026 describes AI Deep Diagnosis as "Human-on-the-loop Agentic AI" built on "NetBrain's digital twin and intent-based automations to analyze network issues." Cisco's AgenticOps rests on telemetry where "signals from networking, ThousandEyes, firewalls, and Splunk flow together." Palo Alto's Prisma SD-WAN agent "automatically pulls telemetry, logs and configurations to validate its reasoning," and cites Gartner's forecast that "by 2030, 50% of organizations will use agentic NetOps with minimal human involvement." Selector "collects metrics, logs, configs, and flows with no agents required." For a switching fabric, an SD-WAN overlay or a wireless estate that is the only sane design, because you cannot install a daemon on a Catalyst. What none of these products do is read the wire on the Linux host where your application process lives, because that is not their layer. If the reset came from the load balancer, the agent that sees it is the one with a probe on the host that received it, which is the same argument as for an AI SRE that reasons over telemetry it doesn't collect.
You can, and it works for the failure you can reproduce and fails for the one you are paging about, because both routes hand the agent a packet capture that had to be running when the thing happened.
A Wireshark MCP server gives an assistant "real-time network traffic capture from any interface" and "analysis of capture files with Wireshark display filters," with "Wireshark/TShark installed and in PATH" and either dumpcap granted capture capabilities with setcap or the server run under sudo, which the project itself marks "not recommended." That is tshark with a model driving it, useful for a loop you can reproduce: start a capture, trigger the request, stop, read the dissection. An intermittent failure means capturing continuously on a production NIC, with the disk, CPU and policy cost that implies.
Kubeshark's MCP server is the more complete version of the same idea and the one real agent-facing traffic capture in the category. It exposes list_l4_flows, capture_traffic, export_pcap and L7 calls with decrypted TLS, and its prerequisites begin with "Kubeshark installed in your cluster." On Kubernetes it is a serious option; on a VM or a bare-metal box it is not an option at all. tcpdump over SSH is the oldest form and quietly grants the most: the agent holds a shell on a production host, and the record of what it ran is its own transcript, which stops at the shell boundary.
| Route | What the agent reads | Needs Kubernetes | Needs the capture running before the failure | Where the privilege sits | Answers a question nobody wrote a probe for |
|---|---|---|---|---|---|
| yeet, a JavaScript runtime for Linux ops | Read-only graph of processes, containers and interfaces; eBPF scripts the agent writes and runs; GraphQL endpoints scripts like httpscope serve | No | A probe has to be attached, but it is cheap enough to leave running and yeet service keeps it up; no pcap | In yeetd; yeet run and yeet graph query are unprivileged | Yes, the agent writes the probe in JavaScript |
| Kubeshark MCP | L4 flows, L7 calls with decrypted TLS, PCAP export, within its retention window | Yes | Partly; Kubeshark captures continuously and retains | In the Kubeshark hub and workers | Within its captured fields |
| Wireshark MCP | Live capture and pcap files via tshark | No | Yes | With dumpcap, via setcap or sudo | Within tshark's dissectors |
| NetBrain, Cisco AgenticOps, Selector | Device telemetry, flows, configs, digital twins | No | Yes, by design; they reason over what was exported | In the vendor platform | No; a record that was not exported is absent |
tcpdump over SSH | Packets, as a pcap | No | Yes | With the agent, as the SSH account | Within what tcpdump filters |
Keep the privilege in the daemon and give the agent the interface, which is a different grant from any account. Attaching an eBPF program is privileged work; the question is who holds it. With yeet, yeetd performs the privileged load, and yeet run and yeet graph query are unprivileged commands that never take sudo. The agent holds no SSH key, no capability and no sudoers entry; it holds the ability to ask questions and to run scripts inside a sandboxed isolate whose kernel access the daemon mediates. That is the fourth of the four ways to let an agent inspect a Linux server, and the other three each grant more than their names suggest.
Two limits belong next to the grant. A probe the agent writes can read anything the kernel sees on that host, including plaintext request bodies, so govern the output the way you govern database access. And the record of what the agent did should come from below the agent: claudefeed tails every command, file and TCP port a Claude Code session touches, which is what actually happened rather than what the transcript says.
Five published scripts, each with output an agent can read, plus the graph and whatever probe the agent writes for the rest. Hand the agent the output rather than a description of it.
Resets, SYNs and anything else at the packet level: pktscope. A Wireshark-style packet list, protocol tree and hex pane in the terminal, attached with TCX hooks on ingress and egress of every interface, returning TCX_NEXT on every path so nothing is dropped or delayed. The display filter accepts rst, syn, rx, tx and bare substrings, so "who sent the reset, and did it arrive or leave" is one filter away:
yeet run gh:yeet-src/pktscope # then type: / rst
yeet run gh:yeet-src/pktscope -- --port=5432 # in-kernel scope, nothing else reaches userspace
Every outbound connection, by process: dialout. One fexit probe on tcp_connect captures the four-tuple and the process lineage while execution is still in the dialing process's context, and flags connections that leave the private network. "Which process on host-03 is talking to 10.0.0.4, and since when" is one snapshot:
yeet run gh:yeet-src/dialout -- --once --secs 5 # a five-second snapshot
yeet run gh:yeet-src/dialout/dump.js | jq -c 'select(.public)'
The longer comparison puts ss -tp, BCC's tcptop and a bpftrace one-liner next to it.
Every live TCP connection and its byte counts: tcpsnoop. netstat for right now, filterable by pid, name, port or direction. "Is this process still holding the old address after the DNS change" is this view.
DNS questions and answers, by process: dnssnoop. One event per query with the pid and command that asked, the domain, the A records that came back, the resolver and the latency. Where it does not fit, the agent writes its own probe.
HTTP decoded off the wire: httpwatch on a host, container-traffic per container, httpscope when the agent should query rather than watch. httpwatch reads plaintext HTTP at the TC layer; container-traffic reads it at the socket layer and tags each request with the kernel's cgroup id, so the per-container split needs no service mesh. httpscope is the one built for an agent: it learns every HTTP API the machine serves and calls, plaintext off the wire and HTTPS from inside OpenSSL and rustls, and serves a GraphQL endpoint at /api/query where the agent composes its own criteria. The API debugging post covers that loop; this post is the layer underneath it.
For an agent that should build the tool rather than run one, yeet.cx/prompts/httptop is a prompt to paste into a coding agent on a host running yeet, and the same shape works for any of the five things above, which is the point: the agent is not limited to the scripts somebody published.
Or hand the first pass to an agent on the box:
Find out who is resetting TCP connections on this Linux machine.
Check uname -s is Linux and yeet --version works; if not, install yeet with
curl -fsSL https://yeet.cx | sh. Never run yeet with sudo.
Run yeet graph query '{ procs { pid comm } }' and note which services are here.
Run yeet run gh:yeet-src/pktscope for 60 seconds with the display filter set to
rst, and for every reset report the direction (rx or tx), the peer address and
the local port.
Say which local process owns each local port, whether this host sent or received
each reset, and what you would check next. Watch only: do not open connections.It names the sender and the idle gap in the first minute instead of proposing retry logic in the fourth. With illustrative numbers, on a host where a Python service behind a cloud load balancer logs a few ECONNRESET errors a night: given the logs, an agent notices the errors cluster after quiet periods, guesses the pool's idle timeout is longer than something upstream's, and proposes lowering it. That is a deploy you have to make to find out, and if the cause is a NAT gateway rather than the load balancer it is wrong in a way that looks right for a week.
Given the wire, the agent runs pktscope with the rst filter, or writes a probe like the 110-line one in the FIN post that prints one line per reset with its direction, the peer, the owning process and the socket's idle time before the write that got reset:
12:27:52 RST from 10.0.3.17:443 -> python[220588] 10.0.1.9:58330 idle 355.0s before the write that got reset
The reset arrived (rx), from the load balancer's address, five seconds past a 350-second idle timeout, on a socket the pool had kept open. Per RFC 9293, a reset "is sent whenever a segment arrives that apparently is not intended for the current connection," which is what a device that forgot the connection does when the pool writes to it. The agent now has the actor, the mechanism and the number. The same line settles the cross-team argument, because the proof that a problem is not on your side is who sent the first FIN or RST, and the socket-to-process join behind it is documented.
Partly, and the boundaries are specific enough to list, because an agent that concludes "nothing failed" from an empty table has been misled by the tool rather than informed by it.
pktscope and httpwatch capture at TCX, where HTTPS is opaque bytes. Reading the plaintext needs a uprobe on SSL_write and SSL_read, which is what httpscope does for OpenSSL and rustls; its Go crypto/tls taps are built but not attached yet, and TLS inside a container is not read yet, both stated in its own limits. grpcsnoop reads plaintext gRPC at the TC layer and says a TLS channel is ciphertext to it.pktscope pulls the SNI out of the ClientHello, so a failing handshake can be diagnosed to the side that rejected it.httpwatch states this in its own limits; if your internal services speak h2c, expect an empty table there and reach for grpcsnoop.container-traffic attributes it by cgroup. A Unix domain socket never touches TCP and produces nothing.pktscope decodes each packet alone, with no reassembly and no pcap export. When reassembly or decryption with keys is the requirement, its own README sends you to Wireshark, and so does this post.Safer than letting it run tcpdump there, for three reasons about the mechanism rather than about trust. Cost: a TCX tap returns TCX_NEXT on every path, so it is not in the request path, and an in-kernel scope like pktscope's --port is checked before a ring-buffer reservation, so cost scales with matched events rather than total traffic. The verifier: every eBPF program goes through the kernel's verifier, which rejects unbounded loops and out-of-bounds reads, so a probe the model gets wrong fails to load with a structured error rather than running badly; what eBPF is covers the model. Scope: the script runs inside a V8 isolate and the sandbox is deliberately narrow, with no fs, fetch, require or process, so a probe that can read every plaintext request cannot stash it in a file or dial out on its own. What leaves is what the runtime exposes on purpose: the console stream, a page served by a yeet service, or a yeet.alert to Slack.
The same runtime can enforce, which is how an HTTP/2 L7 firewall was built on it, but enforcement is a program a script loads on purpose, not something an observation script acquires by accident. The residual risk is what the agent can read, and that is governed as data, not as a chart.
When the thing you are troubleshooting is not a Linux host you can install a daemon on, or when you need history and a fleet-wide view that this approach does not keep.
What you give up with the host-side approach is retention, a query language over history and a fleet-wide service map. yeet keeps no data store; it aggregates across a fleet when a script reports to one place, but it is not where last Tuesday lives.
If the failing thing is a Linux host and the dashboards are green, install yeet on it, give the agent yeet graph query and yeet run, and point it at pktscope for resets, dialout for egress, dnssnoop for resolution, tcpsnoop for live connections and httpscope for HTTP it can query. If the failing thing is the switching fabric, the SD-WAN or the wireless estate, that is what NetBrain, Cisco AgenticOps and Selector are for, and a host-side probe is their last hop rather than their replacement. If the workloads are on Kubernetes and you want continuous capture with retention, Kubeshark's MCP server is the serious option. If you need reassembly or decryption with keys, it is still Wireshark.
The failure mode to avoid is the one that looks like progress: an agent with every chart, no packet, and a confident hypothesis you then deploy to test. An agent that can read the wire replaces that hypothesis with the line that names the sender, the process and the idle gap, and that is the difference between agentic network operations as a slide and as a thing that ended your incident.
Network operations where an AI agent investigates and, with approval, acts, rather than a human reading dashboards and typing commands. Vendors such as NetBrain, Cisco and Palo Alto Networks use the term for agents that reason over device telemetry, configurations and digital twins. On Linux hosts, yeet uses it for an agent that reads the live network from the kernel and writes its own probes, so the agent is not limited to what was collected in advance.
It can reason about configs, logs and whatever you paste, which is enough for a failure that reproduces and not enough for one that only happens in production at night. With yeet installed on the host, Claude Code can query the host's graph with yeet graph query and run eBPF scripts it writes with yeet run, so a reset, a DNS change or a TLS alert becomes something it reads rather than something it infers.
Attaching eBPF programs is privileged, but the privilege does not have to sit with the agent. With yeet the daemon performs the privileged load and yeet run and yeet graph query are unprivileged commands that never take sudo, so the agent holds no account, key or capability on the host. A Wireshark MCP server by contrast needs dumpcap granted capture capabilities or the server run as root.
Not today, and the yeet documentation says why: an MCP server exposes data a vendor already collected and stored, while yeet has the agent write and run the probe itself on the host and read the result directly. If you want yeet's output inside an MCP-speaking tool, stream it into that tool's data store and let its server expose it.
Not at the packet layer, where TLS is ciphertext. Reading the plaintext needs a uprobe on the process's SSL_write and SSL_read, which is how httpscope reads HTTPS from OpenSSL and rustls; its Go crypto/tls taps are not attached yet. The start of the TLS handshake is cleartext, so the hostname in the ClientHello and an alert sent before encryption begins are readable without any key.
From a packet tap that reports each RST with its direction, joined to the socket's owning process through the inode that /proc/net/tcp and the process's file descriptors share. pktscope on yeet shows the direction as rx or tx so the agent knows immediately whether the host sent the reset or received it, and the join to a pid follows from the surviving socket.
Yes, if it can read what the application resolved rather than what dig resolves now. dnssnoop on yeet emits one event per DNS query with the pid and command that asked, the domain, the A records returned, the resolver and the latency, which is how an agent catches a changed A record under a connection pool still dialing the old one.
list_l4_flows, capture_traffic and export_pcap; L7 queries cover live and historical traffic within the retention window with decrypted TLS.dumpcap capture capabilities with setcap or run under sudo, which the README labels "not recommended."yeet graph dump prints the system graph's schema and yeet graph query runs a query against it; yeet run runs a script from a path, a git repo (gh:), a URL or stdin and emits one line per console.log when stdout is a pipe; yeet service keeps scripts running and serves them on HTTP routes.fs, fetch, require or process.TCX_NEXT on every path; the in-kernel --port and --proto scope is checked before a ring-buffer reservation; the display filter accepts syn rst fin ack, rx tx and substrings; no reassembly, no pcap export./api/query in GraphQL; Go crypto/tls taps "built and pass their self-test, but the app does not attach them yet."pid, command, domain_name, resolved_addresses, the resolver's remote_ip and latency_ns.yeet graph query as a single allow rule, and the managed settings that holdBuilt with yeet, a JS runtime for writing eBPF programs on Linux machines. Join us on discord.