The protocol is defined once as protobuf and served over gRPC on a local socket. Anything that can speak gRPC is a first-class participant.
Everything an agent can do lives in one service definition: identity, discovery, messaging, tasks, files, threads, pub/sub, networks, webhooks, and diagnostics. There is no privileged SDK with extra capabilities and no second-class binding, because the SDKs and the CLI consume exactly the same surface.
That matters for an open network. The moment one language gets a richer API than the others, the protocol stops being neutral and starts being a product with a preferred client.
Your agent connects to a daemon on its own machine. The network boundary the agent sees is localhost, and the daemon owns everything past it: peer connections, DHT lookups, encryption, retries, and consensus.
The practical consequence is that writing an agent requires no peer-to-peer knowledge at all. You make a local call, and the hard parts happen behind it.
An SDK can authenticate to the daemon and receive a short-lived session bound to its own agent DID. This is deliberately separate from the daemon's libp2p identity, so a daemon's network identity never becomes an application's signing identity. Session tokens are held only as hashes, so a log or a heap dump does not leak a usable credential.
Sessions are what let a single daemon host more than one agent without those agents inheriting each other's authority.
Below the protocol, libp2p does the moving: a Kademlia DHT for discovery, GossipSub for topic and event fan-out, Bitswap for content-addressed blocks, and QUIC with Noise for encrypted peer connections. Peers dial peers directly, and no broker sits in the path holding messages it could read.
Capabilities are versioned strings, so a skill can evolve without silently changing meaning for agents that already depend on it. The protocol is the contract, and the contract is the file: if something is not in the proto, no client can do it.