<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Philip Stayetski</title>
    <description>The latest articles on DEV Community by Philip Stayetski (@pstayet).</description>
    <link>https://dev.to/pstayet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3896740%2Ffbf5015f-af90-4277-b187-3176bd60f441.png</url>
      <title>DEV Community: Philip Stayetski</title>
      <link>https://dev.to/pstayet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pstayet"/>
    <language>en</language>
    <item>
      <title>Agent App vs MCP Server: The Honest Structural Difference</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Sun, 19 Jul 2026 21:32:38 +0000</pubDate>
      <link>https://dev.to/pstayet/agent-app-vs-mcp-server-the-honest-structural-difference-5c6d</link>
      <guid>https://dev.to/pstayet/agent-app-vs-mcp-server-the-honest-structural-difference-5c6d</guid>
      <description>&lt;p&gt;If you're building tools for AI agents, you've likely come across two approaches: &lt;strong&gt;agent apps&lt;/strong&gt; (installable local capability services) and &lt;strong&gt;MCP servers&lt;/strong&gt; (remote tools exposed via the Model Context Protocol). They look similar on the surface — both let agents do things beyond text completion — but they solve fundamentally different problems. Understanding the structural difference matters when you're deciding how to ship your own tool or evaluating what to wire into an agent pipeline.&lt;/p&gt;

&lt;p&gt;This article lays out the honest architectural distinction: typed local IPC versus a hosted JSON-RPC endpoint. Both are valid. They solve different halves of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an MCP Server Actually Is
&lt;/h2&gt;

&lt;p&gt;The Model Context Protocol (MCP) defines a standard way for an agent to discover and call tools on a remote server. You run an MCP server somewhere — locally as a subprocess, on a VM, or behind a URL — and the agent talks to it over JSON-RPC (usually stdio or HTTP+SSE).&lt;/p&gt;

&lt;p&gt;The core pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent ──JSON-RPC──&amp;gt; MCP Server (stdio / HTTP)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server announces its capabilities (tools, resources, prompts) at connect time. The agent calls tools by name with JSON arguments and gets JSON results back. It is an RPC protocol with a well-defined schema, and that's its strength: any agent that supports MCP can talk to any MCP server without custom integration code.&lt;/p&gt;

&lt;p&gt;The trade-off: the server is something you &lt;strong&gt;run and manage&lt;/strong&gt;. You pick the transport, handle the lifecycle, decide on authentication, and ensure uptime. MCP does not specify how the server is installed, verified, kept alive, or isolated — that is your responsibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Agent App Is
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;agent app&lt;/strong&gt; (as implemented by the Pilot Protocol app store) is a different model entirely. It is a typed IPC service that runs &lt;strong&gt;locally on the agent's own daemon&lt;/strong&gt;, installed with a single command and auto-spawned on demand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent ──JSON──&amp;gt; Daemon Supervisor ──spawns──&amp;gt; App (local IPC)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The loop is &lt;strong&gt;discover → install → call&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discover:&lt;/strong&gt; &lt;code&gt;pilotctl appstore catalogue&lt;/code&gt; lists every available app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View/Inspect:&lt;/strong&gt; &lt;code&gt;pilotctl appstore view &amp;lt;id&amp;gt;&lt;/code&gt; shows the manifest, permissions, and source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;code&gt;pilotctl appstore install &amp;lt;id&amp;gt;&lt;/code&gt; downloads the app, verifies its integrity, and registers it with the local daemon. No separate hosting, no manual wiring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Call:&lt;/strong&gt; &lt;code&gt;pilotctl appstore call &amp;lt;id&amp;gt; &amp;lt;app&amp;gt;.method '&amp;lt;json&amp;gt;'&lt;/code&gt; — the daemon spawns the app, routes the JSON request, collects the JSON response, and tears it down when idle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The structural differences from an MCP server are not cosmetic. They change who bears the operational cost and what guarantees you get.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Honest Breakdown
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Where It Runs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;MCP Server&lt;/th&gt;
&lt;th&gt;Agent App&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Host&lt;/td&gt;
&lt;td&gt;You provision and manage (local process, VM, container, or serverless)&lt;/td&gt;
&lt;td&gt;Daemon-managed local process, auto-spawned from install artifact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lifecycle&lt;/td&gt;
&lt;td&gt;You start/stop/monitor it&lt;/td&gt;
&lt;td&gt;Daemon supervises — spawns on call, idles, restarts on crash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;stdio, HTTP, SSE — requires a reachable endpoint&lt;/td&gt;
&lt;td&gt;Local IPC socket — no network exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An MCP server is a service you &lt;strong&gt;own the operations of&lt;/strong&gt;. An agent app is a capability you &lt;strong&gt;install and forget&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trust and Integrity
&lt;/h3&gt;

&lt;p&gt;MCP servers use whatever auth the implementer chooses — API keys, bearer tokens, mutual TLS, or nothing. The protocol does not define a trust model; the agent typically trusts whatever server it connects to.&lt;/p&gt;

&lt;p&gt;Agent apps have a built-in integrity model baked into the installation process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each app's manifest pins a &lt;strong&gt;sha256 hash&lt;/strong&gt; and an &lt;strong&gt;Ed25519 signature&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The daemon re-verifies the hash + signature on every spawn.&lt;/li&gt;
&lt;li&gt;Permissions are declared in the manifest and accepted at install time — no ambient authority.&lt;/li&gt;
&lt;li&gt;The app runs in a daemon-supervised sandbox; it has no access to the filesystem, network, or other apps unless the manifest declares it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is deliberately stronger than "trust the URL" because agent apps are installed from a shared catalogue where anyone can publish.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discovery
&lt;/h3&gt;

&lt;p&gt;MCP servers are discovered through directories (like &lt;a href="https://smithery.ai" rel="noopener noreferrer"&gt;smithery.ai&lt;/a&gt; or community lists). Each is a pointer to a URL or repo — the agent still needs to connect and introspect to learn what tools exist.&lt;/p&gt;

&lt;p&gt;Agent apps are &lt;strong&gt;runtime-discoverable&lt;/strong&gt; after install. Calling &lt;code&gt;&amp;lt;app&amp;gt;.help&lt;/code&gt; returns every method, its parameters, latency class, and cost — all as typed JSON, no network round-trip. The catalogue is queryable at any time with &lt;code&gt;pilotctl appstore catalogue&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protocol Surface
&lt;/h3&gt;

&lt;p&gt;MCP uses JSON-RPC 2.0 over a streaming transport. It has a well-specified initialization handshake, capability negotiation, and notification model. This is powerful for complex tool ecosystems but adds overhead for simple "call a thing, get a result" operations.&lt;/p&gt;

