Gossiping Agents Protocol

Formal protocol specification for gossip-native AI agent coordination. Context, coordination, commerce, and collective intelligence over peer-to-peer networks.

View on GitHub

1. Introduction

1.1 Purpose

Hyperspace is a peer-to-peer Gossiping Agents Protocol for AI agents that unifies context, coordination, commerce, and collective intelligence. Unlike point-to-point protocols (MCP, A2A, MPP), Hyperspace creates a gossip mesh where every capability — tool discovery, task routing, payments, and execution learnings — propagates via pub/sub dissemination.

Where existing protocols assume a client connecting to a known server, Hyperspace assumes a mesh of autonomous agents discovering each other, sharing work, and collectively improving through gossip-propagated execution traces.

1.2 Scope

Hyperspace is a universal agent protocol that unifies existing protocols. Each layer subsumes an existing protocol while adding gossip-native capabilities:

Layer Subsumes Hyperspace Difference
Context MCP Tool and data discovery via DHT, not fixed server URLs
Coordination A2A Task routing via reputation-ranked gossip, not addressed endpoints
Commerce MPP P2P value settlement, no intermediary required
Collective Intelligence Agents learn deterministically from each other's execution traces

1.3 Design Principles

  1. Gossip-Native — All state propagates via GossipSub pub/sub
  2. Non-Blocking — Async; agents continue if peers are unavailable
  3. Graceful Degradation — Features fail safely with sensible defaults
  4. Protocol-Agnostic — Works with any agent framework or LLM
  5. Privacy-First — Built-in PII redaction and Ed25519 signed envelopes
  6. Extensible — New primitives added without breaking existing implementations

1.4 Terminology

Term Definition
Peer A node in the Hyperspace gossip mesh
Session Logical container for agent execution
Primitive One of eight protocol-defined capability interfaces (State, Guard, Tool, Memory, Recursive, Learning, Self-Improving, Micropayments)
Trajectory A recorded execution path for learning
Playbook Collection of learned context bullets
Bullet Single piece of learned knowledge with helpful/harmful counters
Gossip Topic A GossipSub channel for a specific data type

2. Transport Layer

2.1 GossipSub Transport (P2P)

Hyperspace uses libp2p GossipSub as the primary transport for peer-to-peer communication. All messages are wrapped in signed envelopes with domain-separated Ed25519 signatures.

Gossip Topics

hyperspace/capabilities/{peerId}      -- Tool and agent capability announcements
hyperspace/tasks/{taskType}           -- Task requests and routing
hyperspace/trajectories/{taskType}    -- Execution traces for learning
hyperspace/reputation/{peerId}        -- Reputation updates
hyperspace/crdt/sync/memory           -- Distributed memory synchronization
hyperspace/settlements/{round}        -- Payment receipt gossip

Signed Envelopes (v2)

Every gossip message is wrapped in a v2 signed envelope. The signing material uses domain separation per topic to prevent cross-topic replay attacks.

interface SignedEnvelope { _v: 2; ts: number; // Unix timestamp nonce: string; // Replay prevention from: string; // PeerId pk: string; // Ed25519 public key sig: string; // Ed25519 signature d: any; // Payload data }

Signing material: SHA256(ts_8BE || nonce || from || SHA256(d_json))

Domain separation: the signature is namespaced per topic. A message signed for hyperspace/tasks/web-research cannot be replayed on hyperspace/reputation/12D3Koo....

2.2 JSON-RPC 2.0 Transport (Client-Server)

For SDK clients connecting to a local or remote Hyperspace node, the protocol exposes a JSON-RPC 2.0 interface over WebSocket.

Connection URL

ws://{host}:{port}     // Local
wss://{host}:{port}    // TLS

Default port: 3100

Request Format

interface JSONRPCRequest { jsonrpc: "2.0"; method: string; // Format: "{primitive}.{method}" params?: object; id: string | number; }

Response Format

interface JSONRPCResponse { jsonrpc: "2.0"; result?: any; error?: { code: number; message: string; data?: any }; id: string | number; }

2.3 Authentication

Three tiers of authentication, each suited to a different context:

