How to read this FAQ

One fleet, question by question

Each answer below defines one idea, says where it sits in the architecture, and then shows it at work in one running example. Part 1 covers the ideas everything else rests on. Parts 2 to 7 climb the architecture one layer at a time, from identity at the bottom to capability services at the top, with joining a group in its own part. Parts 8 to 10 cover the programming model, security, and the wire. The terms at a glance table at the end lists every term with a link back to its answer.

The box at the top of the page filters the questions as you type, so you can type lease or beacon and read only the answers that mention it.

The running example

Acme Corp runs a fleet of agents called research-fleet. Its network domain is corp.example, and it started the group from the founding text research-fleet-v1. The agentspaces-bootstrap README follows one new agent, summarizer, as it finds the fleet, and the agentspaces-beacon README gives the fleet a beacon. This FAQ picks up from there. Once summarizer has joined, it takes research work, its colleagues vote on what to publish, a desk of clerks pays for licensed reports exactly once, and the fleet recovers when one of them crashes.

Who or whatIts part in the fleet
seed-a, seed-bServers that listen on port 7500. Newcomers dial them first.
beaconA member at beacon.corp.example that plays the rendezvous role and serves the beacon document.
summarizerA new agent on an engineer's laptop. It takes research tasks and writes findings.
summarizer-bA second copy of the same agent, running in Kubernetes. It competes with summarizer for tasks.
coordinatorA Spring Boot application that writes research tasks and opens votes.
reviewer-1, -2, -3Three reviewer agents on one peer. They vote on whether to publish each finding.
publisherThe agent that publishes a finding once the reviewers have decided.
ledger-1, -2, -3Three peers that run the ordered log, each hosting one clerk that pays outside vendors for licensed reports.
docs-connectorA peer with no agents. It offers Acme's document archive to the fleet as an asset.
Partner IncA partner organization with its own group, partner-fleet, which has a signed founding. Acme's peers join it by id.

research-fleet has five spaces: tasks (work shared by lease race), tasks-auction (work allocated by cost), findings (results), votes (proposals and ballots), and payments (orders confirmed through the ordered log). Its entries are plain Java records: ResearchTask(topic, priority, requester), Finding(topic, summary, cid), Published(proposalId), LicenseOrder(orderId, report, vendor, amount), and LicenseReceipt(orderId, vendor, by).

RESEARCH-FLEET · ACME CORP · FOUNDING TEXT research-fleet-v1 · corp.examplecoordinatorSpring Bootsummarizerlaptop, dials outsummarizer-bKubernetesreviewers3 agents, 1 peerpublisherpublishesFIVE SPACES, REPLICATED ON EVERY MEMBERtaskslease racetasks-auctioncheapest bidfindingsresultsvotesquorum ballotspaymentsordered logwrites taskstakesbidsballotsdecisioncomplete, write Findingseed-a:7500seed-brelaybeaconrendezvousdocs-connectorAssetCardledger-1clerkledger-2clerkledger-3clerkRaft log, @OrderedTakenewcomers dial these firstoffers acme-archiveHOW SUMMARIZER JOINS · BOOTSTRAP, LAYER 1startsknows only the textdns-sdunder corp.examplebeacon.jsonsigned seed listdials seed-aintroduces itselfadmittedgossip takes overPARTNER-FLEET · PARTNER INC · SIGNED FOUNDING aspace://q9c2b...summarizersame peer, 2nd grouppartner beacon.jsoncarries the foundingPartner Inc peersINVITE policyjoin by idverify hash, dialmember ofboth groups
Acme's fleet at a glance. Each box with corner marks is a peer. The five spaces replicate to every member of research-fleet, and the arrows show who writes, takes, bids, votes, and pays. The strip below them is how summarizer finds the fleet, and the last lane is the partner group it joins by id.
Part 1 · Top-level concepts

The ideas everything else rests on

These answers explain what AgentSpaces is, the three rules its design follows, and how the five architecture layers stack. Later parts define each term in detail.

What is AgentSpaces?#

AgentSpaces is a peer-to-peer coordination fabric for agents, software services, and the people who work with them. Peers find each other, form groups, and share a replicated tuple space in which they post work, claim tasks, publish results, vote on decisions, and recover from each other's failures. The fabric needs no broker, registry, scheduler, or central server. It signs everything it shares and replicates it across the group.

Acmeresearch-fleet runs with no message queue and no job server. coordinator writes a task into the shared space, summarizer on a laptop claims it, and the finding it writes replicates to every member.

What problem does it solve?#

Agents crash, stall on model calls, and come from different teams, frameworks, and languages. Teams usually coordinate them by stitching together a message queue, a database, a service registry, a workflow engine, and an audit log, none of which anyone designed for agents. AgentSpaces replaces that stack with one coordination layer whose data model already handles failure (leases), attribution (signatures), and discovery (advertisements).

AcmeWhen the engineer closes the laptop lid while summarizer is mid-task, Acme needs no retry service and no dead-letter queue. The task's lease runs out, and summarizer-b takes the task.

What is a tuple space?#

A tuple space is a shared associative memory. Participants write entries into it, read the entries that match a template, and take an entry to claim it for themselves. David Gelernter's Linda language described the idea in 1985, and Jini's JavaSpaces brought it to Java. AgentSpaces calls its tuple space an AgentSpace, or simply a space, and replicates it across the peers of a group.

AcmeThe tasks space holds ResearchTask entries. Any member reads them, and a worker takes one to claim it.

Which words should I learn first?#

Seven words carry most of the model. Each has a full answer further down.

  • A peer is one running AgentSpaces process with its own key.
  • A group is a named set of peers that share state and a security perimeter.
  • A space is a replicated tuple space inside a group.
  • An entry is one typed record in a space, such as a task or a result.
  • A lease is the time to live that every piece of shared state carries.
  • An advertisement is a signed, leased document that describes something: a peer, a space, an agent, an asset.
  • A capability is a protocol a peer offers its group beyond the core, such as voting.

What does "everything is leased" mean?#

Every piece of shared state carries a time to live and disappears unless its owner renews it: entries, advertisements, group memberships, capability bindings, and subscriptions. Failure handling therefore reduces, in most cases, to an owner that stops renewing. AgentSpaces inherits this rule from Jini, and the specification calls it the single most important inheritance in the design.

Acmesummarizer's AgentCard carries a 15-minute time to live. When Acme shuts summarizer down, the card ages out of every member's cache, and the fleet stops routing work to it without any deregistration step.

What does "everything is signed" mean?#

Every advertisement, entry, state change, take claim, and ballot carries the Ed25519 signature of whoever made it, and receivers verify the signature before they cache or act on it. The signatures give integrity and attribution, so any member can trace who wrote, claimed, or completed what. A signature tells a receiver who wrote something. Whether the content is safe to act on is a separate question, so applications still validate their inputs.

AcmeEach Finding in the findings space carries summarizer's signature, so Acme's auditors can prove which agent produced it.

What is "the weakest sufficient primitive"?#

It is the design rule that treats consensus as a scarce resource. By default the fabric is eventually consistent (gossip plus CRDTs), a take is exclusive only for the length of its lease, and total ordering is an opt-in capability. A space moves to a stronger mechanism only when its workload needs one, and every API that offers a stronger guarantee states its cost.

What you needThe mechanismIts cost
Share simple workLease raceOne settle window per take
Allocate work by costAuctionA few gossip rounds
Make a decisionQuorum voteSigned ballots and a tally
Take an irreversible actionOrdered logA Raft quorum and a log round trip
AcmeAcme runs research tasks on the lease race, because summarizing a topic twice wastes a little money and harms nothing. It runs license payments through the ordered log, because paying a vendor twice is a real loss.

How is the architecture layered?#

AgentSpaces has five layers, and each depends only on the layers below it. Layer 1, Peering, also covers how a new peer finds its group: bootstrap and beacons are the Layer 1 mechanisms that hand a newcomer its first address, before membership and gossip take over. The programming model, the gateways, and the framework hosts sit beside the stack and use it. A conforming minimal implementation is Layers 0 through 3 on one LAN with the default conflict strategy, and the capability services and wide-area topology add to that base.

AcmeWhen summarizer starts, Layer 0 gives it a key, Layer 1 finds research-fleet and admits it, Layer 2 publishes its AgentCard, Layer 3 hands it tasks, and Layer 4 lets its colleagues vote and pay vendors.

How does AgentSpaces grow new coordination patterns?#

New patterns arrive as capabilities: protocols a peer offers its group beyond the core, such as voting, aggregation, an ordered log, gossip learning, or one you write. A provider announces a capability with a signed, leased advertisement, and consumers find it through discovery like everything else. The core therefore stays small, and the project holds its design to one test: a new capable peer added tomorrow makes the system more capable with no redesign of the system today.

AcmeThe three ledger peers host the ordered-log capability for the payments space. The rest of the fleet finds the current leader by reading the capability's advertisements.

How do I write an agent?#

You write a plain class and annotate its methods. A method's parameter is the cue that starts it, and its return value is the next entry the fabric writes. The binder performs the take, renews the lease, deduplicates deliveries, moves the work off the fabric's threads, and publishes the agent's card.

@AgentSpec(name = "summarizer", description = "Summarizes research topics")
public class Summarizer {

    @SpaceTake(space = "tasks", lease = "10m", resultSpace = "findings")
    public Finding summarize(ResearchTask task) {
        return new Finding(task.topic(), summarizeWithModel(task.topic()), null);
    }
}
AcmeThat class is everything summarizer needs to work the tasks space. Acme deploys the same class as summarizer-b, and the two become competing consumers of one task list.

Which languages and frameworks can join a fleet?#

Java peers run under the Spring Boot starter, the Micronaut factory, or LangChain4j's FleetRuntime with no framework at all, and the Spring AI and Embabel integrations add model calls and planners on top. Clojure and Groovy bindings wrap the Java libraries. Python and TypeScript peers speak the same signed wire protocol, and shared golden vectors prove that they produce the same bytes as Java. One fleet can therefore mix all of them.

Acmecoordinator is a Spring Boot service, summarizer runs on Micronaut, and a data scientist's Python notebook reads findings from the same space.