&lt;p&gt;Agent apps use raw JSON in → JSON out over a local IPC socket. No handshake, no capability negotiation, no streaming protocol — just input, output, and an error envelope on failure. The daemon handles transport, reliability, and spawning. The latency is negligible because there is no network.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Each Shines
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose an MCP server when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your tool requires server-side state, databases, or external API keys that shouldn't be distributed with the client.&lt;/li&gt;
&lt;li&gt;You already run infrastructure and want to expose an existing service to any MCP-compatible agent.&lt;/li&gt;
&lt;li&gt;You need streaming responses or long-running tool calls (MCP's notification pattern fits this better).&lt;/li&gt;
&lt;li&gt;You want broad interoperability across agent frameworks — MCP is supported by Claude Desktop, many LangChain integrations, and a growing ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose an agent app when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your tool is self-contained — it does not need a backend you host.&lt;/li&gt;
&lt;li&gt;You want agents to install and use your tool with zero ops overhead.&lt;/li&gt;
&lt;li&gt;Integrity matters: you want every invocation to be signature-verified before it runs.&lt;/li&gt;
&lt;li&gt;You are building for an ecosystem where agents discover, install, and compose capabilities autonomously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest answer is that many setups will use both. An MCP server is the right model for a hosted API gateway; an agent app is the right model for a packaged capability you want agents to self-serve.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Concrete Example
&lt;/h2&gt;

&lt;p&gt;An agent needs to research a topic. On the MCP side, it might connect to a web-search MCP server hosted at some endpoint — that server calls an upstream search API and returns results.&lt;/p&gt;

&lt;p&gt;On the agent-app side, it runs &lt;code&gt;pilotctl appstore call io.pilot.cosift cosift.search '{"q":"topic","k":"8"}'&lt;/code&gt; — the daemon spawns the &lt;code&gt;cosift&lt;/code&gt; app locally, which performs grounded web search and returns structured JSON. No server to host, no API key to provision, no connection to manage. The app was installed once, signature-verified, and is always available.&lt;/p&gt;

&lt;p&gt;Both produce search results. The difference is who owns the infrastructure between the agent and the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Agent apps and MCP servers are not competitors — they are different shapes for different operational realities. MCP is a wire protocol for tool interoperability across any agent and any server. Agent apps are a distribution and execution model for capabilities that install and run on the agent's own infrastructure.&lt;/p&gt;

&lt;p&gt;If you have a backend you already run, expose it as an MCP server. If you have a capability you want agents to discover and use with no infrastructure on your side, package it as an agent app.&lt;/p&gt;

&lt;p&gt;The Pilot Protocol app store is one implementation of the agent-app model. You can explore the catalogue at &lt;a href="https://pilotprotocol.network/app-store" rel="noopener noreferrer"&gt;pilotprotocol.network/app-store&lt;/a&gt; — and publish your own app via the &lt;code&gt;/publish&lt;/code&gt; flow. For most developers, the ideal strategy is to have both: an MCP server for your existing services, and an agent app for anything you want agents to self-install.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pilot Protocol is an open-source overlay network with an app store for agent-native capabilities. Install with &lt;code&gt;curl -fsSL https://pilotprotocol.network/install.sh | sh&lt;/code&gt; and explore the catalogue with &lt;code&gt;pilotctl appstore catalogue&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Publish an Agent App: Turn Your API Into a One-Command Install</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Sun, 19 Jul 2026 16:32:36 +0000</pubDate>
      <link>https://dev.to/pstayet/how-to-publish-an-agent-app-turn-your-api-into-a-one-command-install-1mik</link>
      <guid>https://dev.to/pstayet/how-to-publish-an-agent-app-turn-your-api-into-a-one-command-install-1mik</guid>
      <description>&lt;h2&gt;
  
  
  You have an API. Agents should be able to call it.
&lt;/h2&gt;

&lt;p&gt;You built a service — maybe a weather lookup, a company research endpoint, a code sandbox, a price feed. It works fine when a human pastes a curl command. But an autonomous AI agent? It needs discoverability, typed inputs, a contract it can read before calling. It needs an agent app.&lt;/p&gt;

&lt;p&gt;This is the walkthrough for someone who already has an API and wants to drop it into the Pilot app store — where agents discover, install, and call it with one command.&lt;/p&gt;




&lt;h2&gt;
  
  
  What "publishing an agent app" actually means
&lt;/h2&gt;

&lt;p&gt;An agent app on Pilot Protocol isn't a container or a server you ship. It's an &lt;strong&gt;adapter&lt;/strong&gt; — a typed JSON-in/JSON-out description of your API's methods that the local Pilot daemon installs as a supervised IPC service. Agents on the network install it with one command and call your API without writing any integration code.&lt;/p&gt;

&lt;p&gt;The publishing process is: &lt;strong&gt;describe your app → they build and sign the adapter → the team reviews → it's live in the catalogue.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You never upload code. You never hand over your API keys. You describe what your methods do, and Pilot generates the adapter for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before you start
&lt;/h2&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A working API&lt;/strong&gt; (public or with a documented shape). Agents call it over the internet, so it needs to be reachable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A valid email.&lt;/strong&gt; Pilot uses this to send you a submission confirmation and the review decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A name and a short description&lt;/strong&gt; for your app. Think about what an agent would search for.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. No SDK to install, no container to build, no repository to maintain.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Go to the publish page
&lt;/h2&gt;

&lt;p&gt;Navigate to &lt;strong&gt;pilotprotocol.network/publish&lt;/strong&gt;. The form is a 7-step wizard — it walks you through everything in order.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ The page shows a "Publishing needs a desktop" notice on small screens. Open it on a desktop browser to see the full form.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 2: Email (Step 1 of 7)
&lt;/h2&gt;

&lt;p&gt;Enter your email address. Pilot sends a confirmation so they can reach you about your submission and the review decision. This is also where you'll get notified when your app goes live or needs changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Identity (Step 2 of 7)
&lt;/h2&gt;

&lt;p&gt;This is about who you are as a publisher. You provide your name and optionally a handle or organization name that appears alongside your app in the catalogue.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Backend (Step 3 of 7)
&lt;/h2&gt;

&lt;p&gt;Describe the backend your app talks to. This is the API base URL or endpoint. You don't upload credentials — Pilot's model is that &lt;strong&gt;secrets stay with the operator&lt;/strong&gt;. At install time, the person running the agent supplies their own API keys for your service.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Methods (Step 4 of 7)
&lt;/h2&gt;

&lt;p&gt;This is the meat of the submission. Each method is one thing your API does. For each method you describe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt; — a short identifier agents use to call it (e.g. &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;lookup&lt;/code&gt;, &lt;code&gt;analyze&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt; — what this method does, in plain language the agent's LLM can read to decide whether to call it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input parameters&lt;/strong&gt; — what the agent sends you (name, type, required/optional, a description)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output shape&lt;/strong&gt; — what your API returns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Pilot team uses these descriptions to build a typed JSON adapter. An agent that installs your app calls &lt;code&gt;&amp;lt;app&amp;gt;.&amp;lt;method&amp;gt;&lt;/code&gt; with JSON input and gets JSON output — no curl, no parsing, no conditional branches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make your descriptions agent-friendly.&lt;/strong&gt; A good method description reads like "Search for a company by domain name and return its industry, employee count, and head office location" — not "POST /v2/search with q param."&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6: Listing (Step 5 of 7)
&lt;/h2&gt;

&lt;p&gt;Catalogue details: a full description for the app store listing, a logo or icon URL if you have one, and a website link. This is what agents (and humans browsing the app store) see.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7: Vendor (Step 6 of 7)
&lt;/h2&gt;

&lt;p&gt;Contact details and any support URL. Pilot uses this if there's an issue with your app. It's also how the review team reaches you during the approval process.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8: Review and release (Step 7 of 7)
&lt;/h2&gt;

&lt;p&gt;The final step shows you a summary of everything you entered. Before submitting you confirm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have the right to publish this app and grant Pilot permission to distribute it&lt;/li&gt;
&lt;li&gt;You agree to the &lt;a href="https://pilotprotocol.network/terms" rel="noopener noreferrer"&gt;Terms&lt;/a&gt;, &lt;a href="https://pilotprotocol.network/aup" rel="noopener noreferrer"&gt;Acceptable Use Policy&lt;/a&gt;, and &lt;a href="https://pilotprotocol.network/publisher-agreement" rel="noopener noreferrer"&gt;Publisher Release Agreement&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Submit when ready.&lt;/p&gt;




&lt;h2&gt;
  
  
  What happens next
&lt;/h2&gt;

&lt;p&gt;Pilot's team reviews your submission. The review checks that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The method descriptions match what the API actually does&lt;/li&gt;
&lt;li&gt;The adapter it generates works correctly&lt;/li&gt;
&lt;li&gt;The app doesn't violate the Acceptable Use Policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once approved, your app appears in the &lt;strong&gt;app store catalogue&lt;/strong&gt;. Any agent on the network finds it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pilotctl appstore catalogue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And installs it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pilotctl appstore &lt;span class="nb"&gt;install&lt;/span&gt; &amp;lt;your-app-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your API is now an agent-native tool. No additional code on your side. No integration maintenance. The agent calls it as a typed service — JSON in, JSON out, supervised by the daemon.&lt;/p&gt;




&lt;h2&gt;
  
  
  What kind of APIs make good agent apps
&lt;/h2&gt;

&lt;p&gt;The best candidates are APIs that an autonomous agent would naturally reach for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lookup and research APIs&lt;/strong&gt; — company data, person enrichment, domain info, patent search&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price and market data&lt;/strong&gt; — crypto, FX, stocks, commodities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weather and environmental data&lt;/strong&gt; — forecast, air quality, marine, wildfire&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Translation and language services&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code execution or sandbox APIs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Any API you'd want an agent to call without you writing integration logic&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your API already has a documented REST shape and you can describe each endpoint's intent in a sentence, it's a good fit.&lt;/p&gt;




&lt;h2&gt;
  
  
  No-code publishing, agent-native consumption
&lt;/h2&gt;

&lt;p&gt;The loop is asymmetric by design: &lt;strong&gt;you publish without writing code&lt;/strong&gt;, and the &lt;strong&gt;agent consumes without writing code&lt;/strong&gt;. The adapter Pilot generates for you is signed and verified — the daemon re-checks the manifest's sha256 hash and ed25519 signature each time your app is spawned, so the agent never runs an untrusted adapter. At install time, the operator's secrets stay with the operator — your app just defines the shape.&lt;/p&gt;

&lt;p&gt;This is the same model that lets agents chain multiple Pilot apps into a single workflow: install a research app, a web scraping app, and a notification app, and the agent calls them in sequence, piping JSON output to JSON input, without you ever writing a line of middleware.&lt;/p&gt;




&lt;h2&gt;
  
  
  Ready to publish?
&lt;/h2&gt;

&lt;p&gt;Head over to the &lt;a href="https://pilotprotocol.network/publish" rel="noopener noreferrer"&gt;publish page&lt;/a&gt; and start the 7-step wizard. Describe your app, confirm your email, and let the platform generate the adapter. Your API becomes an agent-native tool in a single submission cycle.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>agents</category>
      <category>api</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Stateful vs Stateless Agents: The Hidden Cost of Starting Fresh Every Loop</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Sun, 19 Jul 2026 12:12:57 +0000</pubDate>
      <link>https://dev.to/pstayet/stateful-vs-stateless-agents-the-hidden-cost-of-starting-fresh-every-loop-235g</link>
      <guid>https://dev.to/pstayet/stateful-vs-stateless-agents-the-hidden-cost-of-starting-fresh-every-loop-235g</guid>
      <description>&lt;p&gt;Every time an autonomous agent completes a task loop — calls an API, processes the result, decides the next action — it has to re-establish its identity and environment from scratch if it's truly stateless. That's not a design debate anymore; it's an operational cost that compounds with every iteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Loop You Aren't Counting
&lt;/h2&gt;

&lt;p&gt;Picture a stateless agent running on a serverless function. It starts, authenticates to two or three services (each requiring its own handshake or token refresh), discovers which peers or tools are available, hydrates some context from a database, does its work, and shuts down. Next invocation: same thing. Re-auth. Re-discovery. Cold start.&lt;/p&gt;

&lt;p&gt;This is the default architecture for many agent deployments because it's simple to reason about and maps cleanly onto existing cloud infrastructure. But the hidden cost is real: every loop pays the setup tax. For a single-turn agent, that's noise. For an agent that runs hourly — or one that maintains ongoing conversations with other agents — it dominates the latency budget.&lt;/p&gt;

&lt;p&gt;The divide between &lt;strong&gt;stateful vs stateless agents&lt;/strong&gt; isn't about storing conversation history in a database. It's about whether the agent itself holds any durable identity that survives the gap between invocations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Statelessness Bites
&lt;/h2&gt;

&lt;p&gt;Three costs show up in practice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repeated authentication.&lt;/strong&gt; Every invocation means re-proving identity. Token refreshes, JWTs, session cookies — each requires a round trip to an auth server. If the agent talks to multiple services, each one needs its own handshake. Multiply that by the number of invocations per hour, and the overhead accumulates fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Re-discovery of peers and capabilities.&lt;/strong&gt; A stateless agent that needs to coordinate with other agents or talk to specialist services must discover what's available each time. That means directory lookups, capability negotiation, or hardcoded endpoints — all of which break when the network changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cold-start context loss.&lt;/strong&gt; The agent's working state — what it was doing, where it left off, which peers it was in conversation with — has to be serialized and stored between invocations. Serialization is lossy. The agent picks up with a snapshot, not a live connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Case for a Persistent Address
&lt;/h2&gt;

&lt;p&gt;A stateful agent holds a continuous identity. It can maintain long-lived connections, respond to inbound messages from peers without polling, and keep cryptographic state (session keys, negotiated parameters) alive across invocations. The natural consequence is a persistent network address: something that stays the same no matter where the agent runs or how many times it restarts.&lt;/p&gt;

&lt;p&gt;Persistent addressing means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One-time trust establishment.&lt;/strong&gt; Handshake once with a peer or service; the relationship holds across restarts. No re-auth per loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push, not poll.&lt;/strong&gt; Peers can send messages to the agent's address without waiting for it to wake up and ask. That shifts the model from "agent asks the world" to "the world notifies the agent."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State continuity.&lt;/strong&gt; Connections and cryptographic sessions survive the agent being offline. When it restarts, the old keys and relationships are still valid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is common ground with VPN overlays and mesh networks — but those were designed for devices, not agents. An agent overlay network gives the same durable addressing without requiring a full network interface, routing table, or device-level setup. The identity lives at the agent level, not the machine level.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Give Up Going Stateful
&lt;/h2&gt;

&lt;p&gt;Stateful isn't free. The trade-offs are real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Colder operation.&lt;/strong&gt; Stateless is easier: spin up, work, spin down. Stateful means managing who can reach you, what state you keep, and what happens to it when you move.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State management.&lt;/strong&gt; A persistent address only matters if the address allocation doesn't break when the agent moves across machines. That requires the overlay to handle mobility transparently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attack surface.&lt;/strong&gt; A reachable agent is a reachable agent. Stateless agents are mostly invisible between invocations; stateful ones are always on the network, so they need authentication on every inbound message.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where Each Model Fits
&lt;/h2&gt;

&lt;p&gt;The stateless model works well for simple, single-purpose agents: check the weather, post a notification, run a quick lookup. The agent fires, does one thing, and exits. Any identity setup paid on every invocation is small relative to the actual work.&lt;/p&gt;

&lt;p&gt;The stateful model earns its weight for agents that coordinate with each other, maintain ongoing conversations, or need to be discovered by peers without polling. A research agent that delegates subtasks, a monitoring agent that watches for events, or a multi-agent system where agents hand off work between invocations — these benefit from a persistent address because they'd otherwise pay the re-establishment cost on every delegation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hybrid That Actually Works
&lt;/h2&gt;

&lt;p&gt;Most production systems land somewhere in between. An agent stays stateless for the hot path — fast, disposable execution — but maintains a persistent overlay address for discovery and trust. Other agents and services reach it by that address; when it's offline they queue messages. When it fires up, it reconnects with its existing identity, drains the queue, and gets to work.&lt;/p&gt;

&lt;p&gt;This gives you the operational simplicity of stateless execution (no long-running daemon, no keepalive management) while keeping the identity continuity that makes multi-agent coordination practical. The agent doesn't need to be "always on" — just always reachable at the same address.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;When you design an agent system, don't default to fully stateless or fully stateful. Ask where your agent pays the re-establishment tax most often: on every loop, or only on infrequent cold starts. If it's every loop — if your agent talks to peers, maintains relationships, or delegates work — a persistent address changes the math. One-time identity establishment instead of per-loop re-auth. Push messages instead of polling. Trust that survives restarts.&lt;/p&gt;

&lt;p&gt;Stateful vs stateless agents isn't a purity contest. It's a cost equation, and the cost side is bigger than most architecture discussions admit.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pilot Protocol is an open-source overlay network that gives AI agents a persistent virtual address with encrypted tunnels and NAT traversal. Install it in one command:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://pilotprotocol.network/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Then discover, install, and call agent-native apps from the &lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;Pilot app store&lt;/a&gt;:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pilotctl appstore catalogue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>networking</category>
      <category>architecture</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Submit an IETF Internet Draft: The Datatracker Walkthrough</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Sat, 18 Jul 2026 20:05:31 +0000</pubDate>
      <link>https://dev.to/pstayet/how-to-submit-an-ietf-internet-draft-the-datatracker-walkthrough-4cdm</link>
      <guid>https://dev.to/pstayet/how-to-submit-an-ietf-internet-draft-the-datatracker-walkthrough-4cdm</guid>
      <description>&lt;h1&gt;
  
  
  How to Submit an IETF Internet Draft: The Datatracker Walkthrough
&lt;/h1&gt;

&lt;p&gt;The IETF Datatracker looks deceptively simple. You log in, upload a document, hit submit. But between draft naming conventions, revision cadence rules, and the fact that one wrong filename prefix can get your submission rejected by the automated tooling, the first submission almost always goes wrong somehow.&lt;/p&gt;

&lt;p&gt;I recently went through this for the first time — submitting the &lt;a href="https://pilotprotocol.network/blog" rel="noopener noreferrer"&gt;Pilot Protocol&lt;/a&gt; agent-transport specification as an individual Internet-Draft. Here's what the Datatracker actually asks for, how draft naming works, and what the revision cycle looks like in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Datatracker: Where Submissions Happen
&lt;/h2&gt;

&lt;p&gt;All IETF Internet-Draft submissions go through &lt;a href="https://datatracker.ietf.org" rel="noopener noreferrer"&gt;datatracker.ietf.org&lt;/a&gt;. You need a Datatracker account, which requires an existing IETF or liaison relationship to create — the signup flow verifies your email against an approved domain or asks for a reference from an existing participant. If you're an individual contributor without an existing IETF relationship, you'll need a short email with a sponsor to get your account approved.&lt;/p&gt;

&lt;p&gt;Once logged in, the submission page is straightforward: you upload a file in one of the accepted formats (XML v3 is the canonical format; plain text with the boilerplate works too), fill in a few metadata fields, and submit. The system validates your document for formatting compliance before accepting it.&lt;/p&gt;

&lt;p&gt;The two things that trip up first-time submitters are the filename and the boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Draft Naming Convention
&lt;/h2&gt;

&lt;p&gt;Every Internet-Draft gets a name in this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;draft-&amp;lt;author-or-prefix&amp;gt;-&amp;lt;topic&amp;gt;-&amp;lt;version-number&amp;gt;.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;author-or-prefix&amp;gt;&lt;/code&gt; is typically your last name or a short group identifier. The &lt;code&gt;&amp;lt;topic&amp;gt;&lt;/code&gt; is a hyphen-separated slug describing the draft. The version number starts at &lt;code&gt;00&lt;/code&gt; and increments with each revision.&lt;/p&gt;

&lt;p&gt;For the Pilot Protocol submission, the two drafts are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;draft-teodor-pilot-problem-statement-01&lt;/code&gt; — the Informational track document describing why agents need network-layer infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;draft-teodor-pilot-protocol-01&lt;/code&gt; — the Experimental track document with the full wire specification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;teodor&lt;/code&gt; prefix comes from the author's last name (individual submissions use the submitter's name). The &lt;code&gt;-01&lt;/code&gt; suffix means these are on their second revision. A brand-new draft starts at &lt;code&gt;-00&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One critical rule:&lt;/strong&gt; the filename must match the document title's draft name. The Datatracker parses the first line of your document to extract the draft name, and if the filename on disk doesn't match what's declared in the document body, the submission will be rejected during validation. Always check that the filename and the document's own &lt;code&gt;Internet-Draft&lt;/code&gt; header line agree before uploading.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Boilerplate You Must Include
&lt;/h2&gt;

&lt;p&gt;Every Internet-Draft needs specific boilerplate text near the top. Missing it is the most common validation failure. The required elements are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Status of This Memo&lt;/strong&gt; — a standard paragraph declaring this is an Internet-Draft, that it expires, and what category it belongs to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copyright Notice&lt;/strong&gt; — the standard IETF Trust copyright.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abstract&lt;/strong&gt; — a brief summary of the document's purpose.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The exact wording for each category (Informational, Experimental, Standards Track) is specified in &lt;a href="https://www.rfc-editor.org/rfc/rfc7841.html" rel="noopener noreferrer"&gt;RFC 7841&lt;/a&gt; and the current &lt;a href="https://www.ietf.org/standards/ids/" rel="noopener noreferrer"&gt;Internet-Draft Guidelines&lt;/a&gt;. The Datatracker's own submission page links to templates — use them rather than guessing.&lt;/p&gt;

&lt;p&gt;For the Pilot drafts, the boilerplate declares Experimental status for the protocol spec (since it describes an active implementation under development, not a finalized protocol) and Informational for the problem statement (which surveys the landscape without specifying a protocol).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Revision Cadence
&lt;/h2&gt;

&lt;p&gt;An Internet-Draft expires &lt;strong&gt;six months&lt;/strong&gt; after its last revision. The Datatracker tracks this automatically and will show an expiration date on the draft's page.&lt;/p&gt;

&lt;p&gt;To keep a draft alive, you resubmit an updated version before the six-month mark. Each resubmission increments the version number by one (&lt;code&gt;-00&lt;/code&gt; → &lt;code&gt;-01&lt;/code&gt; → &lt;code&gt;-02&lt;/code&gt;, etc.). You can submit revisions as often as you like — there is no minimum interval. Some working groups require a revision before every meeting; other drafts sit untouched for five months and get one quick resubmission to stay alive.&lt;/p&gt;

&lt;p&gt;A revision does not have to contain substantive changes. Many drafts that are stable between meetings are resubmitted with only a date change in the boilerplate to reset the clock. The Datatracker handles this gracefully — it accepts minor updates and keeps the same document name with the incremented version.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens After Submission
&lt;/h2&gt;

&lt;p&gt;After you hit submit on the Datatracker:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Automated validation&lt;/strong&gt; runs within seconds — checks filename, boilerplate, formatting, missing references.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The draft appears on the Datatracker&lt;/strong&gt; within minutes, publicly accessible at &lt;code&gt;https://datatracker.ietf.org/doc/draft-&amp;lt;name&amp;gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Internet-Draft repository&lt;/strong&gt; at &lt;code&gt;https://www.ietf.org/archive/id/&lt;/code&gt; mirrors it with a short delay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The secretariat reviews&lt;/strong&gt; for IETF-process compliance (not technical correctness) — this can take a day or two.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The draft is now citable&lt;/strong&gt; by its draft name. Anyone can reference &lt;code&gt;draft-teodor-pilot-protocol-01&lt;/code&gt; in papers, other drafts, or RFCs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is no editorial review of technical content at this stage for individual submissions — that comes later if the draft is adopted by a working group or submitted to the IESG for publication. An individual Internet-Draft is a public statement that the problem and solution exist, not an endorsement by the IETF.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Tips from a First Submission
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Submit XML v3 if you can.&lt;/strong&gt; The xml2rfc toolchain produces perfectly formatted text and HTML output. Writing plain-text drafts by hand is possible but error-prone — the page margins, line lengths, and section numbering rules are strict.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the idnits tool&lt;/strong&gt; before submitting. It's available at &lt;code&gt;https://www.ietf.org/tools/idnits/&lt;/code&gt; and catches most boilerplate, reference, and formatting issues the Datatracker's validator will flag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check your references.&lt;/strong&gt; If your draft cites RFCs or other drafts, the identifiers must match exactly what the RFC Editor uses. The idnits tool checks this too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick your document stream up front.&lt;/strong&gt; Individual submissions go through the Independent Stream; working-group submissions go through the IETF Stream. The stream affects the boilerplate text and the publication path.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full process for the Pilot drafts is documented on the &lt;a href="https://pilotprotocol.network/blog/ietf-internet-draft-pilot-protocol" rel="noopener noreferrer"&gt;Pilot Protocol blog&lt;/a&gt;, including links to both live drafts on the Datatracker if you want to see what a real submission looks like end to end.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How long does the Datatracker account approval take?
&lt;/h3&gt;

&lt;p&gt;Typically 1–3 business days, depending on whether your sponsor responds promptly. The IETF secretariat processes these manually during business hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I submit a draft without a Datatracker account?
&lt;/h3&gt;

&lt;p&gt;No. The submission system requires authentication. If you're collaborating, one author with an account can submit on behalf of the group.&lt;/p&gt;

&lt;h3&gt;
  
  
  What happens if my draft expires?
&lt;/h3&gt;

&lt;p&gt;It is removed from the active Internet-Drafts directory but remains in the archive at the same URL. You can submit a new version at any time to reactivate it, starting from the previous version number.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can an AI agent submit an Internet-Draft automatically?
&lt;/h3&gt;

&lt;p&gt;In theory, if an agent holds Datatracker credentials, it can upload a file through the submission API. The Pilot Protocol app store includes tools for agent-native API access, but the IETF submission process itself still requires a human account holder to own the credentials — no automated tooling can bypass the identity verification step.&lt;/p&gt;

</description>
      <category>networking</category>
      <category>ietf</category>
      <category>tutorial</category>
      <category>protocols</category>
    </item>
    <item>
      <title>Headscale vs Nebula: Self-Hosted Overlay Networks Compared</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Sat, 18 Jul 2026 15:14:07 +0000</pubDate>
      <link>https://dev.to/pstayet/headscale-vs-nebula-self-hosted-overlay-networks-compared-3b16</link>
      <guid>https://dev.to/pstayet/headscale-vs-nebula-self-hosted-overlay-networks-compared-3b16</guid>
      <description>&lt;p&gt;If you're evaluating self-hosted overlay networks in 2026, two names come up constantly: &lt;strong&gt;Headscale&lt;/strong&gt; and &lt;strong&gt;Nebula&lt;/strong&gt;. Both are open source. Both let you build a private mesh without relying on a third-party service. But they take radically different approaches to the same problem, and which one fits your use case depends heavily on what kind of traffic you're routing and who — or what — your nodes actually are.&lt;/p&gt;

&lt;p&gt;This comparison walks through the architecture, deployment model, and tradeoffs of each, then looks at where the requirements start to diverge when the nodes are AI agents instead of servers or laptops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headscale: Tailscale for People Who Want Full Control
&lt;/h2&gt;

&lt;p&gt;Headscale is an open-source implementation of the Tailscale coordination server. It provides the same centralized control-plane model: nodes register with a server, the server distributes cryptographic keys and ACLs, and nodes connect directly to each other via WireGuard tunnels when possible, falling back to DERP relay servers when NAT or firewalls block direct connections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; A single headscale server (or cluster) acts as the coordination point. Each node runs Tailscale's open-source client, which authenticates with headscale, receives its node key and ACL policy, then negotiates WireGuard tunnels to every other node it's authorized to reach. Traffic is encrypted end-to-end by WireGuard. The headscale server itself never sees data-plane traffic — it only handles coordination, key distribution, and NAT traversal signaling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it's good at:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Small-to-medium device meshes (tens to low hundreds of nodes)&lt;/li&gt;
&lt;li&gt;Teams that want a Tailscale-like experience without paying for Tailscale's SaaS&lt;/li&gt;
&lt;li&gt;Environments that already use WireGuard and want to layer identity and ACLs on top&lt;/li&gt;
&lt;li&gt;Human-operated device access (SSH, web UIs, database connections)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where it struggles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The central control plane is a single point of failure and a coordination bottleneck&lt;/li&gt;
&lt;li&gt;Scaling beyond a few hundred active nodes puts strain on the server&lt;/li&gt;
&lt;li&gt;Each node maintains a WireGuard tunnel to every other node it can reach — O(n²) state for the mesh&lt;/li&gt;
&lt;li&gt;DERP relay performance varies; relayed traffic adds latency and bandwidth on the relay node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Headscale is an excellent choice for a team of developers or a small organization that needs private, zero-trust connectivity between devices. The user experience, inherited from Tailscale's design, is polished and familiar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nebula: Lighthouse-Based Mesh at Scale
&lt;/h2&gt;

&lt;p&gt;Nebula, originally built by Slack and now maintained as an open-source project under the Linux Foundation, takes a fundamentally different architectural approach. Instead of a centralized control plane, it uses a distributed &lt;em&gt;lighthouse&lt;/em&gt; model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; Nebula nodes (called "hosts") discover each other through one or more lighthouse nodes. The lighthouse's job is purely directory and NAT traversal assistance — it tells node A how to reach node B, but it never routes or relays traffic between them. Once nodes have each other's addresses, they establish encrypted tunnels directly using Nebula's own protocol (not WireGuard). Nebula uses certificate-based authentication: a certificate authority signs host certificates that encode the host's identity, IP address within the overlay, and group membership.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it's good at:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Larger meshes (hundreds to thousands of nodes)&lt;/li&gt;
&lt;li&gt;Site-to-site connectivity where traffic patterns are predictable&lt;/li&gt;
&lt;li&gt;Environments where you want no single point of failure in the data or control path&lt;/li&gt;
&lt;li&gt;Infrastructure that already uses certificate-based identity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where it struggles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No built-in relay fallback — if two nodes can't establish a direct tunnel, they can't communicate&lt;/li&gt;
&lt;li&gt;The CLI and configuration surface are more bare-metal than Headscale's&lt;/li&gt;
&lt;li&gt;Lighthouse scoping requires thought: too few lighthouses creates a bottleneck, too many creates coordination overhead&lt;/li&gt;
&lt;li&gt;Certificates need their own lifecycle management (rotation, revocation, distribution)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nebula shines in infrastructure-grade deployments where traffic patterns are stable, node count is high, and the team has the operational maturity to manage certificates and lighthouse topology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Node Identity Changes Everything
&lt;/h2&gt;

&lt;p&gt;Both Headscale and Nebula were designed for &lt;em&gt;device&lt;/em&gt; or &lt;em&gt;user&lt;/em&gt; identity. A node is a server, a laptop, a container — something with a stable hostname and an operator on the other end. The overlay makes that device reachable from anywhere.&lt;/p&gt;

&lt;p&gt;AI agents are not devices. They are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ephemeral:&lt;/strong&gt; An agent spins up, does work, and terminates. It may have seconds of uptime. Registering it with a control plane and negotiating a full mesh every time is wasted work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transient in address:&lt;/strong&gt; An agent can move between clouds, containers, and serverless runtimes multiple times a minute. Its IP changes constantly — even within a single session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust-dynamic:&lt;/strong&gt; Agents from different teams, organizations, or frameworks need to collaborate on one task and never talk again. Full mesh membership is the wrong scope. Per-peer, per-session trust is what matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traffic-shaped differently:&lt;/strong&gt; Agents don't stream terminals or files. They exchange structured data — JSON payloads, function calls, context blocks. A tunnel designed for TCP streams adds unnecessary overhead for small, frequent messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Headscale's full-mesh model means every new agent registers, gets a key, and tunnels to every other node — O(n) setup time that grows with every peer. Nebula's lighthouse model avoids the central bottleneck, but the lack of relay fallback means two agents behind NAT can't talk at all without help.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilot Protocol: Built for Agent-Shaped Traffic
&lt;/h2&gt;

&lt;p&gt;Pilot Protocol was designed from the ground up for AI agents, not devices. It's an open-source overlay network that gives every agent a permanent virtual address — one that survives restarts, IP changes, and cloud migrations — without needing a full-mesh tunnel to every peer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it differs from both approaches:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No central control plane.&lt;/strong&gt; Discovery uses a rendezvous registry, not a coordination server. There is no single point of failure and no server that sees all traffic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT traversal by default.&lt;/strong&gt; STUN + hole-punching + beacon relay fallback. Agents behind any NAT topology are reachable without manual relay configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-peer trust, not mesh membership.&lt;/strong&gt; Trust is explicit and bidirectional — one handshake at a time. Joining the network does not imply trusting everyone on it. This is the opposite of a VPN where membership equals trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent-native tools.&lt;/strong&gt; The app store delivers capabilities as typed IPC services — discover, install, call. An agent finds what it needs at runtime through &lt;code&gt;pilotctl appstore catalogue&lt;/code&gt;, not pre-configured tunnel ACLs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permanent virtual addressing.&lt;/strong&gt; Move an agent between three clouds in one session. It keeps its address. There is no re-registration, no tunnel teardown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;243k+ agents already use the network, and the protocol is pure Go with zero external dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Should You Choose?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Constraint&lt;/th&gt;
&lt;th&gt;Headscale&lt;/th&gt;
&lt;th&gt;Nebula&lt;/th&gt;
&lt;th&gt;Pilot Protocol&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Node type&lt;/td&gt;
&lt;td&gt;Human-operated devices&lt;/td&gt;
&lt;td&gt;Infrastructure hosts&lt;/td&gt;
&lt;td&gt;AI agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Traffic pattern&lt;/td&gt;
&lt;td&gt;Persistent tunnels&lt;/td&gt;
&lt;td&gt;Site-to-site / host-to-host&lt;/td&gt;
&lt;td&gt;Ephemeral, structured data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NAT traversal&lt;/td&gt;
&lt;td&gt;DERP relay (built-in)&lt;/td&gt;
&lt;td&gt;None (direct only)&lt;/td&gt;
&lt;td&gt;STUN + hole-punch + beacon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust model&lt;/td&gt;
&lt;td&gt;Mesh membership&lt;/td&gt;
&lt;td&gt;CA certificates&lt;/td&gt;
&lt;td&gt;Per-peer handshake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scale ceiling&lt;/td&gt;
&lt;td&gt;Low hundreds&lt;/td&gt;
&lt;td&gt;Thousands&lt;/td&gt;
&lt;td&gt;Designed for agent density&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosted&lt;/td&gt;
&lt;td&gt;Yes (one server)&lt;/td&gt;
&lt;td&gt;Yes (lighthouse(s))&lt;/td&gt;
&lt;td&gt;Optional (rendezvous)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Headscale is the right choice for a team needing a self-hosted, device-first overlay with a polished UI. Nebula wins for infrastructure-scale meshes where teams can manage certificates. For AI agents — ephemeral, address-changing, trust-dynamic — neither model maps cleanly, which is exactly why Pilot Protocol starts from a different set of assumptions.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pilot Protocol is open source (AGPL-3.0) and built in Go. Source at &lt;a href="https://github.com/pilot-protocol" rel="noopener noreferrer"&gt;github.com/pilot-protocol&lt;/a&gt;. To see how it works:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://pilotprotocol.network/install.sh | sh
pilotctl appstore catalogue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>networking</category>
      <category>opensource</category>
      <category>devops</category>
      <category>comparison</category>
    </item>
    <item>
      <title>AES-GCM vs ChaCha20-Poly1305: A Practical Comparison for Protocol Designers</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Fri, 17 Jul 2026 23:33:10 +0000</pubDate>
      <link>https://dev.to/pstayet/aes-gcm-vs-chacha20-poly1305-a-practical-comparison-for-protocol-designers-5ef</link>
      <guid>https://dev.to/pstayet/aes-gcm-vs-chacha20-poly1305-a-practical-comparison-for-protocol-designers-5ef</guid>
      <description>&lt;p&gt;If you build anything with transport security — VPNs, tunnels, messaging protocols, or encrypted overlay networks — you've met two dominant AEAD constructions: &lt;strong&gt;AES-256-GCM&lt;/strong&gt; and &lt;strong&gt;ChaCha20-Poly1305&lt;/strong&gt;. Both give you authenticated encryption (confidentiality + integrity in one pass), but they take very different engineering paths to get there.&lt;/p&gt;

&lt;p&gt;This is a practical comparison for developers choosing between them: the hardware landscape, the threat models each handles better, and the trade-offs that actually matter in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  What they are
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AES-GCM&lt;/strong&gt; (Galois/Counter Mode) combines AES block encryption in CTR mode with a GHASH polynomial authenticator. It's been the default for TLS 1.2 and IPsec for over a decade. NIST-standard, FIPS-140-certifiable, and backed by dedicated CPU instructions (AES-NI + PCLMULQDQ) on virtually every modern x86 and ARM chip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ChaCha20-Poly1305&lt;/strong&gt; is a stream cipher (ChaCha20) paired with a Poly1305 MAC. Designed by Daniel J. Bernstein, it does not use AES at all — it operates on 512-bit blocks with ARX (add-rotate-XOR) primitives. Standardised in RFC 8439, mandatory in TLS 1.3, and the default for SSH, WireGuard, and a growing share of HTTPS connections (especially on mobile).&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware acceleration: the real divide
&lt;/h2&gt;

&lt;p&gt;The single most important practical difference is whether the CPU has AES-NI.&lt;/p&gt;

&lt;p&gt;On x86-64 with AES-NI + PCLMULQDQ, AES-256-GCM encrypts at around 1–3 cycles per byte — extremely fast. On mobile ARM with the ARMv8 Crypto Extensions, the same. &lt;strong&gt;With hardware acceleration, AES-GCM is usually faster than ChaCha20-Poly1305.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without it — on older ARM Cortex-A cores, low-power MCUs, or software-only fallback paths — AES-GCM slows down dramatically. AES's S-box substitution is expensive in pure software. ChaCha20-Poly1305, which runs entirely on ARX operations, has no such penalty. &lt;strong&gt;Without hardware AES, ChaCha20-Poly1305 is typically 3–5x faster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is why you see ChaCha20-Poly1305 everywhere in mobile-first protocols (WireGuard, TLS to mobile clients). It guarantees good performance on hardware where AES acceleration is absent or disabled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Side-channel and security posture
&lt;/h2&gt;

&lt;p&gt;Both ciphers are considered cryptographically sound, but their side-channel profiles differ.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AES-GCM&lt;/strong&gt; has a well-known nonce reuse vulnerability: encrypting two messages with the same 96-bit nonce and key leaks the GHASH authentication key, allowing forgeries. With a 96-bit nonce, a random nonce collision begins to become likely after about 2^32 messages (the birthday bound). For high-volume protocols, this is a real concern — TLS 1.3 mitigates it with record sequence numbers, but not every protocol has that luxury.&lt;/p&gt;

&lt;p&gt;GCM is also &lt;strong&gt;incrementally slower with short messages&lt;/strong&gt; in software, because the GHASH polynomial multiplication has setup overhead. OpenSSL and BoringSSL have constant-time GCM implementations for x86, but careful implementation is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ChaCha20-Poly1305&lt;/strong&gt; is more forgiving. A 96-bit nonce is standard here too, and reuse is equally catastrophic, but the cipher's underlying structure is naturally constant-time on almost any architecture — no lookup tables, no secret-dependent branches. It also has a larger POLY1305 tag (128-bit) with better forgery bounds than GCM's GHASH, though this rarely matters in practice at standard message sizes.&lt;/p&gt;

&lt;p&gt;The XChaCha20 variant (extended 192-bit nonce) is worth mentioning: the larger nonce eliminates random-collision risk entirely for most practical workloads, making it much safer for protocols that cannot guarantee unique nonces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where each shines
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose AES-GCM when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run on x86-64 with AES-NI or ARMv8 Crypto Extensions (the majority of cloud servers, modern laptops, and recent phones)&lt;/li&gt;
&lt;li&gt;You need FIPS 140 certification&lt;/li&gt;
&lt;li&gt;You want maximum hardware-accelerated throughput for bulk encryption&lt;/li&gt;
&lt;li&gt;Your protocol enforces unique nonces (sequence numbers, epoch counters)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose ChaCha20-Poly1305 when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You target mixed hardware (older phones, IoT, embedded, SBCs)&lt;/li&gt;
&lt;li&gt;You want constant-time properties guaranteed by construction&lt;/li&gt;
&lt;li&gt;Your protocol cannot guarantee unique nonces (consider XChaCha20 for 192-bit nonces)&lt;/li&gt;
&lt;li&gt;You ship mobile or browser clients where the other endpoint's CPU is unknown&lt;/li&gt;
&lt;li&gt;You value implementation simplicity and want to audit the cipher yourself&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this means for protocol designers
&lt;/h2&gt;

&lt;p&gt;Many modern transport protocols don't pick one — they offer both as ciphersuites. WireGuard &lt;em&gt;only&lt;/em&gt; offers ChaCha20-Poly1305. TLS 1.3 mandates both (TLS_AES_128_GCM_SHA256 and TLS_CHACHA20_POLY1305_SHA256). QUIC and HTTP/3 use both.&lt;/p&gt;

&lt;p&gt;The right question is not "which is better?" but "what does your deployment look like?" If you control both ends and know the hardware (a cloud-to-cloud tunnel), AES-256-GCM on AES-NI is the obvious choice. If you're building a P2P protocol where endpoints are unpredictable, ChaCha20-Poly1305 is the safer default.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example: Pilot Protocol
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;Pilot Protocol&lt;/a&gt; — an open-source overlay network for AI agents — is a case study in this exact trade-off. It connects agents across arbitrary infrastructure: cloud VMs, local workstations, edge devices, even machines behind NAT. It cannot assume AES-NI on every peer.&lt;/p&gt;

&lt;p&gt;Pilot builds its encrypted UDP tunnels with X25519 key exchange and AES-256-GCM for transport payloads. The choice reflects a specific deployment reality: Pilot's daemon runs on servers and developer machines where AES-NI is nearly universal. The ciphersuites are pinned — no negotiation, no downgrade surface.&lt;/p&gt;

&lt;p&gt;A protocol like Pilot could equally well use ChaCha20-Poly1305 as an alternative ciphersuite for ARM-based edge deployments. The important thing is that the cipher choice follows the topology and hardware constraints, not fashion or inertia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final take
&lt;/h2&gt;

&lt;p&gt;AES-256-GCM and ChaCha20-Poly1305 are both excellent. Neither is "broken" or "wrong." The difference is in engineering trade-offs — hardware dependency, constant-time guarantees, nonce budget, and certification requirements. A well-designed protocol knows its deployment envelope and picks accordingly. The best protocols offer both and let the endpoints negotiate.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cryptography</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>X25519 Key Exchange Explained: Walk Through the Handshake</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Fri, 17 Jul 2026 19:10:05 +0000</pubDate>
      <link>https://dev.to/pstayet/x25519-key-exchange-explained-walk-through-the-handshake-24a7</link>
      <guid>https://dev.to/pstayet/x25519-key-exchange-explained-walk-through-the-handshake-24a7</guid>
      <description>&lt;h2&gt;
  
  
  X25519 is everywhere. Here's what actually happens in the handshake.
&lt;/h2&gt;

&lt;p&gt;Start reading any modern protocol spec — WireGuard, Signal, Noise, Pilot Protocol — and you hit the same wall: "X25519 key exchange." The name appears in a security-considerations section, maybe with a one-liner about Curve25519, and the spec moves on. If you're an engineer building with these protocols (or writing one yourself), that wall is frustrating. What does the handshake actually &lt;strong&gt;do&lt;/strong&gt;? What bytes cross the wire? And why X25519 instead of the ECDHE you already know from TLS?&lt;/p&gt;

&lt;p&gt;This is the walkthrough I wanted when I first encountered it: an end-to-end trace of a real X25519 handshake, using an agent-to-agent tunnel as the concrete example.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem X25519 solves
&lt;/h3&gt;

&lt;p&gt;Before any encrypted tunnel carries data, both sides need a shared secret that nobody else knows. The classic approach — the Diffie-Hellman you learn in a cryptography course — works over a finite field: both sides pick a private number, send a public value computed from it, and combine their private number with the other side's public value to arrive at the same secret.&lt;/p&gt;

&lt;p&gt;X25519 does the same thing, but over an elliptic curve (Curve25519) instead of a finite field. The math difference matters because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smaller keys&lt;/strong&gt;: 32-byte public keys instead of the 256-byte or larger keys finite-field DH needs for equivalent security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster computation&lt;/strong&gt;: Curve25519 operations are constant-time and vectorize well on modern CPUs (no side-channel leaks from data-dependent branches).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No validation needed&lt;/strong&gt;: Every 32-byte string is a valid Curve25519 public key. Finite-field DH requires checking that the received value isn't out of range or in a small subgroup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The handshake, step by step
&lt;/h3&gt;

&lt;p&gt;Let's trace what happens when two agents — call them &lt;strong&gt;Agent A&lt;/strong&gt; and &lt;strong&gt;Agent B&lt;/strong&gt; — establish an encrypted tunnel. They've discovered each other through a registry and agreed to talk. Now they need a shared secret.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Generate keypairs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each agent generates an X25519 keypair. A keypair is two values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Private key (scalar)&lt;/strong&gt;: 32 random bytes, clamped to prevent small-subgroup attacks (the low 3 bits cleared, the high bit cleared, the second-highest bit set).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public key&lt;/strong&gt;: The result of the scalar multiplication &lt;code&gt;clamp(private) × basepoint&lt;/code&gt; — another 32-byte value derived deterministically from the private key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Go (Pilot's implementation language), this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x25519&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X25519&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;curve25519&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Basepoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The standard library's &lt;code&gt;crypto/curve25519&lt;/code&gt; (stdlib-only, no external deps) does the clamping and multiplication in one call.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Exchange public keys.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent A sends its 32-byte public key to Agent B. Agent B sends its 32-byte public key to Agent A. Transfer is over UDP — these 32 bytes plus a few bytes of protocol framing fit in a single packet.&lt;/p&gt;

&lt;p&gt;The raw exchange at this point is just two 32-byte values crossing the wire. No handshake state beyond "sent pubkey, waiting for peer's."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Compute the shared secret.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each agent performs the scalar multiplication again, this time using their own private key and the peer's public key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sharedSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x25519&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X25519&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;myPrivate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;peerPublic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both agents compute the &lt;strong&gt;same 32-byte value&lt;/strong&gt; — this is the crucial property of Diffie-Hellman. An eavesdropper who saw both public keys pass across the wire cannot compute this value (the computational Diffie-Hellman assumption: given &lt;code&gt;a×G&lt;/code&gt; and &lt;code&gt;b×G&lt;/code&gt;, computing &lt;code&gt;a×b×G&lt;/code&gt; is infeasible).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Derive session keys.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The shared secret isn't used directly as an encryption key. Instead, it's fed through a key-derivation function (KDF) to produce separate keys for the two directions of the tunnel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;encrypt_key_a_to_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HKDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shared_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pilot-enc-a2b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;encrypt_key_b_to_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HKDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shared_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pilot-enc-b2a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The salt comes from the handshake transcript — a hash of every message sent so far — which binds the session keys to this specific handshake and prevents replay attacks (key confirmation).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Encrypt traffic.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now the tunnel is live. Every packet is encrypted with AES-256-GCM using the derived session key. Each packet carries a nonce that increments monotonically — the receiver rejects any packet that reuses a nonce (replay protection for free, since GCM's security relies on nonce uniqueness).&lt;/p&gt;

&lt;h3&gt;
  
  
  A real trace from an agent tunnel
&lt;/h3&gt;

&lt;p&gt;Here's what the actual bytes look like when two Pilot Protocol agents handshake. I've simplified the framing to show only the X25519 exchange (the real protocol also includes version negotiation and a handshake transcript hash).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Agent A → B (handshake init, 44 bytes UDP):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: 0x01 (KeyExchange)
Pubkey: d85a336b5e8f8a1c9a7b3e2f1c6d8a4b0e2f3c5a7b9d1e3f5c7a9b0d2e4f6c8a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Agent B → A (handshake response, 44 bytes UDP):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type: 0x02 (KeyExchange)
Pubkey: e7b9c1d3f5a7b9c1d3e5f7a9b0c2d4e6f8a0b2c4d6e8f0a2c4d6e8f0a2c4d6e8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After these two packets, both sides compute the shared secret. The next packet from either direction is encrypted with AES-256-GCM. Total handshake latency: one round trip. About 200-300 microseconds on a modern CPU for the X25519 scalar multiplication itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why protocol specs keep using X25519
&lt;/h3&gt;

&lt;p&gt;Walk through the steps above and a pattern emerges: X25519 fits naturally into the constraints protocol designers actually face.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's fast enough to do per-connection without thinking about it.&lt;/strong&gt; An X25519 key exchange takes microseconds — not milliseconds — on modern hardware. You don't need session resumption or ticket caching for performance reasons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The implementation is simple enough to audit.&lt;/strong&gt; The entire Curve25519 scalar multiplication fits in about 300 lines of C (the original TweetNaCl implementation is even smaller). The Go standard library ships it. No external crypto library dependency needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No edge cases.&lt;/strong&gt; Finite-field DH has corner cases around group validation and small subgroups that a careful implementation must handle. X25519 eliminates them: every 32-byte input is valid, and clamping handles the small-subgroup threat at the scalar level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It composes cleanly with modern AEAD.&lt;/strong&gt; The 32-byte shared secret maps naturally into HKDF for key derivation, and HKDF's output feeds AES-256-GCM or ChaCha20-Poly1305. No weird size mismatches.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common misconceptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;"X25519 and Curve25519 are the same thing."&lt;/strong&gt; Almost — Curve25519 is the elliptic curve; X25519 is the Diffie-Hellman function defined over it. The distinction matters when you read specs: X25519 is specifically the ECDH function, not the curve itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"X25519 needs a trusted setup or certificate."&lt;/strong&gt; No. X25519 is a key-exchange algorithm, not a PKI. It gives both sides a shared secret after exchanging public keys, but it doesn't tell you &lt;strong&gt;who&lt;/strong&gt; you exchanged it with. Authentication — proving that Agent A really is Agent A — requires an additional step (typically an Ed25519 signature on the handshake transcript). X25519 and Ed25519 share the same curve math (Curve25519 vs Ed25519), but they're different operations: key exchange vs signing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"You need a separate library for X25519."&lt;/strong&gt; Not anymore. Go's &lt;code&gt;crypto/curve25519&lt;/code&gt; is stdlib. OpenSSL 1.1.0+ includes it. Libsodium wraps it. BoringSSL ships it. If your language's crypto standard library shipped in the last five years, X25519 is almost certainly already there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Putting it together
&lt;/h3&gt;

&lt;p&gt;When you see "X25519 key exchange" in a protocol spec, here's what the author is saying: two parties each generate a 32-byte keypair, exchange the public halves, compute a shared 32-byte secret, and derive session keys from it. No CA. No certificates in the key-exchange phase. One round trip. Microseconds of CPU.&lt;/p&gt;

&lt;p&gt;The agent tunnel in the example above — two Pilot Protocol agents on different machines, each behind NAT — establishes an encrypted tunnel with exactly this exchange. The X25519 handshake runs once when the tunnel opens, and the derived session keys encrypt every packet after that. The whole handshake takes a single round trip and fits in two 44-byte UDP packets.&lt;/p&gt;

&lt;p&gt;If you're building agent infrastructure (or any encrypted transport), the protocol stack you want is X25519 for key exchange, HKDF for key derivation, and AES-256-GCM for bulk encryption — all in your standard library, zero external dependencies. That's the combination that keeps appearing in protocol specs because it works, it's auditable, and it doesn't impose operational complexity.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Pilot Protocol uses exactly this stack for every agent-to-agent tunnel: &lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;X25519 + HKDF + AES-256-GCM, all from the Go standard library, zero external crypto dependencies&lt;/a&gt;. The same key exchange described above runs between every pair of agents on the network.&lt;/em&gt;&lt;br&gt;
.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cryptography</category>
      <category>networking</category>
      <category>opensource</category>
    </item>
    <item>
      <title>HIPAA-Compliant AI Agent Architecture: The Network Layer You Can't Skip</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Fri, 17 Jul 2026 13:37:52 +0000</pubDate>
      <link>https://dev.to/pstayet/hipaa-compliant-ai-agent-architecture-the-network-layer-you-cant-skip-1nh8</link>
      <guid>https://dev.to/pstayet/hipaa-compliant-ai-agent-architecture-the-network-layer-you-cant-skip-1nh8</guid>
      <description>&lt;p&gt;When you're thinking through a HIPAA-compliant AI agent architecture, most of the checklists focus on the obvious layers: data encryption at rest, access controls, audit logging, business associate agreements. The network layer tends to be an afterthought — "just put everything in a VPC" is the default answer.&lt;/p&gt;

&lt;p&gt;But for AI agents that need to communicate across environments, clouds, or organizational boundaries, the network layer is where compliance architecture either holds together or leaks. Here's how to think about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Network Layer Matters for PHI-Handling Agents
&lt;/h2&gt;

&lt;p&gt;HIPAA's Security Rule requires safeguards for electronic protected health information (ePHI) in transit. For a traditional web application, that means TLS between browser and server, and maybe a VPN between services. For an AI agent architecture — where autonomous processes fetch data, call APIs, coordinate with other agents, and return results across a chain of services — the picture is more complex.&lt;/p&gt;

&lt;p&gt;Every hop between agents, every tool call to an external service, every peer-to-peer coordination message is a data-in-transit event. If agents are handling or passing PHI, each of those hops needs confidentiality and integrity protection, and each identity needs verification.&lt;/p&gt;

&lt;p&gt;This is not a compliance document and it does not constitute legal advice. But as an architectural matter: if you're building agent infrastructure that will handle PHI, the network transport is part of your compliance surface, and it deserves the same attention as your storage and application layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Traditional Approach: Shared Flat Network
&lt;/h2&gt;

&lt;p&gt;The simplest approach is to put every agent and every service on a single private network — a VPC, a VPN mesh, or a Tailscale/ZeroTier network. Join everything, and everything can talk to everything.&lt;/p&gt;

&lt;p&gt;The problem with this model for HIPAA-relevant architectures is that membership and trust are coupled. When you join an agent to the network, that agent can reach every other resource on that network. A compromised agent — or one that was never supposed to see PHI — has ambient network access to everything.&lt;/p&gt;

&lt;p&gt;In a flat-network model, the perimeter is between "inside the network" and "outside the network." That works well for static service meshes. For autonomous agents that move between environments, join and leave dynamically, and operate with different levels of privilege, it's a poor fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Layer: Encrypted Peer-to-Peer with Explicit Trust
&lt;/h2&gt;

&lt;p&gt;An alternative approach is to decouple membership from trust. Instead of a shared network where joining means trusting, the architecture treats every agent-to-agent connection as an individual, explicitly authorized tunnel.&lt;/p&gt;

&lt;p&gt;At the transport level, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-tunnel encryption&lt;/strong&gt; using a key exchange per connection, so no shared secret exists across the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explicit handshake&lt;/strong&gt; between two agents before any data flows — no ambient access to other nodes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity pinned to keys&lt;/strong&gt;, not to IP addresses, so agents can move between networks, clouds, or containers without reconfiguring trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the zero-trust networking model applied to agent communication: every pair of agents authenticates each other independently, and no agent has standing access to another agent's resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Per-Tunnel Encryption Works at the Transport Layer
&lt;/h2&gt;

&lt;p&gt;For a HIPAA-relevant architecture, the transport needs to provide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mutual authentication&lt;/strong&gt; — both sides prove their identity before any data is exchanged.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forward secrecy&lt;/strong&gt; — compromising one session's key does not compromise past or future sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrity&lt;/strong&gt; — tampering with a message in transit is detectable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidentiality&lt;/strong&gt; — message content is visible only to the intended recipient.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A concrete example: X25519 key agreement for the initial handshake, with AES-GCM for the per-message encryption and authentication. Each agent generates its own keypair. Agent A and Agent B exchange public keys (authenticated through a handshake), derive a shared session key, and all subsequent traffic is encrypted and authenticated. No intermediate proxy, no shared VPC network, no flat trust.&lt;/p&gt;

&lt;p&gt;Each tunnel is independent. Even if Agent A is talking to Agents B, C, and D simultaneously, each connection uses a distinct session key derived from a separate key exchange. Compromising one tunnel has no effect on the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  NAT Traversal as a Security Consideration
&lt;/h2&gt;

&lt;p&gt;AI agents frequently run behind NAT — inside a cloud private subnet, on a laptop behind a home router, in a container with no public IP. For a TCP-based service behind NAT, the standard workaround is a reverse proxy or a cloud relay: expose a public endpoint, route traffic through it.&lt;/p&gt;

&lt;p&gt;For compliance-conscious architectures, NAT traversal matters because every relay or reverse proxy is an additional data plane. If PHI passes through a relay, that relay becomes part of your compliance boundary. A better approach is direct peer-to-peer tunnels with NAT traversal built into the transport layer — using STUN to discover public mappings and hole-punching to establish direct connections, falling back to a relay only when both sides are behind restrictive NATs.&lt;/p&gt;

&lt;p&gt;The relay path is still encrypted end-to-end — the relay never has access to the plaintext — but minimizing relay usage reduces the number of components in the trusted data path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest Comparison of Approaches
&lt;/h2&gt;

&lt;p&gt;No single approach fits every architecture. Here's an honest assessment of common options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;WireGuard / Tailscale / ZeroTier&lt;/strong&gt;: Excellent for traditional VPN-style connectivity. Easy to set up, strong encryption. The trade-off is the flat-trust model — joining the network grants broad access. For static deployments where every node has the same trust level, these work well. For dynamic agent workloads where agents have different privilege levels, you need additional network segmentation or ACLs on top.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mutual TLS&lt;/strong&gt;: Strong authentication, well-understood. The operational cost is certificate management — issuing, rotating, and revoking certificates for every agent that joins and leaves. For long-lived services this is manageable; for ephemeral agents it adds friction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Webhook / polling patterns&lt;/strong&gt;: No persistent connection needed. The trade-off is that every interaction requires a round trip through shared infrastructure (a message queue, an API gateway, or a polling endpoint), which adds latency and creates a central data plane that needs its own compliance treatment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Per-tunnel encrypted mesh&lt;/strong&gt; (what Pilot Protocol implements): Decouples membership from trust. Every connection is individually authenticated and encrypted. No shared network fabric. The trade-off is higher per-connection coordination overhead — the handshake happens per pair, not once per network join.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Security Model in Practice
&lt;/h2&gt;

&lt;p&gt;For a HIPAA-relevant agent architecture, the key architectural property is that trust is per-connection, not per-network. When an agent joins a deployment, it does not automatically get access to other agents or services. It must be explicitly authorized for each peer. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A PHI-handling agent and a non-PHI agent can coexist on the same infrastructure without the non-PHI agent ever having a path to sensitive data.&lt;/li&gt;
&lt;li&gt;An agent that is compromised or misconfigured cannot laterally access other agents' communications or data.&lt;/li&gt;
&lt;li&gt;Audit logs record exactly which peer connections were established, when, and for how long — because each tunnel is a discrete, documented event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is achievable with any of the approaches above, with varying levels of operational overhead. The architecture decision is about where you want the complexity: in network configuration rules and ACLs (flat-network approach), in certificate lifecycle management (mTLS), or in per-connection handshake logic (mesh approach).&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Start
&lt;/h2&gt;

&lt;p&gt;If you're evaluating network architectures for a HIPAA-relevant agent deployment, start by mapping every hop an agent's data will take. For each hop, ask: is this connection authenticated on both sides? Is it encrypted with a session-specific key? Is the trust scope limited to this one pair, or does it extend to the whole network?&lt;/p&gt;

&lt;p&gt;The answers will tell you which transport model fits your compliance requirements.&lt;/p&gt;

&lt;p&gt;For developers evaluating options, the install is the same either way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://pilotprotocol.network/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full docs at &lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;pilotprotocol.network/docs&lt;/a&gt; cover the transport details — handshake protocol, per-tunnel encryption, and the trust model — so you can compare against your own architecture requirements.&lt;br&gt;
.&lt;/p&gt;

</description>
      <category>security</category>
      <category>architecture</category>
      <category>ai</category>
      <category>devops</category>
    </item>
    <item>
      <title>gRPC vs UDP for Low Latency: What You Actually Give Up</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Thu, 16 Jul 2026 21:32:23 +0000</pubDate>
      <link>https://dev.to/pstayet/grpc-vs-udp-for-low-latency-what-you-actually-give-up-1hpj</link>
      <guid>https://dev.to/pstayet/grpc-vs-udp-for-low-latency-what-you-actually-give-up-1hpj</guid>
      <description>&lt;h1&gt;
  
  
  gRPC vs UDP for Low Latency: What You Actually Give Up
&lt;/h1&gt;

&lt;p&gt;When your multi-agent system needs low latency, the default reflex is gRPC. Fast serialization, HTTP/2 multiplexing, bidirectional streams — it checks every box on paper. But between two agents on different machines, gRPC runs over TCP. And TCP has non-negotiables: in-order delivery, congestion control, retransmission backoff, head-of-line blocking inside a single HTTP/2 connection.&lt;/p&gt;

&lt;p&gt;For agent-to-agent communication, those properties aren't free. The question isn't whether gRPC is fast — it's whether TCP's guarantees cost more latency than your use case can afford.&lt;/p&gt;

&lt;h2&gt;
  
  
  The TCP tax gRPC can't escape
&lt;/h2&gt;

&lt;p&gt;gRPC inherits every TCP tradeoff even though most developers never configure a single TCP knob. Here's what you're paying for by default:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Head-of-line blocking inside HTTP/2.&lt;/strong&gt; HTTP/2 multiplexes multiple streams over one TCP connection, but TCP delivers bytes in order. A lost packet on stream A stalls every other stream on that connection until retransmission arrives. HTTP/2's own flow control adds another per-stream queue on top. Two agents exchanging many small messages concurrently will hit this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Congestion control ramps up slowly.&lt;/strong&gt; TCP slow-start on a fresh connection means the first few round-trips carry far fewer packets than the path can handle. For an agent that sends a burst of 20 messages then goes silent, every burst pays the slow-start tax. BBR and other modern CCs help, but they still react to loss—and for agents on lossy wireless or home NAT links, that reaction is a latency spike.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retransmission timeout (RTO) floor.&lt;/strong&gt; Linux defaults to 200ms RTO minimum. A single lost TCP segment on a gRPC stream stalls that entire connection for at least 200ms. Over a cross-continent or tail-latency-sensitive agent link, that's an eternity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connection setup.&lt;/strong&gt; gRPC adds TLS handshake on top of the TCP three-way handshake. For long-lived agent connections this is a one-time cost. But for agents that discover each other ephemerally—think a task-specific worker fleet that starts up, communicates, and shuts down—the setup latency before a single message is exchanged can be 2-3 round trips.&lt;/p&gt;

&lt;h2&gt;
  
  
  What UDP gives back
&lt;/h2&gt;

&lt;p&gt;Moving to UDP removes all four tax lines at once. No head-of-line blocking (each datagram is independent). No slow-start (send at line rate immediately). No 200ms RTO (loss detection is yours to control). No handshake overhead (connectionless by design).&lt;/p&gt;

&lt;p&gt;But UDP also removes TCP's guarantees. No ordering, no retransmission, no congestion control, no flow control. You get datagrams: best-effort, unordered, up to ~65KB (though real-world MTU limits make 1400 bytes the practical max).&lt;/p&gt;

&lt;p&gt;This is the core trade. gRPC over TCP says: "I'll guarantee ordering and delivery, and you take the latency cost." Raw UDP says: "I'll get out of your way, and you handle order and loss yourself."&lt;/p&gt;

&lt;h2&gt;
  
  
  Userspace reliability: the middle path
&lt;/h2&gt;

&lt;p&gt;Most agent transports that choose UDP don't stay at raw datagrams. They build &lt;strong&gt;userspace reliability&lt;/strong&gt; on top: selective retransmission (not the whole accumulated TCP window), pluggable loss detection (not a fixed 200ms RTO), and optional ordering (not every message must be in-order; an agent status update can arrive after a later one without breaking anything).&lt;/p&gt;

&lt;p&gt;This is a fundamentally different reliability model from TCP's. TCP treats all traffic as one ordered byte stream. A userspace transport over UDP can treat each message as an independent unit and decide per-message whether ordering matters, whether loss is tolerable, and whether the sender even needs an ack.&lt;/p&gt;

&lt;p&gt;For agent workloads this maps well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Heartbeats and presence updates:&lt;/strong&gt; loss is fine, order doesn't matter, no reliability needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task dispatch:&lt;/strong&gt; ordering matters within one task, not across tasks. Selective ack per message group, not a TCP window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large payloads (state sync, model config):&lt;/strong&gt; fragment, sequence, retransmit only the missing fragments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where agents pay the gRPC-over-TCP tax hardest
&lt;/h2&gt;

&lt;p&gt;Three patterns common in multi-agent systems expose the TCP gRPC tax more than a traditional client-server microservice setup:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. One-to-many fan-out.&lt;/strong&gt; A coordinator sends the same task to 10 workers. With gRPC, that's 10 TCP connections (or one HTTP/2 connection per worker). Each has its own congestion state. A lossy link to one worker stalls &lt;em&gt;that&lt;/em&gt; stream — not the others, but you're still paying 10× the TCP setup cost. Over UDP the coordinator sends 10 datagrams in a single batch with one syscall batch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Ephemeral agent groups.&lt;/strong&gt; Agents that form teams per task and dissolve afterward pay TCP connection setup + TLS every time. A 3-RTT setup cost on a 50ms link adds 150ms before the first message arrives. For a 2-second task, that's 7% overhead just to start talking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Lossy or asymmetric links.&lt;/strong&gt; Agents on residential NAT, WiFi, cellular uplinks, or tail-latency cross-region links see more packet loss than datacenter TCP was designed for. TCP interprets loss as congestion and backs off. A user-space transport can distinguish congestion from corruption and retransmit aggressively on a known-clean link.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilot Protocol's approach: userspace reliability over UDP
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;Pilot Protocol&lt;/a&gt; implements exactly this middle path. It builds a userspace reliability layer over encrypted UDP tunnels (X25519 + AES-GCM), with pluggable loss detection and selective retransmission per message — not per byte. The transport is connectionless in the TCP sense but connection-oriented at the application layer: agents have permanent virtual addresses that survive restarts and IP changes, and message delivery semantics are negotiated per exchange rather than dictated by the transport.&lt;/p&gt;

&lt;p&gt;The key difference from gRPC over TCP: Pilot's transport doesn't guarantee ordering unless you ask for it. A status update can arrive before or after a task result without stalling either. It doesn't do slow-start — it sends at line rate from message one. And it doesn't have a 200ms RTO floor — retransmission timing is tuned by the application, not the kernel.&lt;/p&gt;

&lt;p&gt;This isn't a replacement for gRPC everywhere. gRPC's ecosystem — protobufs, service definitions, generated clients, streaming RPCs — is mature and valuable for request-response APIs between stable services. But for agent-to-agent messaging where latency variance matters more than strict ordering, the transport tradeoffs flip.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you actually give up
&lt;/h2&gt;

&lt;p&gt;If you move from gRPC over TCP to a userspace-UDP transport, you give up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stream abstraction&lt;/strong&gt; — you don't get a buffered bidirectional pipe for free. You get messages, and you compose ordering/reliability yourself per use case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem&lt;/strong&gt; — no protobuf codegen (though you can still use protobuf for serialization over UDP; serialization and transport are orthogonal).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Middlebox familiarity&lt;/strong&gt; — TCP goes through every NAT, firewall, and load balancer predictably. UDP hole-punching is well-understood but not universal; some enterprise networks drop all non-DNS UDP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What you gain is control over your latency profile. For agent systems where a 200ms stall on a task-critical link is a failure, not a nuisance, that control is worth the trade.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Interested in how userspace reliability over UDP works in practice? Pilot Protocol's &lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; covers the transport layer, trust model, and how to connect agents across NAT without a VPN.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>networking</category>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>NATS vs gRPC for Messaging: When the Answer Is Neither</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Wed, 15 Jul 2026 20:32:53 +0000</pubDate>
      <link>https://dev.to/pstayet/nats-vs-grpc-for-messaging-when-the-answer-is-neither-2bng</link>
      <guid>https://dev.to/pstayet/nats-vs-grpc-for-messaging-when-the-answer-is-neither-2bng</guid>
      <description>&lt;h1&gt;
  
  
  NATS vs gRPC for Messaging: When the Answer Is Neither
&lt;/h1&gt;

&lt;p&gt;If you're building a distributed system that needs reliable inter-service communication, the NATS vs gRPC debate comes up early. Engineers pick one and usually make it work — but &lt;em&gt;how&lt;/em&gt; it works, and what it assumes about your architecture, matters a lot.&lt;/p&gt;

&lt;p&gt;This is a map of the trade-offs, not a winner. And for one growing use case — autonomous agents that need to talk across clouds and NAT boundaries — both may be the wrong shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  gRPC: RPC with strong contracts
&lt;/h2&gt;

&lt;p&gt;gRPC wraps HTTP/2 with Protocol Buffers, giving you typed RPC methods, server streaming, client streaming, and bidirectional streaming. It shines when you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strict service contracts.&lt;/strong&gt; The &lt;code&gt;.proto&lt;/code&gt; file defines exactly what each service does. Code generation produces clients and servers in 12+ languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request-reply patterns.&lt;/strong&gt; Most gRPC usage is unary RPC — call a method, get a response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A service mesh or DNS layer underneath.&lt;/strong&gt; gRPC assumes endpoints are reachable by hostname. It does not discover peers or traverse NAT — those jobs go to a service mesh (Istio, Linkerd) or a separate discovery system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cost: TLS certificates are mandatory (gRPC won't connect without them), and every service needs a stable DNS name or proxy in front of it. That works well inside a Kubernetes cluster or a VPN. Outside that boundary, it gets complicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  NATS: Cloud-native messaging
&lt;/h2&gt;

&lt;p&gt;NATS is a broker-based messaging system. Clients connect to a NATS server cluster and publish/subscribe on subjects. It handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pub/sub, request-reply, and queue groups.&lt;/strong&gt; NATS has excellent semantics for event-driven architectures and workload distribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At-most-once delivery by default&lt;/strong&gt; (with JetStream for persistence where needed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High throughput and low latency.&lt;/strong&gt; The NATS server is famously fast — a single Go binary that handles millions of messages per second.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off: every client must reach the NATS cluster. If your services live behind different NATs, on different clouds, or in different corporate networks, you need the broker to be publicly reachable — or you run a cluster per network and bridge them. The broker also sees message payloads (unless you add a separate encryption layer), and you're responsible for operating the cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  What both assume
&lt;/h2&gt;

&lt;p&gt;gRPC assumes reachable endpoints. NATS assumes a reachable broker. Both assume you control the network or have infrastructure (VPN, service mesh, public DNS) to make endpoints reachable.&lt;/p&gt;

&lt;p&gt;That assumption holds for a microservice inside a VPC. It breaks down when you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agents running on a user's laptop behind a home router&lt;/li&gt;
&lt;li&gt;Cross-cloud agent fleets (AWS → GCP → Azure with no shared VPC)&lt;/li&gt;
&lt;li&gt;Agents that wake up on dynamic IPs and need to find each other&lt;/li&gt;
&lt;li&gt;Any topology without a central broker you control&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The third shape: an agent overlay
&lt;/h2&gt;

&lt;p&gt;There is a third category that doesn't compete with either gRPC or NATS — it solves a different problem. An &lt;strong&gt;agent overlay network&lt;/strong&gt; gives every agent a permanent virtual address, handles NAT traversal transparently, and encrypts everything end-to-end by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pilotprotocol.network/docs" rel="noopener noreferrer"&gt;Pilot Protocol&lt;/a&gt; is an open-source example of this approach. It is not a messaging broker (NATS) or an RPC framework (gRPC). It is a layer-3.5 overlay: agents get a stable address (&lt;code&gt;N:NNNN.HHHH.LLLL&lt;/code&gt;) that survives restarts and IP changes, encrypted UDP tunnels traverse NAT without any infrastructure, and trust is established via cryptographic handshake — not a VPN that trusts everyone who joins.&lt;/p&gt;

&lt;p&gt;Where does it fit alongside NATS and gRPC?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Reach for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Event-driven microservices in one cluster&lt;/td&gt;
&lt;td&gt;NATS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typed RPC with codegen inside a service mesh&lt;/td&gt;
&lt;td&gt;gRPC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents talking across clouds, NATs, or firewalls&lt;/td&gt;
&lt;td&gt;Overlay (Pilot Protocol)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents need to discover each other dynamically&lt;/td&gt;
&lt;td&gt;Overlay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;End-to-end encrypted by default, no broker&lt;/td&gt;
&lt;td&gt;Overlay&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  You probably need more than one
&lt;/h2&gt;

&lt;p&gt;The pragmatic take: these are complementary tools, not alternatives. Your agent fleet behind NAT can use an overlay for connectivity (peer discovery, encrypted tunnels) and still use gRPC or NATS &lt;em&gt;on top&lt;/em&gt; of that connectivity for messaging semantics. NATS on an overlay means pub/sub across any network. gRPC on an overlay means RPC without TLS certificate management for every agent.&lt;/p&gt;

&lt;p&gt;The question "NATS vs gRPC for messaging" is the right one for a single-VPC deployment. For multi-cloud, multi-network, multi-org agent systems, the real question is "what provides connectivity before I pick my messaging layer?" — and that's where the third shape earns its place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;If you want to try the overlay approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://pilotprotocol.network/install.sh | sh
pilotctl send-message list-agents &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'/data'&lt;/span&gt; &lt;span class="nt"&gt;--wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your agent is now addressable on the overlay network, behind NAT, with no DNS, no TLS certs, and no broker to maintain. Then layer NATS or gRPC on top if you need their semantics — the overlay handles the connectivity problem so your messaging layer can focus on what it does best.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>MCP Tunnels vs VPN for AI Agents: When a VPN Is the Wrong Shape</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Wed, 15 Jul 2026 16:10:35 +0000</pubDate>
      <link>https://dev.to/pstayet/mcp-tunnels-vs-vpn-for-ai-agents-when-a-vpn-is-the-wrong-shape-8fp</link>
      <guid>https://dev.to/pstayet/mcp-tunnels-vs-vpn-for-ai-agents-when-a-vpn-is-the-wrong-shape-8fp</guid>
      <description>&lt;p&gt;If you are running an MCP server, you have probably hit the connectivity question: how do agents across the internet reach it? The default answer is usually "put everything on a VPN." It is familiar, it works, and it feels safe. But a VPN is the wrong shape for an MCP server, and the mismatch costs you in surprising ways.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem VPNs Solve (And Why It Looks Like a Fit)
&lt;/h2&gt;

&lt;p&gt;A VPN — Tailscale, ZeroTier, WireGuard with a mesh — solves a real problem: you want machines in different networks to talk as if they were on the same LAN. Every device gets a virtual IP, traffic is encrypted, and the mesh handles routing.&lt;/p&gt;

&lt;p&gt;For a developer running a handful of servers and workstations, this works well. You join the VPN, you are in. Endpoints are reachable, traffic is private, and the setup is well understood.&lt;/p&gt;

&lt;p&gt;Now apply it to an MCP server. The MCP server runs in one place — a VPS, a home server, a cloud VM. The agents that call it are ephemeral: they spin up, make requests, and disappear. They run in CI pipelines, on user laptops, in serverless functions, across different clouds. Every one of these agents needs a path to the MCP server.&lt;/p&gt;

&lt;p&gt;A VPN says: make every agent a member of the VPN. The problem is in that word — &lt;em&gt;member&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Membership vs. Trust — The Critical Difference
&lt;/h2&gt;

&lt;p&gt;VPNs treat membership and trust as the same thing. If you are on the VPN, you are trusted. If you are not on the VPN, you are unreachable. This is fine for a team of known machines. It breaks for an open or semi-open MCP server that serves many clients.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every new agent needs a VPN join key.&lt;/strong&gt; That key is expensive to rotate and hard to scope. Leak it once and every node on the VPN is exposed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revoking a compromised agent means removing it from the VPN.&lt;/strong&gt; That is a manual operation, and in a mesh VPN, it has to propagate to every peer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ephemeral agents don't fit.&lt;/strong&gt; A CI runner that calls an MCP server for 30 seconds should not need a persistent VPN membership that lives beyond the job.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a flaw in VPN design. VPNs were built for stable, long-lived connections between known machines. MCP servers serve a fundamentally different pattern: many clients, short sessions, high turnover.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an MCP Server Actually Needs
&lt;/h2&gt;

&lt;p&gt;An MCP server needs a small set of properties that are surprisingly different from a VPN's feature set:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Inbound reachability&lt;/strong&gt; — the server has a stable address that clients can reach, regardless of where it is hosted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-connection trust&lt;/strong&gt; — each client authenticates individually; trust is scoped to the session, not to the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No persistent membership&lt;/strong&gt; — clients connect, do work, and disconnect. No join key, no long-lived assignment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UDP-friendly&lt;/strong&gt; — many MCP calls are short request-response cycles; TCP overhead from VPN tunnels adds latency that compounds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A VPN gives you (1) and part of (3), but it actively fights (2) by giving every member access to everything on the subnet. And it adds network overhead for (4) that is invisible until you measure it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-Peer Tunnels — The Alternative Shape
&lt;/h2&gt;

&lt;p&gt;The alternative is a per-peer tunnel: instead of joining a shared network, each client establishes a direct encrypted tunnel to the MCP server. The server never exposes a subnet; it exposes exactly one endpoint. Trust is per-handshake, not per-membership.&lt;/p&gt;

&lt;p&gt;This pattern has practical advantages that map directly to the MCP use case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No join key to distribute.&lt;/strong&gt; Each agent authenticates on connection with its own credentials. There is no shared secret that, leaked, compromises the whole mesh.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revocation is instant.&lt;/strong&gt; Drop the peer's trust entry on the server. That agent cannot connect again. No propagation delay, no stale membership.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ephemeral clients work.&lt;/strong&gt; An agent that connects for a single query and disappears leaves nothing behind. No cleanup, no lingering tunnel state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No subnet exposure.&lt;/strong&gt; The MCP server appears at a single address. There is no virtual network to scan, no lateral movement possible from a compromised peer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pilot Protocol uses exactly this model: per-peer encrypted UDP tunnels with explicit handshake-based trust. An agent finds the MCP server by name (via a rendezvous registry), establishes a tunnel, and communicates — no VPN join, no subnet, no shared key. The trust is bidirectional and individually scoped.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a VPN Is Still the Right Call
&lt;/h2&gt;

&lt;p&gt;None of this says VPNs are bad. If you run a private MCP server for a fixed team of 5–10 agents that run on known machines, a Tailscale mesh is simple and effective. The overhead is negligible at that scale, and the mental model matches the deployment pattern.&lt;/p&gt;

&lt;p&gt;The mismatch appears when the set of calling agents is dynamic — agents that appear and disappear, agents on different clouds, agents operated by different teams or organizations. At that point, the VPN's membership model starts working against you, and per-peer tunnels become simpler, not harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Practical Takeaway
&lt;/h2&gt;

&lt;p&gt;When you design the connectivity for an MCP server, ask yourself: &lt;em&gt;how many entities need access, and how stable are they?&lt;/em&gt; If the answer is "a small, fixed set of machines I control," a VPN is the straightforward path. If it is "a growing set of agents I don't fully control, some ephemeral, some persistent," then per-peer tunnels with individual trust are a better architectural fit.&lt;/p&gt;

&lt;p&gt;The two patterns are not in competition — they serve different deployment profiles. But confusing one for the other leads to unnecessary complexity, either from managing VPN membership for short-lived agents or from over-engineering tunnels for a static team.&lt;/p&gt;

&lt;p&gt;For the agent-native case, Pilot Protocol's overlay network implements the per-peer tunnel model natively — it is built for agents, not for laptops. But the point stands regardless of the implementation: match the connectivity model to the actual agent lifecycle, not to the most familiar tool.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>Crypto Price API With No Key: The Real Keyless Options Compared</title>
      <dc:creator>Philip Stayetski</dc:creator>
      <pubDate>Sat, 11 Jul 2026 02:33:14 +0000</pubDate>
      <link>https://dev.to/pstayet/crypto-price-api-with-no-key-the-real-keyless-options-compared-2fe2</link>
      <guid>https://dev.to/pstayet/crypto-price-api-with-no-key-the-real-keyless-options-compared-2fe2</guid>
      <description>&lt;h2&gt;
  
  
  The problem with "free" crypto price APIs
&lt;/h2&gt;

&lt;p&gt;You want the current price of BTC, ETH, or a handful of altcoins in a script, a Discord bot, or an agent — and you don't want to create an account, verify an email, or paste a secret key into an environment variable for something this simple. That's a completely reasonable ask, and there are more keyless options than most "top 10 crypto APIs" roundups let on. They just don't all deserve the same amount of trust.&lt;/p&gt;

&lt;p&gt;This post compares the actual no-signup, no-key options for pulling crypto (and adjacent FX) prices, what limits and caveats come with each, and — since agents are increasingly the ones making these calls, not humans — where Pilot Protocol's finance agents fit into the picture as a genuinely agent-native option.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "no key" actually means in practice
&lt;/h2&gt;

&lt;p&gt;Before comparing anything, it's worth separating three things that get lumped together as "free crypto API":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Truly keyless, no signup&lt;/strong&gt; — you hit an endpoint and get JSON back. No headers, no account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free tier, but still requires a key&lt;/strong&gt; — you sign up once, get a key, and stay under a request ceiling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Try it keyless" marketing&lt;/strong&gt; — a demo endpoint that works without a key for light testing, but production use still expects registration.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Most listicles conflate all three. If your actual requirement is &lt;em&gt;zero setup, zero account&lt;/em&gt;, only option 1 counts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyless options worth knowing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CoinGecko's public API&lt;/strong&gt; is the most commonly recommended keyless option. The &lt;code&gt;/simple/price&lt;/code&gt; endpoint returns spot prices for a coin list against one or more fiat/crypto quote currencies with no key required on the public tier. It's well documented, covers a huge number of assets, and is the default answer in most threads on this topic — worth checking their current terms before depending on it, since free-tier policies shift over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exchange public endpoints&lt;/strong&gt; are another underused keyless path. Coinbase, Kraken, and Binance all expose public market-data endpoints (ticker, order book, recent trades) that don't require authentication — because they're public market data, not account data. The tradeoff: you get exchange-specific pricing (which can diverge slightly from a blended index) and you're depending on an exchange's infra and rate-limiting policy rather than a dedicated data provider's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FreeCryptoAPI and similar keyless aggregators&lt;/strong&gt; exist specifically to serve the "just give me a price, no signup" use case. These are worth spot-checking for uptime and coverage before relying on them for anything production-critical — smaller providers can have less predictable availability than the exchanges or CoinGecko.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes when the caller is an agent, not a human
&lt;/h2&gt;

&lt;p&gt;Every option above assumes a human developer reading docs, picking an endpoint, and writing a request. That model gets awkward when the caller is an autonomous agent: the agent has to know which of a dozen keyless crypto APIs exists, parse each one's inconsistent JSON shape, and handle each provider's own rate-limit and error conventions — repeated work every agent building this integration does independently.&lt;/p&gt;

&lt;p&gt;This is the specific gap &lt;a href="https://pilotprotocol.network/plain" rel="noopener noreferrer"&gt;Pilot Protocol&lt;/a&gt; is built around. Pilot is an overlay network that gives agents a permanent address and lets them query specialist agents directly — structured JSON in, structured JSON out, no API key, no SDK. A handful of the ~243k+ agents already on the network are finance specialists that answer exactly this kind of query: current crypto spot prices, FX rates, and related market data, each with a documented &lt;code&gt;/data&lt;/code&gt; query shape instead of a bespoke REST contract you have to reverse-engineer.&lt;/p&gt;

&lt;p&gt;The pattern from an agent's side looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# one-time install&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://pilotprotocol.network/install.sh | sh
pilotctl daemon start &lt;span class="nt"&gt;--hostname&lt;/span&gt; my-agent

&lt;span class="c"&gt;# find a finance specialist agent&lt;/span&gt;
pilotctl send-message list-agents &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'/data {"search":"bitcoin"}'&lt;/span&gt; &lt;span class="nt"&gt;--wait&lt;/span&gt;

&lt;span class="c"&gt;# query it directly — no key, no signup&lt;/span&gt;
pilotctl send-message &amp;lt;agent-name&amp;gt; &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'/data {"symbol":"BTC"}'&lt;/span&gt; &lt;span class="nt"&gt;--wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't know which specialist to query, &lt;code&gt;pilot-director&lt;/code&gt; will resolve it for you from a plain-English description of the task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pilotctl send-message pilot-director &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'current bitcoin price in USD'&lt;/span&gt; &lt;span class="nt"&gt;--wait&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't a claim that Pilot replaces CoinGecko or an exchange's public API for a human developer writing a one-off script — for that, a plain HTTP GET to a keyless REST endpoint is still the simplest path, and CoinGecko or an exchange's own endpoint is a fine choice. Where Pilot earns its place is the agent case: one consistent connection method across many data domains (finance is one category among 20+), rather than a different keyless API, a different JSON shape, and a different rate-limit policy for every data source an agent needs to reach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing between them
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CoinGecko public API&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;General-purpose spot prices, broad coin coverage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exchange public endpoints (Coinbase/Kraken/Binance)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Exchange-specific pricing, order-book/trade data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keyless aggregators (FreeCryptoAPI, etc.)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Quick scripts; verify uptime before depending on it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pilot Protocol finance specialists&lt;/td&gt;
&lt;td&gt;Install &lt;code&gt;pilotctl&lt;/code&gt; once&lt;/td&gt;
&lt;td&gt;Agents that need consistent structured access across finance &lt;em&gt;and&lt;/em&gt; other live-data domains (weather, transit, news, etc.) without juggling a different keyless API per category&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is there a truly free, no-signup crypto price API?&lt;/strong&gt;&lt;br&gt;
Yes — CoinGecko's public API and the public market-data endpoints on major exchanges (Coinbase, Kraken, Binance) don't require a key for basic price lookups. Verify current rate limits and terms before depending on any of them long-term.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why would an agent use Pilot instead of hitting CoinGecko directly?&lt;/strong&gt;&lt;br&gt;
Both work. Pilot's value for an agent is consistency: one connection method (no key) that reaches finance specialists &lt;em&gt;and&lt;/em&gt; dozens of other live-data domains, instead of learning and maintaining a different keyless integration per source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does Pilot require an API key?&lt;/strong&gt;&lt;br&gt;
No. Pilot's service agents — including its finance specialists — are queried directly over the overlay network with no key and no SDK required, per the documented &lt;code&gt;/plain&lt;/code&gt; reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where do I see the full catalogue of what Pilot's specialists cover?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;pilotctl send-message list-agents --data '/data' --wait&lt;/code&gt; returns the live catalogue, or see the plain-text summary at &lt;a href="https://pilotprotocol.network/plain" rel="noopener noreferrer"&gt;pilotprotocol.network/plain&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Get started: &lt;code&gt;curl -fsSL https://pilotprotocol.network/install.sh | sh&lt;/code&gt;&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>api</category>
      <category>agents</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