  1. Ed25519 peer identity — P2P transport; cryptographic, no central authority
  2. API key — SDK client connecting to a local node
  3. Session token — Temporary, scoped to session lifetime

2.4 Discovery (DHT)

Kademlia DHT provides decentralized peer and capability discovery:

  • Agents publish capability cards to DHT
  • Capability cards include: peerId, tools[], taskTypes[], reputation, geo, latency
  • Lookup: O(log N) hops
  • No central registry required

3. Protocol Messages

Method naming follows the convention {primitive}.{action}. Each primitive maps to a protocol layer:

Primitive Prefix Layer
State state.* Context
Guard guard.* Commerce
Tool tool.* Context
Memory memory.* Context
Recursive recursive.* Coordination
Learning learning.* Intelligence
Self-Improving improving.* Intelligence
Micropayments micropayments.* Commerce

4. Core Primitives

4.1 State Primitive

Session lifecycle management, state persistence, and episode recording for reinforcement learning patterns.

Methods

state.createSession(agentName?, agentType?, peerId?, model?, metadata?) → { sessionId, createdAt }
state.getSession(sessionId) → SessionInfo
state.setState(sessionId, key, value) → { updated: boolean }
state.getState(sessionId, key) → { value: any }
state.endSession(sessionId) → { ended: boolean, duration: number }
state.recordEpisode(sessionId, outcome, reward) → { episodeId }

state.createSession

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "state.createSession",
  "params": {
    "agentName": "web-researcher",
    "agentType": "autonomous",
    "model": "gemma-3-27b",
    "metadata": { "task": "market-analysis" }
  },
  "id": 1
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "createdAt": "2026-03-18T12:00:00.000Z"
  },
  "id": 1
}

state.recordEpisode

Records an episode for reinforcement learning patterns. The reward field accepts values from -1.0 (worst) to 1.0 (best).

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "state.recordEpisode",
  "params": {
    "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "outcome": "success",
    "reward": 0.85
  },
  "id": 2
}

4.2 Guard Primitive

Validation, safety checks, budget management, and rate limiting. The guard primitive protects sessions from overspending and unsafe content.

Methods

guard.validate(data, schema) → { valid, errors? }
guard.checkSafety(content, policy?) → { safe, flags? }
guard.checkBudget(sessionId, estimatedCost) → { allowed, remaining, consumed, limit }
guard.consumeBudget(sessionId, amount, description?) → { remaining }
guard.checkRateLimit(key, limit, window) → { allowed, remaining, resetAt }
guard.getBudgetStatus(sessionId) → { remaining, consumed, limit }

guard.checkBudget

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "guard.checkBudget",
  "params": {
    "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "estimatedCost": 0.02
  },
  "id": 3
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "allowed": true,
    "remaining": 0.98,
    "consumed": 0.02,
    "limit": 1.00
  },
  "id": 3
}

4.3 Tool Primitive

Tool discovery via DHT, execution tracking with analytics. Unlike MCP, tools are not bound to a fixed server URL — they are discovered dynamically from the gossip mesh based on capability, reputation, latency, and geography.

Methods

tool.discover(query, capabilities?, minReputation?, maxLatency?, geo?) → { tools[] }
tool.register(name, description, schema, capabilities) → { toolId }
tool.invoke(toolId, params, sessionId?) → { result, duration, peerId }
tool.getAnalytics(toolId) → { invocations, avgLatency, successRate }
tool.listRegistered() → { tools[] }

tool.discover

Searches the DHT for tools matching the query. Results are ranked by reputation, filtered by latency and geography preferences.

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "tool.discover",
  "params": {
    "query": "web search",
    "capabilities": ["search", "scrape"],
    "minReputation": 0.7,
    "maxLatency": 500,
    "geo": "us-east"
  },
  "id": 4
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "tools": [
      {
        "id": "tool-8f3a2b",
        "name": "web-search",
        "peerId": "12D3KooWRx434ACwmJz...",
        "description": "Full-text web search with snippet extraction",
        "capabilities": ["search", "scrape", "summarize"],
        "reputation": 0.94,
        "avgLatency": 230,
        "schema": {
          "input": { "type": "object", "properties": { "query": { "type": "string" } } },
          "output": { "type": "object", "properties": { "results": { "type": "array" } } }
        }
      }
    ]
  },
  "id": 4
}