Where are the boundaries of what AgentSpaces does?#

  • Data. A space holds coordination state and small payloads. Larger payloads travel content-addressed between the peers that need them, and databases join the fleet as assets.
  • Trust. AgentSpaces keeps no global ledger and does not tolerate Byzantine members. Its threat model is one organization's trust boundary, with pluggable interfaces for identity, policy, and transports.
  • Standards. MCP stays the tool layer that agents use, and the A2A gateway bridges the fleet to foreign agents.
  • Consistency. Reads are eventually consistent by default. ConsistencyHint.FRESH costs one round trip, and quorum votes and the ordered log exist for the cases that need agreement.
  • Delivery. The fabric delivers at least once, unless a space takes through the ordered log.

Where do the ideas come from?#

From JXTA, AgentSpaces takes the peering model: identities independent of network location, peer groups as trust and discovery scopes, advertisements as the universal discovery format, and rendezvous and relay roles. From Jini and JavaSpaces it takes the coordination model: a typed tuple space, leases on all state, event notification, and the replicated worker. From the modern peer-to-peer literature it takes SWIM membership, epidemic gossip, push-sum aggregation, CRDTs, hybrid logical clocks, Raft, and CBBA auctions. The project's contribution is the composition: one identity layer under all of them, one lease rule across all of them, and one rule for choosing which of them answers which question.

Where do I start?#

With JDK 21 and Maven, clone the repository, install it, and run the one-file quick start, which starts two peers on TCP ports 7591 and 7592:

git clone https://github.com/badmonkeyai/AgentSpaces.git agentspaces
mvn -f agentspaces/pom.xml install -DskipTests
cd agentspaces && mvn -q -pl examples/example-11-quickstart exec:java

The release artifacts are on Maven Central as ai.badmonkey.agentspaces:*:0.4.0, and the bill of materials agentspaces-dependencies aligns their versions. The developer guide teaches the API chapter by chapter, the workflow guide shows the coordination patterns, and the architecture guide draws the layers.

Part 2 · Layer 0

Identity: who is speaking

Layer 0 gives every peer and every agent a key, and derives every name the fabric uses from a key or a hash. Everything above it trusts a statement only when the right key signed it.

What is a PeerID?#

On its first start a peer generates an Ed25519 key pair (RFC 8032) and derives its PeerID as multibase(sha-256(public key)), a string that starts with z. The peer keeps the key pair in its keystore, so the PeerID stays the same across restarts, addresses, and transports. The peer signs every message and advertisement with that key, and receivers verify the signature before they cache or act on anything. A peer started without a keystore gets a fresh identity on every start.

Acmesummarizer keeps its keys in ./peer-keys (the agentspaces.keystore property). The engineer carries the laptop from the office Wi-Fi to a home network, and summarizer keeps the same PeerID because its key stays the same.

What is an AgentID?#

A peer can host several logical agents. An AgentID is a PeerID plus a local name, written <peerId>/<localName>. By default an agent signs with its peer's key, and the fabric attributes the agent's work on the peer's word.

AcmeThe three reviewers run on one peer as <peerId>/reviewer-1, <peerId>/reviewer-2, and <peerId>/reviewer-3.

What is a subordinate agent key?#

An agent may carry an Ed25519 key of its own, which its peer certifies with an AgentCertificate: the agent's name, its public key, an issue time, a lifetime, and the peer's signature. The agent then signs its own records, claims, and state changes, and receivers check the certificate under the peer's key before they check the agent's signature. Receivers judge a certificate at the signing time of the thing it certifies, and the peer re-issues certificates at half-life (24-hour lifetimes by default), so an agent can run indefinitely. The Spring starter turns this on with agentspaces.identity.agent-keys=subordinate, and the agent classes contain no identity code.

AcmeAcme turns on subordinate keys so that each reviewer's ballot is that reviewer's own signed record. When Acme's vote grant names the three reviewers' AgentIDs, the tally counts each reviewer once, even though all three run on one peer.

What do PEER_ASSERTED and AGENT_ATTESTED mean?#

A replica reports, for every entry, how it knows who wrote it. PEER_ASSERTED means the peer vouched for the agent's name with the peer's key. AGENT_ATTESTED means the agent's own certified key signed the entry. A certificate proves who signed. What an agent may do remains a decision for the authorizer.

AcmeWith subordinate keys on, every Finding that summarizer writes reads as AGENT_ATTESTED at every replica.

What are aspace:// names, and what does self-certifying mean?#

Names in the fabric are URIs: aspace://<groupID> names a group, aspace://<groupID>/<spaceName> a space, and aspace://<groupID>/<spaceName>#<entryID> an entry. A GroupID or SpaceID that comes from a founding document is the hash of that document, which makes it self-certifying: whoever holds the document can prove the name, and a receiver that re-derives the id from a document a peer hands it detects a substituted policy.

AcmePartner Inc's group id, aspace://q9c2b..., is the hash of Partner Inc's signed founding. When a seed hands summarizer a founding document, summarizer hashes it and joins only if the result is exactly q9c2b....

Can a fleet use DIDs and verifiable credentials?#

Yes, as an option. A fleet can write a PeerID as a W3C did:key: identifier, and a resolver interface lets a group's membership policy accept DIDs and verifiable credentials issued elsewhere. The core does not depend on them.

AcmePartner Inc could admit Acme's peers with a POLICY validator that checks a verifiable credential Acme's identity team issued.
Part 3 · Layer 1

Peering: groups, membership, and gossip

Layer 1 decides who is in a group and carries everything the group says. It answers who belongs, who is alive, how news spreads, and how bytes get from one peer to another.

What is a peer?#

A peer is one running AgentSpaces process: a Spring Boot service, a Micronaut service, a Python script, a browser tab. Each peer has its own identity key. A peer can listen for connections on an address, or it can only dial out, as a laptop behind a home router does.

Acmeseed-a listens on seed-a.corp.example:7500. summarizer, on a laptop, only dials out.

What is a group?#

A group (a peer group) is the unit of scope. It defines a membership policy, a gossip domain, and a namespace for spaces and capabilities, and its id looks like aspace://z7f3a.... A peer can belong to many groups at once, and applications often start a group per mission, per tenant, or per conversation.

Acmesummarizer belongs to research-fleet and to Partner Inc's partner-fleet at the same time. Each group has its own members, spaces, and policy.

What is the difference between a founding text and a signed founding?#

A group's id comes from one of two places, and that decides how a peer can enter the group.

  • A founding text. Every peer receives the same text, such as founding: research-fleet-v1, and derives the same group id from it by itself. There is no signed document and no secret to distribute. This fits one organization whose operators control every peer's configuration. Nobody can join a text group by id, because it has no founding to serve; an operator adds a peer by giving it the text.
  • A signed founding. A founder signs the group's immutable founding fields (name, founder, issue time, lifetime, membership policy, default conflict strategy, gossip parameters). The pair of fields and signature is the founding document, and the GroupID is its hash. A peer that holds only the id asks a member for the document (GROUP_AD_WANT, answered by GROUP_AD), checks that it hashes to exactly that id, and only then introduces itself.
Acmeresearch-fleet uses a text. Partner Inc's partner-fleet has a signed founding, so summarizer joins it with join: aspace://q9c2b.... A hostile seed can delay that join, and it cannot substitute a different policy.

What is a GroupAdvertisement?#

The GroupAdvertisement is the signed document that describes a group: its name, its GroupID, its membership policy, the default conflict strategy for its spaces, and its gossip parameters (fan-out 3 and period one second by default). It lives 24 hours by default before its issuer must refresh it. A member verifies every group advertisement it learns from the network before it joins or acts on it, and it never serves a newcomer one it cannot verify.

What is a membership policy, and what is admission?#