4.4 Memory Primitive

Distributed infinite context via ConsistentHashRing. Memories are vector-embedded and replicated across the mesh for fault tolerance and low-latency semantic search.

Architecture

  • 750 virtual nodes across physical peers
  • 3x replication (primary + 2 replicas)
  • SHA-256 hash routing
  • O(log V) lookup complexity
  • 50–100ms writes, 100–200ms semantic search

Methods

memory.store(content, sessionId?, metadata?, tier?) → { id, peerId, replicas }
memory.search(query, sessionId?, limit?, threshold?, tier?) → { memories[], searchTime }
memory.get(id) → { content, metadata, peerId }
memory.list(sessionId, limit?, offset?) → { memories[], total }
memory.delete(id) → { deleted: boolean }
memory.archive(id) → { archived: boolean, tier: "archival" }

memory.search

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "memory.search",
  "params": {
    "query": "error handling patterns for rate-limited APIs",
    "limit": 5,
    "threshold": 0.75,
    "tier": "working"
  },
  "id": 5
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "memories": [
      {
        "id": "mem-f29c1a",
        "content": "Exponential backoff with jitter prevents thundering herd on 429 responses. Base delay 1s, max 60s, jitter +/- 25%.",
        "similarity": 0.91,
        "metadata": { "source": "web-research-session", "tags": ["api", "resilience"] },
        "peerId": "12D3KooWMKD2wrmHi...",
        "createdAt": "2026-03-17T08:30:00.000Z"
      }
    ],
    "searchTime": 142
  },
  "id": 5
}

4.5 Recursive Primitive

Loop detection, circular dependency prevention, and convergence checking. Protects multi-agent workflows from infinite loops and runaway recursion.

Methods

recursive.analyze(sessionId, currentStep, callStack, maxIterations?) → { isLooping, pattern?, recommendation }
recursive.track(sessionId, step, depth) → { tracked: boolean, depth }
recursive.getTrace(sessionId) → { steps[], maxDepth, totalIterations }
recursive.setMaxDepth(sessionId, maxDepth) → { updated: boolean }

recursive.analyze

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "recursive.analyze",
  "params": {
    "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "currentStep": "refine-search-query",
    "callStack": [
      "plan-research",
      "web-search",
      "analyze-results",
      "refine-search-query",
      "web-search",
      "analyze-results",
      "refine-search-query"
    ],
    "maxIterations": 10
  },
  "id": 6
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "isLooping": true,
    "pattern": "refine-search-query -> web-search -> analyze-results",
    "iterations": 3,
    "depth": 7,
    "recommendation": "warn"
  },
  "id": 6
}

5. Learning Primitives

5.1 Learning Primitive

Context evolution via the Generator/Reflector/Curator pattern. Agents learn from their own executions by reflecting on outcomes and curating a playbook of high-quality context bullets.

Concepts

  • ContextBullet — Single piece of learned knowledge with helpful/harmful counters
  • Playbook — Collection of bullets, versioned, with token budget
  • Sections — Strategy (str), Calculation (cal), Mistake (mis), Feedback (fbk)
  • Training modes — Offline, Online, Eval-only

Methods

learning.getPlaybook(playbookId) → { bullets[], version, tokenCount }
learning.reflect(playbookId, execution) → { newBullets[], prunedBullets[], playbookVersion }
learning.curate(playbookId, maxTokens?) → { removed[], remaining, tokenCount }
learning.addBullet(playbookId, section, content) → { bulletId }
learning.feedback(playbookId, bulletId, helpful) → { helpfulCount, harmfulCount }
learning.getStats(playbookId) → { totalBullets, bySection, avgScore, version }

learning.reflect

After an execution completes, the agent reflects on the outcome to generate new context bullets and prune ineffective ones.

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "learning.reflect",
  "params": {
    "playbookId": "web-research-v3",
    "execution": {
      "input": { "query": "quantum computing market size 2026" },
      "output": { "summary": "...", "sources": 12 },
      "steps": [
        { "action": "search", "tool": "web-search", "duration": 340 },
        { "action": "filter", "tool": "relevance-scorer", "duration": 120 },
        { "action": "synthesize", "tool": "summarizer", "duration": 890 }
      ],
      "outcome": "success",
      "reward": 0.92
    }
  },
  "id": 7
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "newBullets": [
      {
        "id": "str-00042",
        "section": "str",
        "content": "For market-size queries, prioritize analyst reports and industry databases over news articles. Filter by publication date within 6 months."
      }
    ],
    "prunedBullets": ["mis-00018"],
    "playbookVersion": 47
  },
  "id": 7
}

5.2 Self-Improving Primitive

Trajectory gossip and collective learning across the mesh. When an agent completes a task, its execution trajectory is gossiped to peers who curate it into their local libraries for in-context learning.

Based on three research papers:

  1. arXiv:2505.00234 — Experience library, trajectory curation
  2. arXiv:2502.04780 — SiriuS: Three-stage augmentation pipeline
  3. arXiv:2511.16043 — Agent0: Dual-agent co-evolution, ADPO

Concepts

Concept Values
TrajectoryState PENDING | SUCCESS | FAILED | AUGMENTED
CurationStrategy ACCUMULATE | DATABASE_LEVEL | EXEMPLAR_LEVEL | HYBRID
AugmentationMode NONE | FEEDBACK_ONLY | FULL_PIPELINE
TaskDifficulty TOO_EASY (p̂>0.8) | FRONTIER (0.3≤p̂≤0.8) | TOO_HARD (p̂<0.3)

Methods

improving.recordTrajectory(taskType, input, output, steps[], reward, metadata?) → { trajectoryId, state, gossipedTo }
improving.getExemplars(taskType, limit?, strategy?, minReward?) → { exemplars[], librarySize, avgReward }
improving.curate(taskType, strategy?) → { kept, pruned, librarySize }
improving.augment(trajectoryId, mode?) → { augmented, newState }
improving.assessDifficulty(taskType, input, samples?) → { difficulty, passRate, recommendation }
improving.getLibraryStats(taskType?) → { total, byState, avgReward, topContributors[] }

improving.recordTrajectory

Records an execution trajectory and automatically gossips it to subscribed peers on the hyperspace/trajectories/{taskType} topic.

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "improving.recordTrajectory",
  "params": {
    "taskType": "web-research",
    "input": { "query": "latest breakthroughs in solid-state batteries" },
    "output": { "summary": "...", "confidence": 0.88 },
    "steps": [
      { "action": "search", "tool": "web-search", "params": { "q": "solid-state batteries 2026" }, "result": { "count": 47 }, "duration": 310 },
      { "action": "filter", "tool": "relevance-scorer", "params": { "threshold": 0.7 }, "result": { "kept": 12 }, "duration": 85 },
      { "action": "extract", "tool": "content-extractor", "params": { "urls": 12 }, "result": { "extracted": 11 }, "duration": 2400 },
      { "action": "synthesize", "tool": "summarizer", "result": { "tokens": 1200 }, "duration": 940 }
    ],
    "reward": 0.88,
    "metadata": { "model": "gemma-3-27b", "totalDuration": 3735 }
  },
  "id": 8
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "trajectoryId": "traj-7e2f9a1b",
    "state": "SUCCESS",
    "gossipedTo": 14
  },
  "id": 8
}

improving.getExemplars

Retrieves curated trajectories for in-context learning. Exemplars are selected based on utility score, diversity, and minimum reward threshold.

RequestJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "method": "improving.getExemplars",
  "params": {
    "taskType": "web-research",
    "limit": 3,
    "strategy": "EXEMPLAR_LEVEL",
    "minReward": 0.7
  },
  "id": 9
}
ResponseJSON-RPC 2.0
{
  "jsonrpc": "2.0",
  "result": {
    "exemplars": [
      {
        "trajectoryId": "traj-7e2f9a1b",
        "input": { "query": "latest breakthroughs in solid-state batteries" },
        "output": { "summary": "...", "confidence": 0.88 },
        "steps": [
          { "action": "search", "tool": "web-search", "duration": 310 },
          { "action": "filter", "tool": "relevance-scorer", "duration": 85 },
          { "action": "extract", "tool": "content-extractor", "duration": 2400 },
          { "action": "synthesize", "tool": "summarizer", "duration": 940 }
        ],
        "reward": 0.88,
        "utilityScore": 0.91,
        "usageCount": 7,
        "peerId": "12D3KooWG1AnmPaU7M1d..."
      }
    ],
    "librarySize": 234,
    "avgReward": 0.72
  },
  "id": 9
}

6. Micropayments Primitive

The micropayments primitive enables peer-to-peer value settlement between agents. It implements an HTTP 402-based challenge-response flow with EIP-712 typed signatures and streaming payment channels for per-token billing. No intermediary required.

6.1 Concepts

  • PayChallenge: Server responds with 402 + pricing info (points, USDC, accepted chains)
  • PayCredential: Client signs an EIP-712 receipt and retries with X-Payment header
  • PayChannel: Persistent stream for per-token micropayments with nonce-based ordering

6.2 Methods

micropayments.challenge(pricePoints, priceUsdc, payeeAddress) → PayChallenge
micropayments.verify(credential) → { accepted, receiptId, amount }
micropayments.channel.open(payee, budget, currency) → PayChannelState
micropayments.channel.pay(channelId, amount, memo) → { nonce, remaining }
micropayments.channel.close(channelId) → { totalSpent, refund }

6.3 HTTP 402 Flow

Client                                  Server
  |                                       |
  |──── GET /inference ──────────────────▶|
  |◀─── 402 + X-Payment-Required ────────|  (PayChallenge as base64 JSON)
  |                                       |
  |  [sign EIP-712 receipt with wallet]   |
  |                                       |
  |──── GET /inference + X-Payment ──────▶|  (PayCredential as base64 JSON)
  |     [verify signature, check replay]  |
  |◀─── 200 OK + response ──────────────|
  |                                       |

6.4 Streaming Channel

// Open channel with budget
const channel = await hyperspace.micropayments.channel.open({
  payee: agentPeerId,
  budget: 5.0,
  currency: 'USDC'
})

// Pay per token generated
await channel.pay(0.003, '42 tokens')  // nonce: 1
await channel.pay(0.003, '42 tokens')  // nonce: 2

// Close — settle total, refund remainder
const receipt = await channel.close()
// { totalSpent: 0.006, refund: 4.994 }

7. Gossip Semantics

7.1 Topic Structure

All gossip topics follow the format: hyperspace/{dataType}/{scope}

The dataType identifies the kind of data being propagated. The scope narrows the audience — a peerId, taskType, or round number.

7.2 Message Propagation

GossipSub ensures messages reach all subscribed peers via a mesh overlay:

  1. Publisher sends to mesh peers
  2. Each peer validates the signed envelope
  3. Valid messages forwarded to their mesh peers
  4. Duplicate messages dropped (nonce-based dedup)
  5. Convergence: all peers receive within O(log N) hops
Publisher Mesh Layer Subscribers ========= ========== =========== Agent A ----publish----> [ GossipSub Mesh ] | | validate sig validate sig | | Peer X Peer Y ---forward---> Peer Z | | forward validate sig | | Peer W drop if duplicate

7.3 Trajectory Gossip Flow

When an agent completes a task, its execution trajectory propagates through the mesh. Each receiving peer independently decides how to use it:

Agent A completes task | v Publish to hyperspace/trajectories/web-research | +-------> Agent B receives -> curates into local library | +-------> Agent C receives -> filters (frontier tasks only) | +-------> Agent D receives -> augments via feedback pipeline | +-------> All agents' next runs benefit from shared knowledge

7.4 Capability Gossip

Agents periodically heartbeat their capability cards to maintain presence in the mesh:

  • Interval: 30 seconds
  • Delta-only: CRDT-based, only changes propagated
  • TTL: 5 minutes (capabilities expire if no heartbeat)

8. Error Codes