The membership policy decides who may join. OPEN admits every peer whose signed self-introduction verifies. INVITE admits only peers that present a credential signed by the founder (or under a founder's delegation) and bound to their PeerID. POLICY hands the decision to a pluggable validator, such as a DID or LDAP check. Every member enforces the policy at admission, the moment it decides whether a newcomer enters its view. A peer that fails admission never enters membership and can gossip nothing into the group. A verified signature proves who wrote an introduction, and only the policy says whether its author may join, which leaves an OPEN group open to anyone who can reach it.

Acmeresearch-fleet is OPEN because only Acme's network can reach it. partner-fleet is INVITE: Partner Inc admits only the Acme peers it has issued credentials to.

What is an invite credential, and what is an invite key?#

An invite credential is the proof an INVITE group asks for, carried in the newcomer's self-advertisement under the hint aspace:join. It has two forms, and every member checks either one with public data. The founder-issued form is the founder's signature over the candidate's PeerID and the group. The delegated form adds a delegation: the founder signs an invite key, the group, an expiry (notAfter), and a label, and whoever holds that invite key signs candidates under it. The expiry limits first admission only; a member admitted in time stays admitted until the founder revokes the credential or the delegation.

AcmePartner Inc gives Acme's team lead an invite key that is valid for one week. The lead admits Acme's peers to partner-fleet without asking Partner Inc's founder to sign for each one.

How does membership work, and what is a view?#

Each member regularly sends a leased, signed self-advertisement (its PeerAdvertisement) on the reserved peers stream, and that refresh is its proof of life, a claim only that member can make. A peer's view of a group is the list of members it currently knows. A member that stays silent past the member TTL (30 seconds by default) drops out of every view without ceremony. A SWIM-style probe cycle detects failures sooner: once per protocol period (one second by default) a node pings the next member in a shuffled round-robin order, asks two other members to ping it indirectly when it does not answer, and marks it suspect if they get no answer either. Suspicion stays local. No member ever gossips a verdict about another member, so the group learns of a join from the joiner's own signed advertisement and of a departure from its silence.

Acmeseed-a and seed-b learn of summarizer from summarizer's own signed introduction. When the laptop sleeps, they stop hearing from it and drop it from their views after 30 seconds. Nobody announces that it left.

How does a peer leave a group?#

It stops refreshing and stops answering in that group. The protocol has no leave message. The other members drop the peer at its member TTL, exactly as they drop a member that crashed. A node that leaves one group keeps its other groups and the connections it shares with their members.

AcmeWhen Acme's contract with Partner Inc ends, summarizer leaves partner-fleet and stays in research-fleet.

What is gossip, and what are its two channels?#

Each group runs a gossip bus with two channels. The rumor channel pushes each new item to a few sampled members (the fan-out, 3 by default), and each receiver forwards it to a few more while the item's hop budget (6) lasts, so news reaches the whole group in a number of rounds that grows with the logarithm of its size. Receivers deduplicate items by stream and payload hash. The anti-entropy channel makes delivery certain: once per gossip period a node compares digests of its state with one random partner and pulls what it lacks, and it backs off, up to 32 periods, while nothing changes. Rumors make news fast, and anti-entropy makes sure every member eventually has it.

AcmeWhen summarizer writes a Finding, the rumor reaches seed-a, seed-b, and the beacon within a hop or two. summarizer-b, restarting at that moment, gets the finding at its first anti-entropy round.

What is a stream?#

A stream is a named channel on the gossip bus. The fabric reserves several: peers for self-advertisements, revocations and credential-revocations for revocations, and view for the membership view. Each space adds a stream named space:<name>, and each component registers its own anti-entropy state under its stream.

AcmeEntries in the tasks space travel on the stream space:tasks, and entries in findings on space:findings.

What is lazy push?#

Lazy push is how the rumor channel avoids sending each item to each member several times. Between members that advertise the hint wire.tree=1, the bus pushes items eagerly along a spanning tree that prunes itself: a member that receives a duplicate sends a PRUNE to cut that edge. Members off the tree hear short HAVE announcements and ask for a missed item with a GRAFT. The design follows the Plumtree protocol of Leitão, Pereira, and Rodrigues, and in the steady state each item reaches each member once. Members without the hint keep the classic random fan-out.

What is a tick, and what is the peer sampler?#

Progress in a peer is tick-driven. On each tick a node refreshes its self-advertisement when its interval comes due, runs its probes, and starts an anti-entropy round when the gossip period has passed; the examples tick every 250 milliseconds. Capabilities hang their own protocol steps off the same tick, so a peer runs on one clock. The peer sampler, PeerSampler.randomMembers(n), draws random members from the view, and every gossip channel and capability chooses its partners through it.

What are the rendezvous and relay roles?#

Any peer may take on extra roles and advertise them. A rendezvous keeps a larger advertisement cache (four times the default) and answers discovery queries for peers with little memory or short uptimes. It is only a cache, so losing one costs discovery latency and nothing else. A relay forwards frames for peers that nobody can dial, such as a laptop behind a home router. It forwards a frame only to a member of the group the frame names, and the inner frame stays signed by its origin, so the relay cannot alter what it carries.

AcmeThe beacon plays rendezvous. seed-b plays relay, so a member can reach summarizer at home through the connection summarizer opened to seed-b.

What is a transport, and which ones ship?#

A transport carries length-prefixed byte frames (at most 8 MiB each) between two peers. Its interface is small: dial, listen, and capabilities(), which reports any of ENCRYPTED, ATTESTING, RELIABLE, and ORDERED. Everything above the transport stays the same whichever one carries the frames. The shipped bindings are:

SchemeWhat it is
memAn in-process loopback for tests and single-process fleets
tcp, tlsFrames over a socket, and the same inside TLS 1.3 (RFC 8446)
quicOne bidirectional QUIC stream per connection (RFC 9000)
dtls, udpDTLS 1.2 on UDP (RFC 6347) with Connection ID (RFC 9146) and a recovery layer, and the same recovery layer on plain UDP for closed networks
ws, wssWebSocket (RFC 6455), plain and inside TLS
http, httpsBatched frames through HTTP requests, for networks whose proxies break WebSocket
webrtcA WebRTC data channel, so a browser can join a fleet
AcmeAcme's servers speak tls and quic. A browser dashboard joins the same fleet over wss.

What is an endpoint, and what is the difference between bind and advertise?#

A peer lists its endpoints in its PeerAdvertisement as (transport, address, priority). Dialers try endpoints in ascending priority and skip schemes they cannot dial, so a fleet can run mixed transports and move between them by changing priorities. A peer binds the address it listens on and advertises the address others should dial (agentspaces.advertise), and the two differ behind NAT and in containers.

AcmeIn Kubernetes, summarizer-b binds 0.0.0.0:7500 and advertises ${POD_IP}:7500, the address other members can reach.

What is channel attestation?#

Every frame carries the sender's signature by default. When the transport itself authenticates the channel, that per-frame signature repeats work the handshake already did, so the tls, quic, and dtls bindings can attest the remote peer instead. Each peer presents a channel certificate: a fresh P-256 TLS key in a self-signed X.509 certificate that the peer's Ed25519 identity key endorses. The handshake then binds the connection to a PeerID, the two ends agree with a signed CHANNEL_HELLO, and frames on that connection may travel without their own signatures. An enterprise can use CA-issued certificates with CRL or OCSP checking, and required attestation (agentspaces.transport.tls.require-attestation) refuses every frame that arrives on an unattested connection, so a CA revocation removes a member from the fleet. The signatures on records, state changes, claims, and advertisements never change, whatever the transport attests.

AcmeOn the TLS link between seed-a and summarizer, frames travel without per-frame signatures, which saves both ends work. Each Finding on that link still carries summarizer's record signature.

What is session attestation?#

Session attestation attests a connection that the transport cannot attest, such as plain TCP. The two ends exchange one fully signed SESSION_HELLO each, derive a shared key from ephemeral X25519 keys, and from then on tag each frame with an HMAC under that key in place of an Ed25519 signature. The dev-local security profile selects it.

Part 4 · Layer 1, joining

Finding a group: bootstrap, seeds, locators, and beacons

These terms come from the agentspaces-bootstrap and agentspaces-beacon projects. They cover one step of Layer 1: how a peer that knows nobody finds its first member. Once a peer has met one member, gossip does the rest.

What is bootstrap?#

A peer that has just started has an empty view and knows nobody. It has to dial something, and nothing inside the group can tell it what. Finding that first address is bootstrap. In these projects the word means that one step; admission and gossip start afterward.

Acmesummarizer knows the group's name and its founding text, and no addresses. Bootstrap is how it learns that seed-a.corp.example:7500 is a place to start.

What is a seed, and what is name expansion?#

A seed is an address a newcomer dials first, written host:port or scheme://host:port. Any member that listens for connections can act as one, and a peer that has joined no longer needs its seed. With name expansion, a seed that DNS resolves to several addresses becomes one seed per address, and the peer dials them all.

Acmeseeds.corp.example has two A records and one AAAA record. Acme configures seeds: [ "seeds.corp.example:7500" ], and summarizer dials all three addresses. It keeps working if seed-a goes away later.

What is a locator, and what is a hint?#

A locator is one way of finding where to dial. The peer tells it which group it wants, and the locator answers with a hint: addresses in priority order, and optionally the group id it believes the group has, the signed founding document, a lifetime, and the evidence that produced the answer. A locator only suggests addresses and never admits anyone, because the peer dials each address as it would dial any stranger. A wrong DNS answer can delay a join, and it cannot place a stranger in the group.

LocatorWhat it asks
seedsThe configured list, with name expansion (core)
dns-sdDNS-SD (RFC 6763) under the network domain: PTR, then SRV and TXT records
dns-txtOne TXT record at agentspaces.<domain> that points to a beacon document
dns-srvSRV records (RFC 2782) at an owner name you choose
k8sThe SRV records Kubernetes publishes for a headless service
urlA beacon document fetched over HTTPS
documentA beacon document read from a file, for networks with no outside access
multicastAddresses heard in LAN multicast datagrams (core)

What is the network domain?#

The network domain is the DNS domain the host belongs to, and the dns-sd and dns-txt locators look under it. With domain: auto, the peer finds it as the host does: from the AGENTSPACES_DOMAIN environment variable, from the search and domain lines of /etc/resolv.conf, or on Windows from the search list.

AcmeThe laptop on Acme's Wi-Fi receives the search domain corp.example from DHCP, so dns-sd finds research-fleet with no seeds configured.

What is a chain, and how does it answer?#

A chain is the ordered list of locators one group uses. Each group has its own chain, because each group can need a different way of being found. When a peer asks a chain about a group, the chain asks every locator that applies at once, each with its own deadline (3 seconds by default); merges the answers in chain order so the first locator's addresses rank highest; removes duplicates; keeps the first founding document it finds; accepts a group id claim only from the locators named in accept-group-id-from; expands names into addresses last; and gives the answer the shortest lifetime among the locators that contributed. With first-wins: true, the chain asks one locator at a time and stops at the first one that returns addresses. A peer asks its chain when it joins and again whenever its view of the group is empty, no sooner than every 30 seconds and no later than every 10 minutes.

  summarizer wants research-fleet
              |
              v
  research-fleet's chain: [seeds, dns-sd, url], all asked at once
  +--------------------+-----------------------+---------------------+
  | seeds              | dns-sd                | url                 |
  | seeds.corp.example | SRV: seed-a, seed-b   | document lists      |
  | :7500              | TXT: url=...          | beacon, seed-a,     |
  |                    |                       | and seed-b          |
  +--------------------+-----------------------+---------------------+
              |
              v
  merge in chain order, remove duplicates, expand names to addresses
              |
              v
  dial the addresses in order and introduce itself;
  from here gossip takes over
Acmesummarizer uses [seeds, dns-sd, url] for research-fleet and [url] for partner-fleet, whose beacon document lives at https://partner.example/.well-known/agentspaces/beacon.json.

What does "beacon" mean?#

The word names three different things.

  1. A beacon is a peer that newcomers can find and dial first: an ordinary member with a stable address, usually playing the rendezvous role. Nothing in the protocol marks a peer as a beacon; the word describes how an operator uses a member. The agentspaces-beacon project runs one as a standalone program, or you embed its classes in your own application.
  2. The beacon document is the signed JSON file a beacon serves.
  3. The multicast beacon is a UDP datagram, off by default, that members send so peers on one LAN segment find each other.
AcmeAcme runs a beacon at beacon.corp.example so that a new agent can find the fleet without anyone editing a seed list. A lost beacon slows newcomers and nothing else, because members that have joined learn the rest of the group by gossip. Acme runs a second beacon for availability, and each lists the other as a seed.

What is the beacon document?#

The beacon document is a signed JSON file that a beacon serves at /.well-known/agentspaces/beacon.json. For each group the beacon has joined it lists the name, the id, the seeds, and the wire hints, and it adds the signed founding when the group has one. It never carries a secret. The beacon builds the seed list from its live view of the group, itself first, then the rendezvous members, then the other members that listen, so the list follows the fleet. The beacon's identity key signs the document, and a reader can pin that key with beacon-peer.

{
  "v": 1,
  "issuer": "zDnaCm6XCa...",
  "issued": "2026-10-21T19:35:30Z",
  "ttl": 300,
  "groups": [ {
    "name": "research-fleet",
    "id": "aspace://zDXTnY2y...",
    "seeds": [
      { "transport": "tls", "address": "beacon.corp.example:7500", "priority": 0 },
      { "transport": "tls", "address": "seed-a.corp.example:7500", "priority": 1 }
    ],
    "wire": { "batch": 1, "hashes": 1, "tree": 1 }
  } ],
  "signature": "<base64 Ed25519 signature over every other field>"
}
AcmePython and TypeScript agents read the same document at its URL, verify the signature, and take its seeds. For partner-fleet, Partner Inc's document also carries the founding, so summarizer can check it against aspace://q9c2b... before it dials.

Which DNS records point to a fleet?#

At startup a beacon prints a zone fragment for your DNS team to register: a PTR record that names the group's instance under _agentspaces._tcp.<domain>, an SRV record per seed, a TXT record with the group name, id, scheme, and document URL, and one pointer TXT record at agentspaces.<domain> that holds only url=. The beacon never changes your DNS itself. SRV records you register by hand do not follow the fleet, so a fleet whose seeds change often registers only the pointer record and lets the document carry the seeds.

_agentspaces._tcp.corp.example.               IN PTR  research-fleet._agentspaces._tcp.corp.example.
research-fleet._agentspaces._tcp.corp.example. IN SRV  10 50 7500 beacon.corp.example.
agentspaces.corp.example.                     IN TXT  "v=1" "url=https://agentspaces.corp.example/.well-known/agentspaces/beacon.json"

What are the multicast beacon and the sealed beacon?#

The multicast beacon is an opt-in UDP datagram that a member sends at an interval, once per joined group, carrying only its signed self-advertisement with an IP TTL of 1. A peer on the same LAN segment verifies it, applies the group's admission policy, and treats the advertised endpoints as seeds. The sealed beacon encrypts that datagram under a key derived from the group's content key, so a bystander on the segment learns neither the group, the issuer, nor the endpoints.

AcmeAcme's robotics lab, where every peer shares one network segment, turns the multicast beacon on and needs no seeds at all.

What does a peer check before it trusts a locator's answer?#

  • The peer only dials addresses. Every connection goes through the same handshake, signature checks, and admission policy as a connection from any stranger.
  • The peer verifies a founding when there is one. A peer joining by id checks the founding against the id in its configuration.
  • A group id claim needs a named source. The chain accepts a locator's claim about the group id only from the locators in accept-group-id-from, which defaults to url and document. Plain DNS answers carry no signature, so naming a DNS locator there stops the application at startup unless you allow it explicitly or use a DNSSEC-validating resolver.
  • An operator can pin a document. beacon-peer names the PeerID that must have signed any document, and the url locator fetches over HTTPS, caps the size, limits redirects, and refuses private addresses by default.
AcmeAn attacker poisons the DNS answer for one of partner-fleet's seed names, and summarizer dials the attacker's host. That host cannot show a founding that hashes to aspace://q9c2b..., so summarizer does not join it and asks its chain again later.

What is a host?#

A host is the framework that creates your peer: the Spring Boot starter or the Micronaut factory. The host builds one chain per group from the agentspaces.bootstrap.* properties and from any BeaconLocator beans the application defines, so you can add your own way of finding a group as a bean.

AcmeAcme adds a locator bean that asks its cloud provider's service registry, and the host places it in every group's chain after the property locators.
Part 5 · Layer 2

Advertisements and discovery: what is out there

Layer 2 describes everything in the fleet with one kind of document, the signed and leased advertisement, and lets any member find what it needs from its own cache first.

What is an advertisement?#

An advertisement is a signed, typed document with a time to live. It names its type, its id, its issuer, its group, its issue time, how long it lives, and a type-specific body, and the issuer's signature covers all of it. On the wire it travels as canonical CBOR, and the documentation shows it as JSON. Discovery, trust, and binding all work on advertisements, an idea AgentSpaces takes from JXTA and strengthens by making the signatures mandatory.

{
  "type": "aspace:CapabilityAdvertisement",
  "id": "aspace://zDXTnY2y.../cap/ordered-log/peer-...",
  "issuer": "peer:...",
  "issued": "2026-10-21T14:02:11Z",
  "ttl": "PT15M",
  "body": { ...type-specific... },
  "sig": "ed25519:..."
}

What does an advertisement's time to live do?#

The TTL bounds how long caches keep an advertisement after its issue time. Caches evict expired advertisements and never forward them, and an issuer refreshes by publishing again with a new issue time. Short TTLs act as the liveness check: a fresh advertisement answers "does this peer still offer this?" with no extra round trips. The recommended defaults are 10 minutes for a PeerAdvertisement, 15 minutes for AgentCards, SpaceAdvertisements, and capability advertisements, and 24 hours for a GroupAdvertisement.

AcmeThe binder refreshes summarizer's card every five minutes (card-refresh-millis), well inside the card's 15-minute TTL.

Which advertisement types exist?#

TypeWhat it describes
PeerAdvertisementA peer: its endpoints, roles, resource hints, and wire hints
GroupAdvertisementA group: name, id, membership policy, default strategy, gossip parameters
SpaceAdvertisementA space: name, conflict strategy, schema hints, admission rule, replication mode
CapabilityAdvertisementA capability a peer offers: type URI, version, binding, parameters, cost hints
AgentCardAn agent: what it does, its goals, what it consumes and produces, and where
AssetCardData a peer provides, such as a database or an archive
RevocationAdvertisementA permanent withdrawal of a peer's identity
CredentialRevocationA withdrawal of an agent, an agent key, a channel certificate, or a join credential

What is an AgentCard?#

An AgentCard describes one agent for humans and for models: a description, the goals it can pursue, the entry types it consumes and produces, cost hints, the space it takes each input type from, its declared actions, and, for an agent with its own key, that key and its certificate. A card carries no network address, because the fleet reaches agents by writing entries. The binder publishes one card per agent into every group the agent joins and refreshes it, and the card stays close enough to an A2A Agent Card that the gateway translates it mechanically.

Acmesummarizer's card says "Summarizes research topics", consumes ResearchTask from tasks, produces Finding, and declares one action, summarize, of kind take.

What are card actions and space bindings?#

A card's space bindings map each entry type the agent consumes to the space it takes that type from, so a caller can route an input without configuring routes. Its actions declare each bound method separately: the name, a description, what it consumes and produces, the space, and how it is bound (take, notify, ordered-take, ballot, on-decision, embabel-action, join, propose, on-estimate, or reduce). Readers then use the declared pairs of inputs and outputs, and a planner sees one action per method. A card declares at most 64 actions.

What is an AssetCard?#

An AssetCard is the AgentCard's sibling for peers that provide data and pursue no goals. A connector joins a group on behalf of a warehouse, database, search cluster, message broker, or web service and publishes one card per asset: its name and source URI, a description, the shape of its data, how fresh it stays, size and cost hints, and how to query it. Agents find assets exactly as they find agents, and the connector turns incongruent data from its source into typed entries whose shape the card declares.

Acmedocs-connector publishes an AssetCard for acme-archive, Acme's archive of past research reports, with query access through the data-query capability.

What is the ad-cache?#

Every peer keeps a local ad-cache per group, which gossip fills. It verifies every signature before it stores an advertisement, bounds how many it holds, and evicts each one when its TTL runs out. A rendezvous peer keeps a cache four times larger.

How does discovery find things?#

Discovery is local-first. find(type, predicate) queries the local ad-cache and returns at once. remoteFind escalates in parallel to the group's rendezvous peers and to a scoped gossip query under the hop budget, then searches the cache again as answers arrive. It checks the predicate against the advertisement type before it sends anything, so a predicate that names an unknown field fails at once. Core predicates are structural (a type and field matchers), and matching by meaning is a Layer 4 capability, semantic discovery.

Acmesummarizer calls find(AssetCard.class, ...) to locate acme-archive, and the cache answers without touching the network.

What happens to an advertisement a peer cannot understand?#

A receiver that meets an enumerated value it does not know, such as a new admission rule, treats the advertisement as undecodable and drops it without caching or forwarding it. It never substitutes a default. An older peer therefore stays out of a space whose rules it cannot read, which is safer than joining it under the wrong rule. Decoders do ignore unknown appended fields, which is how the format grows.

What is a revocation?#

A RevocationAdvertisement withdraws a peer's identity permanently. Its signer gives it authority: the group's founder by default, or, in enterprise-CA mode, any member whose evidence (the peer's certificate chain and a CRL that lists it) validates to the CA. A revocation travels on its own gossip stream with anti-entropy, so late joiners learn of it, and it stays out of the ad-cache, because a TTL there would let it expire. A revocation can name a successor, which is how a self-certifying identity rotates to a new key. A CredentialRevocation withdraws something a peer certified: an agent, one agent key, one channel certificate, or one join credential. Part 9 describes how members enforce both.

Part 6 · Layer 3

The AgentSpace: shared, leased, replicated memory

Layer 3 is the tuple space. It gives every member of a group the same operations on the same entries, keeps working through partitions, and turns failure into an expired lease.

What is a space?#

A space is a typed, replicated tuple space inside one group, identified by aspace://<groupID>/<spaceName>. A member creates one by publishing a SpaceAdvertisement, which states its conflict strategy, the entry types it expects, its admission rule, and its replication mode (FULL or TAG_SHARDED), and any member may attach. LocalSpace runs in one process, which suits tests. ReplicatedSpace replicates across the group as a delta-CRDT over gossip.

Acmeresearch-fleet has five spaces. tasks and findings use the default lease race, tasks-auction uses AUCTION, votes holds ballots, and payments takes through the ordered log.

What is an entry?#

An entry is any serializable domain object, usually a Java record, registered with the space's schema registry under a schema name (by default <fully.qualified.ClassName>#v1). The space wraps each entry in an EntryRecord: an issuer-generated id, the space id, the type, the payload (inline up to 64 KiB, or a content hash for larger ones), the issuer, an issue stamp from the hybrid logical clock, the lease, indexable tags, and the issuer's signature.

Acmenew ResearchTask("agentic memory", 3, "coordinator") is an entry. So is the Finding that answers it.

What are the space operations?#

OperationWhat it does
write(entry, lease)Publishes an entry. The write lease is the entry's time to live.
read, readAllReturn matching entries without removing them.
take(template, lease, timeout)Claims one matching entry exclusively under a take lease and the space's conflict strategy.
complete(taken, result?)Consumes the taken entry for good and writes an optional result in the same step.
notify(template, listener, lease)Registers a leased subscription to matching events.

complete builds and checks the result before it commits, so a result that cannot be written never leaves a task completed with no result.

Optional<TakenEntry<ResearchTask>> taken = tasks.take(
        Template.of(ResearchTask.class).where("priority", gte(3)),
        Lease.of(Duration.ofMinutes(10)), Duration.ofSeconds(5));
taken.ifPresent(t -> tasks.complete(t,
        new Finding(t.entry().topic(), "...", null), Lease.of(Duration.ofHours(1))));

What is a template?#

A template says which entries an operation matches: a type plus conditions on fields and tags, such as Template.of(ResearchTask.class).where("priority", gte(3)). Matching runs against the local replica, so reads never block on the network. Within one entry type, a single node returns the oldest match first. Tag conditions (whereTag, hasTag) run before the replica decodes the payload, so a relay or a shard can select by tag without the content key. A portable text grammar (field op literal, with =, !=, <, <=, >, >=, and in) lets every language state the same conditions identically.

Acmesummarizer-b runs on a GPU node, so it takes only tasks with priority >= 3 and leaves the small ones to the laptop.

What are a write lease and a take lease?#

A lease is a time to live that its holder must renew. An entry's write lease is its lifetime, so an entry nobody renews vanishes. A taker holds a take lease on the entry it claimed: if the taker dies, or lets the lease lapse without calling complete, the entry reappears for someone else. This is the JavaSpaces crash-recovery idiom, the replicated worker or bag of tasks, built on leases where JavaSpaces used transactions.

Acmesummarizer takes "agentic memory" under a 10-minute take lease, and the laptop's battery dies. The lease lapses, the task reappears, and summarizer-b takes it and writes the finding. coordinator sees one finding and writes no retry code.

What is notify, and which events exist?#

notify registers a leased subscription, and events arrive at least once, deduplicated by entry. The event kinds are WRITTEN, TAKEN, COMPLETED, EXPIRED, and REAPPEARED, and a replicated space emits the last two from its lease sweep exactly once per transition. Applications build complex event processing (CEP) and watchdogs on this event stream.

Acmecoordinator subscribes to REAPPEARED on tasks and counts how often workers drop tasks, an early sign of an overloaded model endpoint.

How does a space replicate?#

A replicated space is a delta-CRDT (conflict-free replicated data type). The entry set is an observed-remove set keyed by entry id, the lease fields are last-writer-wins registers ordered by the hybrid logical clock, and deltas ride the gossip channels. Replicas that have seen the same updates are identical, partitions merge deterministically, and a disconnected member keeps serving reads, writes, and (when the strategy allows) takes from its own replica. A replica keeps the tombstone of a completed or expired entry for twice the longest lease it has seen (at most 24 hours) and then collects it, and it refuses a lagging partner's attempt to bring a collected entry back.

Acmesummarizer loses its network on a train. It keeps reading its local replica and writing findings, and when it reconnects, its writes merge into every other replica.

What is a conflict strategy?#

An exclusive take is the one operation a CRDT cannot express, so each space declares a conflict strategy that decides which taker wins. LEASE_RACE is the default, AUCTION allocates by cost, and ORDERED serializes takes through the ordered log. The API stays the same across strategies, and only the guarantees and the latency change. A space uses one strategy for all its entries, so an application that needs several uses several spaces, the way it would use several queues.

What is a lease race?#

In a lease race, each taker writes a signed claim on the entry and waits one settle window (200 milliseconds by default in the starter, about twice the gossip period in a tuned fleet). The claim with the lowest pair of clock stamp and PeerID wins at every replica, and the others get an empty result and try another entry. The merge rule allows at most one completion per entry, so a lease race never completes an entry twice. During a partition two workers can briefly do the same work, which is why idempotent tasks suit it best. A replica refuses claims stamped more than ten minutes before the entry was issued, so nobody wins every race by back-dating.

Acmesummarizer and summarizer-b claim the same task within a few milliseconds. After the settle window both see that summarizer's claim won, and summarizer-b takes the next task.

What is the take claim lattice?#

A take claim is TakeClaim{epoch, stamp, holder, bid, expiresAtMillis}, signed by its holder. The claims on one entry merge by a fixed preference: the higher epoch wins (the epoch grows each time someone re-claims a lapsed entry), then the lower bid, then the lower stamp and holder, and among one holder's claims the later expiry, which is how renewal works. The merge always returns one of its two inputs, so the holder's signature survives any number of merges and hops.

What is an auction space?#

In an AUCTION space a take is a bid. Each agent bids through a @BidFunction, the lower bid wins, and rounds of a CBAA/CBBA-style auction over gossip converge on a conflict-free, least-cost assignment, which turns the space into a decentralized task allocator. Bid functions are ordinary application code, and a fleet may learn them as policies. The specification accepts that a lying bidder can win work it never performs, and the lease lapse that re-offers the work is the operational remedy.

@BidFunction(space = "tasks-auction")
public double bid(ResearchTask t) {          // lower = cheaper = selected
    return estimatedTokens(t) * costPerToken() + queueDepthPenalty();
}
Acmesummarizer uses a small local model and bids low on short topics. summarizer-b rents a large model and bids low only on long reports, so each task lands where it costs least.

What does ORDERED mean?#

ORDERED gives exactly-once takes. Takes pass through the ordered-log capability, a small Raft quorum, and its take coordinator admits exactly one claim per epoch, so every member decides the same winner whenever it applies the log. The coordinator installs each committed claim exactly as its holder signed it. The price is quorum liveness: a majority of the log's members must be up. Use it for entries that are neither idempotent nor cheap to repeat.

AcmeEach LicenseOrder in payments pays a vendor real money, so the clerks take orders through the ordered log, and the desk pays each order once even when a clerk dies mid-payment.

What is content addressing?#

A payload larger than 64 KiB travels by its content identifier, CID = base58btc(sha-256(bytes)). The space replicates only the record, and a block exchange (BLOCK_WANT and BLOCK) moves the bytes between peers that need them. A receiver accepts a block only when its bytes hash to the CID, so integrity checking and deduplication are one mechanism. Reads never wait for a block: a read that meets a missing block starts one background fetch.

Acmesummarizer attaches a 3 MB extract to a finding. Gossip carries the small record at once, and publisher fetches the extract only when it reads the finding.

What is ConsistencyHint.FRESH?#

Reads use ConsistencyHint.LOCAL by default and match the replica as it stands. FRESH first runs one anti-entropy pull from one random member and then matches locally, which costs a round trip and narrows the window in which a just-written entry is missing.

Acmepublisher reads with FRESH right after a decision closes, so it sees the finding the vote was about even if its rumor has not arrived yet.

What are tags and tag sharding?#

Tags are a string map on each entry record. They stay readable under a group content key, so a member without the key can still match and route by them. A tag-sharded space lets a replica hold only the slice of a space that its tag predicate selects. Because tags and type names stay readable, payloads whose shape must not leak need neutral type names and tags.

AcmeAcme tags each task with its region, and the European cluster's replicas hold only region=eu tasks.

Who may write to or take from a space?#

The space's admission rule decides, and every member applies the same rule because the SpaceAdvertisement carries it. Reads stay open to the whole group.

  • GROUP, the default: every group member may write and take.
  • ALLOWLIST: only the AgentIDs the founder lists.
  • CREDENTIAL: a credential issuer writes leased SpaceCredential entries into the space that grant WRITE, TAKE, or both to an agent, and cancels them to revoke.
  • AUTHORIZER: the space asks the group's authorizer for SPACE_WRITE and SPACE_TAKE.

Admission applies to the acting agent, so a space can admit one agent of a peer and refuse its sibling.

Acmepayments uses ALLOWLIST and lists the three clerks, so no other agent can take a payment order.

What is a view of a space?#

Several agents on one peer share one replica of a space through views. A view is the same space seen as another agent of that peer: that agent issues and signs its writes, its claims name that agent as holder, and the space judges its admission for that agent. A view has no state of its own.

AcmeThe three reviewers share one replica of votes, and each writes its ballot through its own view.

What happens when a space's founder goes away?#

A space built with a founder lease turns read-only when that lease lapses, and a founder can also mark it read-only on purpose. A read-only space refuses write and take, still serves reads and subscriptions, and still accepts a complete so work in flight can finish. It stops refreshing its advertisement, and the advertisement's lapse tells the fleet that the founder has released the space.

Which entry types does the library reserve?#

A few entry types belong to the library, and every replica names them identically whatever registry the application uses: SpaceCredential (admission), the vote's Proposal, Ballot, and Decision, and JoinTicket, which a fan-in writes and takes in its fleet-wide modes.

Part 7 · Layer 4

Capability services: protocols a peer offers

Layer 4 holds everything beyond the core. Each capability is a protocol with its own small specification, and peers advertise, discover, and use capabilities through the same advertisement machinery the core uses for everything else.

What is a capability service?#

A capability service, or capability, is any protocol beyond the core that a peer offers its group. The pattern has four parts. The provider publishes a CapabilityAdvertisement with a type URI, a version, a binding, parameters, cost hints, and a TTL. Consumers discover it through the ad-cache. The two sides bind through a space or a direct pipe. The capability's own mini-specification defines the interaction. Type URIs look like aspace:cap/vote, and a third party mints its own namespace, such as acme:cap/negotiate.

Shipped capabilityWhat it doesBinding
aspace:cap/aggregateFleet-wide sums, averages, counts, extremes, and quantiles by push-sumpipe
aspace:cap/voteCollective decisions by gossip majority or by quorum of signed ballotsspace
aspace:cap/ordered-logA Raft log that gives exactly-once takespipe
aspace:cap/gossip-learnDecentralized model averagingpipe
aspace:cap/semantic-discoveryFinding agents and assets by meaningpipe
aspace:cap/key-wrapSealed distribution of the group content keypipe
aspace:cap/data-queryQueries to connectors, answered as entriesspace
aspace:cap/asset-invokeOperations on a connector's assets, run once per requestspace
aspace:cap/rtc-signalWebRTC signalling for the webrtc transportpipe

Should a capability bind through a space or a pipe?#

A space-mediated capability exchanges requests and responses as leased entries in an agreed space, which gives it retries, an audit trail, visibility in the fleet console, and choreography with other capabilities at no extra cost. It is the right default for request and response. A pipe capability exchanges PIPE_DATA frames addressed to its type URI, which suits continuous protocols whose message rate would fill a space with entries nobody reads. A pipe-bound capability gives up the space's retries and audit trail, and it can publish results into a space on purpose to get them back. Both bindings see only authenticated, admitted peers.

What is the capability runtime, and what are its two clocks?#

Each group has a CapabilityRuntime that hosts that peer's providers. It drives two clocks and keeps them apart. The advertisement clock refreshes every hosted advertisement, on the order of minutes. The protocol clock calls each provider's tick() to run one round of its algorithm: a push-sum exchange, a gossip-learning offer, a Raft election-timer step. The runtime registers itself on the peer's tick, so registering a provider is enough to drive it, and the application supplies no scheduler of its own. A capability that has never completed a round refuses fleet-wide queries, because it holds only its own contribution.

What does aggregate do?#

The aggregate capability computes sum, avg, count, min, max, and quantile across the fleet by gossip, over values members report or over a field of the entries that match a template. Any member starts an epoch under an agreed id, and every participant converges in a number of rounds that grows with the logarithm of the fleet size, with no collector node. onEstimate and @OnEstimate fire when an epoch's estimate settles. The values carry no authentication, so any participant can skew an average; the specification accepts that cost and points trust-sensitive decisions to quorum voting.

AcmeEach summarizer reports its average model-call latency. coordinator reads the fleet-wide average and writes fewer tasks while it is high.

What does vote do?#

The vote capability supports collective decisions in two modes. MAJORITY_GOSSIP aggregates preferences by push-sum, which is cheap and approximate. QUORUM collects explicit ballots as signed entries and closes a proposal with a decision once a configured number of the electorate has voted. The electorate counts a ballot while its author's AgentCard is fresh, so the quorum tracks who is actually present, and an authorizer can narrow it further with the VOTE operation. The tally counts at the authorizer's granularity, one per peer or one per attested agent, so one member cannot multiply itself. Any member can recompute the tally from the space, and a decision can reopen if the group revokes a voter.

// coordinator: open one vote per new finding
@Propose(space = "findings", vote = "votes", prefix = "publish:", key = "topic",
         options = {"yes", "no"}, quorum = 2, lease = "2h")
public String ask(Finding f) { return "Publish the finding on " + f.topic() + "?"; }

// each reviewer: one signed ballot per proposal
@Ballot(space = "votes", prefix = "publish:")
public String judge(VoteCapability.Proposal p) { return review(p.question()) ? "yes" : "no"; }

// publisher: runs once per proposal, when the quorum closes
@OnDecision(space = "votes", prefix = "publish:", resultSpace = "findings")
public Published publish(VoteCapability.Decision d) {
    return "yes".equals(d.winner()) ? new Published(d.proposalId()) : null;
}
AcmeEvery new finding opens a proposal. Two of the three reviewers must vote, and publisher writes a Published entry once when they say yes. Auditors later read the ballots and recompute the tally.

What is the ordered log?#

The ordered log elects a Raft group among volunteering members and exposes an append-only log whose committed commands reach listeners in commit order. Its take coordinator backs the ORDERED strategy, and @OrderedTake is the worker annotation for it. A log has a fixed member set, and reconfiguring it means starting a new log. The leader's lease is an advertisement: each member's CapabilityAdvertisement carries its role and term, and the leader's adds leaseUntil, so consumers find the leader by reading advertisements. The authorizer's RAFT_VOTER operation decides who may vote. The log tolerates crashes, and it does not tolerate Byzantine members. Because the starter cannot infer a fixed member set, a deployment supplies the ordered-log provider as a bean.

@OrderedTake(space = "payments", lease = "30s")
public LicenseReceipt pay(LicenseOrder order) {
    vendor.pay(order.vendor(), order.amount(), order.orderId());   // idempotency key on the vendor side, too
    return new LicenseReceipt(order.orderId(), order.vendor(), "clerk");
}
Acmeledger-1, -2, and -3 form the log for payments, and each hosts one clerk. When the leader's machine dies, the other two elect a new leader, and the next order commits through it. The clerks confirm each order once.

What is gossip learning?#

The gossip-learn capability improves models without a central trainer. A model implements a mergeable model interface whose merge must be commutative, and the default averages weights element by element. Members exchange models by a token-passing offer and accept, in which both sides merge exactly the same pair, so concurrent exchanges conserve the fleet's total. Models travel content-addressed, and each epoch writes an Evaluation entry with its loss, so the learning stays auditable from a space.

AcmeThe summarizers train their auction bid policy together, so each learns how long each kind of topic really takes.

What is semantic discovery?#

Semantic discovery keeps an embedding index over the group's AgentCards, AssetCards, and capability advertisements, so a member can look up "who can summarize legal PDFs cheaply?" by meaning. An embedder interface lets a deployment choose its model, and the default hashing embedder works with no model at all. The advertisement names its embedder and dimensions, and a remote query goes only to peers that rank with the same embedder, so a fleet never silently mixes rankings.

Acmesummarizer asks "who holds Acme's past research reports?" and finds docs-connector's card for acme-archive.

What is key wrap?#

The key-wrap capability hands the group's content key to each member that may hold it. The requester sends its X25519 public key in a signed request, the holder checks the requester against its policy (the authorizer's KEY_HOLDER operation), and the holder answers with the key sealed by X25519, HKDF, and AES-256-GCM to that requester alone. Only the requester can open the reply, so the reply may travel any path, relays included. An agent with a certified encryption key of its own can receive the key for itself, and a sibling agent on the same peer learns nothing from it.

What are data-query and asset-invoke?#

They are how agents use a connector's assets. With data-query, an agent writes a typed query entry into an agreed space, and the connector writes result entries back, inline when they are small and content-addressed when they are bulk. A materializing provider pushes changes from its source into the space as AssetChange entries leased for the asset's freshness, so subscribers receive enterprise events as they happen. With asset-invoke, an agent writes an AssetInvocation, exactly one connector takes it under a lease, runs the operation, and writes the result, and a repeat of the same invocation id never runs twice. A connector runs only the operations its card lists.

Acmesummarizer writes a query for reports on agentic memory since 2024. docs-connector answers with a result whose large body travels as a block, and the task's finding cites it by CID.

How do I build a capability of my own?#

Mint a type URI and write its mini-specification. Implement CapabilityProvider (its type, the advertisement it describes, and, when it has rounds to run, tick()). Choose a space or a pipe binding. Register it with the group's capability runtime, or annotate the provider bean with @ProvidesCapability under the facade or the starter. A typed client factory registered through ServiceLoader lets agents receive a client by field with @CapabilityRef. Test it on a simulated network with a deterministic clock, as the project tests the shipped capabilities, and say in its mini-specification whether it authenticates its values.

AcmeAcme writes acme:cap/negotiate, in which buyer and vendor agents trade offer and counter-offer entries in a space until a vote closes the deal.
Part 8 · Programming model and hosts

Annotations, the binder, and the frameworks around the stack

The programming model sits beside the layers and uses all of them. It turns plain classes into agents, and the hosts bring the whole fabric up from configuration.

What are the binder and the facade?#

The binder, AgentBinder, turns annotated plain objects into leased worker loops, reactions, ballots, decision handlers, and exactly-once workers. It gives each agent its signing identity, publishes and refreshes its AgentCard, deduplicates deliveries, renews leases and subscriptions, and runs each reaction on a virtual thread. The facade, AgentSpaces, routes a bean into every group whose spaces satisfy it, registers the capabilities its annotations need, and resolves typed capability clients. Each binding fails at bind time, naming what is missing, when the capability or space it needs is absent.

What are @AgentSpec and @SpaceAgent?#

@AgentSpec on a class names the agent and gives its description and goals, which go onto its AgentCard. The binder also accepts any annotation that is itself annotated @AgentSpec, so frameworks can compose stereotypes. The Spring starter ships @SpaceAgent, which is both @Component and @AgentSpec, so a Spring agent needs one annotation on the class and one on each method.

Which annotation do I use for which job?#

Every binding annotation has the same shape: the method's parameter is the cue, and its return value is the next entry.

AnnotationWhat it doesAcme uses it for
@SpaceTakeA crash-tolerant worker: take the cue under a lease, complete it with the resultsummarizer working tasks
@SpaceNotifyChoreography: react to a matching write (or another event) without consuming itan indexer reacting to each Finding
@SpaceRefInject a space handle into a field for writes in mid-flightprogress markers during long summaries
@BidFunctionSupply the bid for an AUCTION spacecost bids on tasks-auction
@ProposeOpen a vote for each cuecoordinator asking whether to publish
@BallotCast one signed vote per proposalthe three reviewers
@OnDecisionRun once per proposal when its quorum closespublisher
@OrderedTakeAn exactly-once worker through the ordered logthe clerks on payments
@SpaceJoinA fan-in: fire once per key when every required part is presentmerging a finding with its fact-check
@SpaceReduceA persistent fold over a stream of elements per keya running bibliography per topic
@OnEstimateReact once when an aggregate epoch settlesthrottling on fleet latency
@CapabilityRefInject a typed capability client into a fielda VoteClient in coordinator
@ProvidesCapabilityRegister a bean as a capability providerthe ordered-log provider on the ledger peers

What can a bound method return?#

  • An entry, which the binder writes (for a take, atomically with the completion).
  • null, which writes nothing.
  • Tagged.of(entry, tags), which writes the entry with tags.
  • Entries.of(...), a fork, whose elements the binder dispatches one by one after a single completion.
  • A Motion, which opens a vote as the agent.
  • A Contribution, which feeds a push-sum aggregate epoch.

The annotations also accept tags and where filters, which the binder compiles onto the template so a filtered take never claims an entry it would not serve. A space attribute left empty resolves to the binder's only space, and durations read like Spring properties ("10m", "500ms").

What is choreography, and how does it differ from orchestration?#

In service choreography, each participant reacts to the entries it cares about and writes the entries the next participant needs, and no central orchestrator sequences them. A workflow then emerges from the entry types and the agents bound to them, and adding a step means binding one more agent. Workflow orchestration still has a place inside one agent, as when a planner sequences its own actions.

AcmeAcme's whole publishing flow is choreography: a ResearchTask becomes a Finding, the finding cues a proposal, the reviewers' ballots close a decision, and the decision cues a Published entry. No component knows the whole sequence.

What are remote actions?#

Remote actions turn other agents' AgentCards into actions this peer can call. The RemoteActions registry watches the ad-cache for foreign cards and exposes one action per declared consume-and-produce pair. Invoking one writes the input entry into the space the card names and waits for a result entry that shares field values with the request. Any qualified member may serve the request, so a crashed worker's job still finishes. The Embabel bridge generates a typed @Agent from these actions, so Embabel's planner plans across the whole fleet.

AcmeAn Embabel planner in coordinator sees summarizer's card as the action summarizer_ResearchTask and uses it inside multi-step plans.

Which hosts and integrations exist?#

Host or integrationWhat it brings
agentspaces-spring-boot-starterThe peer, groups, spaces, capabilities, and agents from agentspaces.* properties
agentspaces-micronautThe same properties and annotations for a Micronaut service
agentspaces-langchain4jFleetRuntime, a peer from the same configuration with no framework, and the fleet on LangChain4j's extension points
agentspaces-springaiFleet tools, advisors, chat memory in a space, crash-safe model workers, and model access as a fleet service
embabel-agentspacesEmbabel @Agent metadata as AgentCards, and the fleet's cards as planner actions
agentspaces-agentThe binder and facade on plain Java
Clojure, GroovyIdiomatic bindings over the Java libraries
Python, TypeScriptWire-compatible peers, including a Node service host and a browser member

What are the A2A gateway, the fleet console, and the connector SDK?#

The A2A gateway serves the fleet's AgentCards as A2A agent cards and binds the A2A task interface to a space: sending a message writes a task entry, and the task's state follows the entry (present is submitted, taken is working, completed is completed). The fleet console is a read-only peer with a web UI, a HAL+JSON API, and a Server-Sent Events activity stream, plus token-gated command and control with a signed audit log. The connector SDK builds data-provider peers that publish AssetCards and answer queries.

AcmeA partner's agent that speaks only A2A sends a research request to Acme's gateway, and the request becomes an ordinary ResearchTask for the summarizers.
Part 9 · Security, across the layers

Signatures, authorization, encryption, and revocation

Security in AgentSpaces runs through every layer. Layer 0 signs, Layer 1 admits, Layer 3 checks every state change, and one authorizer answers every privileged question. The interfaces are pluggable, so an organization brings its own identity provider, CA, and policy engine.

What does the fabric sign?#

Everything a receiver might act on. Each frame carries its sender's signature, unless an attested channel or session stands in for it. Each advertisement carries its issuer's signature. Each entry record carries its writer's signature, each change to an entry's state carries the signature of the party allowed to make that change, each take claim carries its holder's signature, and each ballot, credential, and revocation carries its author's. The signatures inside frame bodies verify end to end, whatever path the frame took.

What is an authenticated state transition?#

An entry's record signature covers only its immutable identity, so the fabric also signs the mutable state that replication carries: the completion flag, the add and remove sets, and the lease. The transition implies who may sign it: the holder of a valid take claim signs a completion, and the entry's issuer signs a write, a renewal, or a cancellation. A replica drops any delta whose state the right party did not sign, so no member or relay can forge a completion, a removal, or a lease that would make a signed entry vanish.

AcmeA compromised member replays one of summarizer's findings with the completion flag set. Every replica drops the delta, because summarizer never signed that state.

What is the authorizer?#

Membership decides who is inside the perimeter, and the authorizer decides what a member may do. Every privileged decision is one question, permits(peer or agent, operation, scope), over nine operations: RAFT_VOTER, DIRECTIVE_ISSUER, CONNECTOR_SERVE, KEY_HOLDER, SPACE_WRITE, SPACE_TAKE, VOTE, MODEL_SERVE, and KEY_ROTATE. The membership authorizer permits every admitted member unless the deployment lists grants for an operation, by PeerID or by AgentID. The OIDC authorizer reads permissions from identity-provider tokens: a JWT bound to one PeerID, carrying scopes such as aspace:space-write:tasks, which the peer publishes in its signed self-advertisement. KEY_ROTATE permits nobody without an explicit grant.

AcmeAcme grants RAFT_VOTER to the three ledger peers only, so no other member can vote in, lead, or submit to the payments log.

What are the security profiles?#

ProfileThe posture it selects
dev-localLocal development: membership authorizer, session attestation on plain TCP
mtlsThe default: TLS with identity-endorsed channel certificates, membership authorizer with optional grants
mtls-oidcThe same channels, with the OIDC authorizer answering from identity-provider tokens
zero-trustThe OIDC authorizer, and a full signature on every hop
Acmeresearch-fleet runs mtls, the default. When Acme wants its identity provider to decide who may vote in the payments log, it moves every peer of the fleet to mtls-oidc and issues the ledger peers tokens with the aspace:raft-voter scope.

What is a group content key?#

A group may encrypt entry payloads with a symmetric content key: AES-256-GCM with a fresh nonce per encryption, bound to the entry by its space and entry ids. Writers encrypt before they sign, so a member without the key still verifies every signature, stores every record, and forwards every delta, and reads no payload. Key possession is the read perimeter, and group membership stays the write perimeter. Keys form a ring of numbered epochs: the founder or a holder of the KEY_ROTATE grant mints the next epoch with a signed proof, and writers move to it after its cutover. A group must rotate on time, because random nonces bound one key to roughly 232 encryptions across the whole fleet. Type names and tags stay readable so matching and sharding keep working.

Acmeresearch-fleet sets a content key. seed-b, the relay, holds no key: it stores and forwards Acme's findings and cannot read them.

How do members enforce a revocation?#

A member never again admits a revoked peer, never forwards its self-advertisement, purges its advertisements from discovery, and refuses any new state or claim whose actor is revoked. Replicas keep what they already hold, so revocation never deletes admitted work. For revoked agents, agent keys, channel certificates, and join credentials, a freeze rule applies. For the reason key-compromise, members refuse every newly arriving signature by the revoked key, whatever signing time it claims, because a stolen key can back-date. For other reasons, they refuse only signatures made at or after the revocation's effective time, so a late joiner still receives the agent's history. Each group's authorizer refuses what the group has revoked before it answers anything else.

AcmeA thief takes an engineer's laptop that ran an agent in partner-fleet. Partner Inc's founder revokes that agent's key with reason key-compromise, and every member refuses anything new the key signs from then on.

How does the fabric limit abuse?#

Per-issuer rate limits, strikes, and local quarantine bound a misbehaving member. A bounded-drift clock keeps a received stamp from pulling a node's clock more than ten minutes ahead, which also bounds how far a take claim can be back-dated. Deduplication by stream and payload hash stops replays and stops an attacker from suppressing an honest item. Large payloads must move to content addressing, caches bound their occupancy, and a receiver drops frames of any other wire version before it verifies them.

Which risks does AgentSpaces accept?#

The specification names them so deployments can plan around them:

  • A lying bidder in an AUCTION space can win work it never performs.
  • An eclipse attack on bootstrap can isolate a newcomer; several seed sources mitigate it.
  • Aggregate and gossip-learning values carry no authentication, so a participant can skew them; trust-sensitive decisions belong to quorum votes.
  • Under a content key, entry type names and tags stay readable to members without the key.
  • A stolen agent key can sign records back-dated into an old certificate window until someone revokes it with key-compromise.
  • A member admitted under an invite key stays admitted after the invite expires, until the founder revokes the credential or the delegation.
Part 10 · The wire and conformance

Bytes, clocks, and the proof that languages agree

The protocol uses standard formats throughout (CBOR, Ed25519, SHA-256, and URIs) with nothing specific to Java on the wire. TECH-SPEC.md gives every structure byte by byte.

What travels on the wire?#

Every message is a CBOR (RFC 8949) frame: a signed wrapper {envelope, senderPublicKey?, signature?} around an envelope {ver, group, kind, from, to?, stamp, body}. The envelope names the wire version, the group, the message kind, the sender's PeerID, the recipient of an addressed frame, a hybrid-logical-clock stamp, and a kind-specific body. Stream transports prefix each frame with its length, and a frame is at most 8 MiB.

Which message kinds exist?#

KindsPurpose
PING, PING_REQ, ACKMembership probes
RUMOROne gossip item on a named stream
DIGEST, PULL_RESPAnti-entropy
QUERY, QUERY_HITScoped discovery queries
BLOCK_WANT, BLOCKContent-addressed payloads
PIPE_DATADirect capability frames
RELAY_FRAMEA signed frame a relay forwards verbatim
GROUP_AD_WANT, GROUP_ADFetching a signed founding to join by id
CHANNEL_HELLO, SESSION_HELLOChannel and session attestation
BATCH, HAVE, GRAFT, PRUNEBatching and lazy push, sent only to peers that advertise the matching hint

What is canonical CBOR, and why does it matter?#

Every signature covers canonical bytes, so two implementations must encode a structure identically. Canonical CBOR here means record fields in declared order, every map's entries sorted by key in RFC 8949 §4.2.1 order, and definite-length arrays. Decoders ignore unknown fields, so appending a field to a structure is compatible, and removing or reordering one is a breaking change.

What is the wire version, and what are wire hints?#

The wire version is 3. A receiver drops a frame of any other version before it verifies the signature, counts the drop, and never penalizes the sender, so a future version can coexist with this one at the cost of mutual silence. Wire hints in a PeerAdvertisement (wire.batch, wire.hashes, wire.tree, wire.session) tell other members which newer message kinds a peer understands, and members send those kinds only to peers that advertise them. A fleet with one older member therefore keeps every byte that member sees.

What is a hybrid logical clock?#

A hybrid logical clock (HLC, after Kulkarni and colleagues) stamps every item with physical milliseconds, a logical counter, and the node's id, written physical:logical:node. The stamps form a total order close to wall time in constant space, which is what makes lease-race arbitration deterministic across the fleet. A node clamps any remote stamp to its own wall time plus ten minutes, so a forged far-future stamp cannot poison its clock.

What are golden vectors, and what does conformance mean?#

The golden vectors in agentspaces-spec/golden.json are named byte strings and values that every implementation must reproduce exactly, from a fixed private key through peer ids, frames, advertisements, records, claims, certificates, and ballots. Hostile vectors (adv_*) are inputs every implementation must refuse identically without crashing. The Java, Python, and TypeScript suites each check a vendored copy of the file. A conforming minimal implementation covers Layers 0 through 3 on one LAN with the default conflict strategy, and TECH-SPEC §10 is the checklist a new client follows.

AcmeA Partner Inc engineer writes a Rust client for partner-fleet. They start from that checklist and check their encoder against the vectors, so they know the client's bytes match Java's before it ever dials a member.
Reference

Terms at a glance

Every term this FAQ defines, with the layer it belongs to. Each name links to its full answer.

TermLayerWhat it is
AgentSpacesconceptA peer-to-peer coordination fabric for agents, services, and people
Tuple space, AgentSpaceconceptA shared associative memory with write, read, and take; a space
Lease (principle)conceptEvery piece of shared state carries a time to live and vanishes unless renewed
Weakest sufficient primitiveconceptUse the cheapest mechanism that meets the need; consensus only by opt-in
Layers 0 to 4conceptIdentity, peering, discovery, the space, capability services
PeerIDL0multibase(sha-256(Ed25519 public key)); a peer's stable identity
KeystoreL0Where a peer keeps its keys, so its PeerID survives restarts
AgentIDL0A PeerID plus a local name: <peerId>/<name>
AgentCertificate, subordinate keyL0A peer-certified key of an agent's own
PEER_ASSERTED, AGENT_ATTESTEDL0Whether the peer vouched for an entry or the agent's own key signed it
Self-certifying idL0An id that is the hash of the document that defines it
PeerL1One running AgentSpaces process with its own key
Group, group idL1The unit of scope: policy, gossip domain, namespace; aspace://...
Founding textL1A string every member turns into the same group id by itself
Signed founding, founding documentL1Founder-signed founding fields whose hash is the GroupID
GroupAdvertisementL1The signed description of a group
Membership policyL1OPEN, INVITE, or POLICY, enforced at admission
AdmissionL1The moment a member decides whether a newcomer enters its view
Invite credential, invite key, delegationL1Founder-rooted proof that a peer may join an INVITE group
ViewL1The members a peer currently knows
Member TTL, SWIML1Leased liveness and probe-based failure detection with local suspicion
Gossip, rumor, anti-entropyL1Push new items fast; reconcile digests to make delivery certain
Fan-out, hop budgetL1How many members each hop pushes to (3), and how many hops an item gets (6)
StreamL1A named channel on the gossip bus, such as space:tasks
Lazy pushL1Eager push along a self-pruning tree, with HAVE and GRAFT repair
Tick, peer samplerL1The peer's one clock; random partners drawn from the view
RendezvousL1A role with a larger ad-cache that answers discovery queries
RelayL1A role that forwards frames for peers nobody can dial
TransportL1A binding that carries frames: mem, tcp, tls, quic, dtls, udp, ws, http, webrtc
Endpoint, bind, advertiseL1Advertised (transport, address, priority); where a peer listens versus where others dial
Channel attestationL1A handshake that binds a connection to a PeerID, so frames can skip signatures
Required attestationL1Refuse every frame on an unattested connection
Session attestationL1One signed hello each way, then an HMAC per frame
BootstrapL1 joinFinding the first address to dial
Seed, name expansionL1 joinAn address a newcomer dials first; one seed per address a name resolves to
Locator, hint, evidenceL1 joinOne way of finding where to dial, and what it answers
Network domainL1 joinThe host's DNS domain, where DNS-SD and TXT lookups happen
Chain, first-winsL1 joinOne group's ordered locators, asked together or one at a time
BeaconL1 joinA member at a stable address that newcomers dial first
Beacon documentL1 joinSigned JSON at /.well-known/agentspaces/beacon.json
Multicast beacon, sealed beaconL1 joinAn opt-in LAN datagram, optionally encrypted under the content key
beacon-peer, accept-group-id-fromL1 joinPin a document's signer; name who may claim a group id
HostL1 joinThe framework that creates the peer and builds its chains
AdvertisementL2A signed, typed document with a time to live
TTLL2How long caches keep an advertisement; freshness is liveness
AgentCardL2What an agent does, consumes, produces, and where
Space binding, card actionL2Which space an input comes from; one declared action per method
AssetCard, connectorL2A data provider's description of one asset; the peer that serves it
Ad-cacheL2A peer's verified, TTL-evicting cache of advertisements per group
find, remoteFindL2Local-first discovery, escalating to rendezvous peers and gossip
RevocationAdvertisement, CredentialRevocationL2Permanent withdrawals of an identity or of something certified
SpaceL3A typed, replicated tuple space inside a group
Entry, EntryRecordL3A typed record in a space, and its signed wrapper
write, read, take, complete, notifyL3The space operations
TemplateL3A type plus field and tag conditions
Write lease, take leaseL3An entry's lifetime; a taker's claim that lapses back to the space
Replicated workerL3Workers take tasks under leases; a crashed worker's task reappears
EventsL3WRITTEN, TAKEN, COMPLETED, EXPIRED, REAPPEARED
Delta-CRDT, tombstoneL3Conflict-free replication; a completed entry's marker until collected
Conflict strategyL3How a space decides which taker wins: LEASE_RACE, AUCTION, ORDERED
Lease race, settle windowL3Claim, wait, lowest stamp wins; at most one completion
Take claim, epochL3A signed claim; claims merge by epoch, bid, stamp, and expiry
Auction, @BidFunctionL3Takes as bids; the space converges on least-cost assignment
ORDEREDL3Exactly-once takes through the ordered log
Content addressing, CIDL3Payloads over 64 KiB move by hash through the block exchange
ConsistencyHint.FRESHL3One anti-entropy pull before a read
Tags, tag shardingL3Readable labels on entries; replicas that hold only a slice
Space admissionL3GROUP, ALLOWLIST, CREDENTIAL, or AUTHORIZER
View (of a space)L3One replica seen as another agent of the same peer
Founder lease, read-onlyL3A space closes for writes when its founder stops renewing
Capability serviceL4A protocol beyond the core, advertised and discovered
Type URIL4A capability's name, such as aspace:cap/vote
Space-mediated, pipeL4Bind through entries in a space, or through direct frames
Capability runtimeL4Hosts providers; drives the advertisement and protocol clocks
Aggregate, push-sum, epochL4Fleet-wide sums and averages by gossip
Vote, proposal, ballot, decision, electorateL4Collective decisions by gossip majority or signed quorum
Ordered log, Raft, take coordinatorL4A fixed-membership Raft log that backs exactly-once takes
Gossip learning, mergeable modelL4Decentralized model averaging with a commutative merge
Semantic discovery, embedderL4Finding cards by meaning through an embedding index
Key wrapL4Sealed distribution of the content key to permitted members
Data-query, asset-invoke, materializing providerL4How agents query and operate a connector's assets
Binder, facademodelTurn annotated objects into agents; route them into groups
@AgentSpec, @SpaceAgentmodelName an agent; the Spring stereotype that also makes it a component
Cue and next entrymodelA method's parameter starts it; its return value is written next
Tagged, Entries, Motion, ContributionmodelSpecial return values: tags, a fork, a vote, an aggregate share
Service choreographymodelAgents react to entries and write the next ones, with no orchestrator
Remote actionsmodelForeign AgentCards as invokable, plannable actions
A2A gateway, fleet console, connector SDKmodelBridges and tools around the fleet
Authenticated state transitionsecurityA signature on every change to an entry's mutable state
Authorizer, operations, grantssecuritypermits(peer or agent, operation, scope)
Security profilesecuritydev-local, mtls, mtls-oidc, zero-trust
Content key, epoch, rotationsecurityPayload encryption with numbered, signed key epochs
Freeze rulesecurityKeep what a replica holds; refuse new signatures by reason and time
Frame, envelopewireThe signed wrapper and the routed message inside it
Canonical CBORwireThe one encoding every signature covers
Wire version, wire hintswireVersion 3; hints that unlock newer kinds per peer
Hybrid logical clockwirephysical:logical:node stamps with a ten-minute drift clamp
Golden vectors, conformancewireByte strings every implementation reproduces or refuses alike

No question mentions that. Try a shorter word, or browse the contents.