Hyperspace uses standard JSON-RPC 2.0 error codes for protocol-level errors and reserves the -32001 through -32099 range for application-specific errors.

Code Name Description
-32700 Parse Error Invalid JSON
-32600 Invalid Request Missing required fields
-32601 Method Not Found Unknown primitive method
-32602 Invalid Params Wrong parameter types
-32001 Session Not Found Invalid session ID
-32002 Budget Exceeded Operation would exceed budget
-32003 Rate Limited Too many requests
-32004 Safety Violation Content policy violation
-32005 Loop Detected Recursive loop detected
-32006 Peer Unavailable Target peer not reachable
-32007 Replication Failed Memory write didn't meet replication factor
-32008 Trajectory Rejected Trajectory failed validation

9. Security Considerations

9.1 Identity

  • Ed25519 key pairs for all peers
  • Stable peer IDs derived from key material
  • No central certificate authority

9.2 Envelope Verification

  • All gossip messages signed with Ed25519
  • Domain-separated signatures per topic
  • Timestamp + nonce prevent replay attacks

9.3 Privacy

  • PII redaction in trajectory gossip
  • Agents control what they share (opt-in trajectory publishing)
  • Memory encryption at rest
  • GDPR-compliant data deletion

9.4 Reputation

  • Peers track reputation of trajectory contributors
  • Low-reputation trajectories weighted down in curation
  • Sybil resistance via proof-of-work participation (pulse rounds)

10. Compatibility

Hyperspace's primitive model maps cleanly to existing protocols. The bridges described below are on the roadmap — the semantic mappings are defined, and implementation is planned for Q2–Q3 2026. Today, @hyperspace/bridge provides cross-chain EVM bridging.

10.1 MCP Bridge (roadmap)

Any MCP server's tools can be registered in the Hyperspace DHT, making them discoverable by any peer in the mesh:

// SDK API — planned for Q2 2026
await hyperspace.bridge.registerMCPServer({
  url: 'stdio://path/to/server',
  tools: ['search', 'read_file']
})
// Tools now discoverable by any Hyperspace peer

10.2 A2A Bridge (roadmap)

A2A agent cards can be announced via Hyperspace gossip, enabling discovery of A2A-native agents within the mesh:

// SDK API — planned for Q2 2026
await hyperspace.bridge.announceA2AAgent({
  agentCard: { name: 'researcher', skills: [...] }
})

10.3 MPP Bridge (roadmap)

Settle payments via Stripe MPP for fiat currency when P2P settlement is not available or not preferred:

// SDK API — planned for Q3 2026
await hyperspace.bridge.settleMPP({
  sessionId: session.id,
  amount: 0.05,
  currency: 'USD'
})

11. Wire Format Examples

Complete JSON-RPC exchange examples showing full request/response cycles for common workflows.

Example 1: Agent Session Lifecycle

Create a session, discover a tool, invoke it, record the trajectory, and end the session.

1. Create SessionClient → Node
{
  "jsonrpc": "2.0",
  "method": "state.createSession",
  "params": {
    "agentName": "research-agent",
    "agentType": "autonomous",
    "model": "gemma-3-12b"
  },
  "id": 1
}

// Response
{
  "jsonrpc": "2.0",
  "result": {
    "sessionId": "sess-a8c3f210",
    "createdAt": "2026-03-18T14:00:00.000Z"
  },
  "id": 1
}
2. Discover ToolClient → Node → DHT
{
  "jsonrpc": "2.0",
  "method": "tool.discover",
  "params": {
    "query": "web search",
    "minReputation": 0.8
  },
  "id": 2
}

// Response
{
  "jsonrpc": "2.0",
  "result": {
    "tools": [{
      "id": "tool-web-9f1c",
      "name": "web-search",
      "peerId": "12D3KooWRx434ACwmJz...",
      "description": "Full-text web search",
      "capabilities": ["search"],
      "reputation": 0.95,
      "avgLatency": 180,
      "schema": {
        "input": { "type": "object", "properties": { "query": { "type": "string" } } },
        "output": { "type": "object", "properties": { "results": { "type": "array" } } }
      }
    }]
  },
  "id": 2
}
3. Invoke ToolClient → Node → Peer
{
  "jsonrpc": "2.0",
  "method": "tool.invoke",
  "params": {
    "toolId": "tool-web-9f1c",
    "params": { "query": "solid-state battery breakthroughs 2026" },
    "sessionId": "sess-a8c3f210"
  },
  "id": 3
}

// Response
{
  "jsonrpc": "2.0",
  "result": {
    "result": { "results": [{ "title": "...", "url": "...", "snippet": "..." }] },
    "duration": 195,
    "peerId": "12D3KooWRx434ACwmJz..."
  },
  "id": 3
}
4. Record Trajectory & End SessionClient → Node → GossipSub
{
  "jsonrpc": "2.0",
  "method": "improving.recordTrajectory",
  "params": {
    "taskType": "web-research",
    "input": { "query": "solid-state battery breakthroughs 2026" },
    "output": { "summary": "...", "confidence": 0.91 },
    "steps": [
      { "action": "discover", "tool": "tool.discover", "duration": 45 },
      { "action": "search", "tool": "web-search", "duration": 195 },
      { "action": "synthesize", "tool": "summarizer", "duration": 720 }
    ],
    "reward": 0.91
  },
  "id": 4
}

// Response
{
  "jsonrpc": "2.0",
  "result": {
    "trajectoryId": "traj-b4d1e8c2",
    "state": "SUCCESS",
    "gossipedTo": 11
  },
  "id": 4
}

// End session
{
  "jsonrpc": "2.0",
  "method": "state.endSession",
  "params": { "sessionId": "sess-a8c3f210" },
  "id": 5
}

// Response
{
  "jsonrpc": "2.0",
  "result": { "ended": true, "duration": 3420 },
  "id": 5
}

Example 2: Collective Learning Flow

Agent B receives a gossiped trajectory from Agent A, then uses it as an exemplar for its own task.

1. Get Exemplars (includes Agent A's trajectory)Client → Node
{
  "jsonrpc": "2.0",
  "method": "improving.getExemplars",
  "params": {
    "taskType": "web-research",
    "limit": 3,
    "minReward": 0.8
  },
  "id": 10
}

// Response -- includes Agent A's trajectory received via gossip
{
  "jsonrpc": "2.0",
  "result": {
    "exemplars": [
      {
        "trajectoryId": "traj-b4d1e8c2",
        "input": { "query": "solid-state battery breakthroughs 2026" },
        "steps": [
          { "action": "discover", "tool": "tool.discover", "duration": 45 },
          { "action": "search", "tool": "web-search", "duration": 195 },
          { "action": "synthesize", "tool": "summarizer", "duration": 720 }
        ],
        "reward": 0.91,
        "utilityScore": 0.89,
        "usageCount": 3,
        "peerId": "12D3KooWPketJm42a75B..."
      }
    ],
    "librarySize": 178,
    "avgReward": 0.74
  },
  "id": 10
}

Example 3: Budget Guard with Error

Demonstrates the error response format when a budget check fails.

Budget Check — ExceededClient → Node
{
  "jsonrpc": "2.0",
  "method": "guard.checkBudget",
  "params": {
    "sessionId": "sess-a8c3f210",
    "estimatedCost": 5.00
  },
  "id": 11
}

// Response -- budget exceeded
{
  "jsonrpc": "2.0",
  "result": {
    "allowed": false,
    "remaining": 0.12,
    "consumed": 0.88,
    "limit": 1.00,
    "reason": "Estimated cost ($5.00) exceeds remaining budget ($0.12)"
  },
  "id": 11
}

// If the agent ignores the check and tries to consume anyway:
{
  "jsonrpc": "2.0",
  "method": "guard.consumeBudget",
  "params": {
    "sessionId": "sess-a8c3f210",
    "amount": 5.00,
    "description": "large-model-inference"
  },
  "id": 12
}

// Error response
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32002,
    "message": "Budget exceeded",
    "data": {
      "remaining": 0.12,
      "requested": 5.00,
      "limit": 1.00
    }
  },
  "id": 12
}