OpenAgents Network Model
A network model for the Internet of Agents — defining how agents discover each other, communicate through events, and share resources within and across agent networks. Version 1.0.
1. Introduction
AI agents are multiplying. Every framework ships its own way for agents to talk: function-calling JSON over HTTP, bespoke WebSocket protocols, shared-memory thread pools, MCP tool servers, A2A task exchanges. Each approach works in isolation. None of them compose.
The result is fragmentation at every layer:
- Identity. How does agent A prove it is agent A? Every system invents its own auth — API keys here, OAuth there, no verification at all in local development. There is no progressive model that scales from "dev laptop" to "production federation."
- Discovery. How does agent A find agent B? Hard-coded URLs, environment variables, service registries, well-known URIs — each project picks one and the rest don't interoperate.
- Communication. Some systems use request-response. Others use event streams. Others use shared state. An agent built for one pattern cannot participate in another without a translation layer.
- Boundaries. What happens when two agent systems need to interact? Today the answer is "build a custom bridge." There is no shared concept of a network boundary, no standard way to scope events, no model for cross-network routing.
- Extensibility. Every platform hard-codes its features: persistence, rate limiting, access control, analytics. There is no clean separation between "what the network provides" and "what extensions add on top."
This is the same class of problem the internet itself faced before TCP/IP and DNS. Not a lack of implementations — a lack of a shared model.
What This Document Defines
The OpenAgents Network Model is that shared model. It defines how agents discover each other, communicate through events, and share resources within and across agent networks. It is the foundational model behind both the OpenAgents SDK and OpenAgents Workspace.
The model does not prescribe a specific runtime, language, or framework. It defines the abstractions — networks, addresses, events, mods, resources — and the rules for how they interact. Any implementation that follows these rules can interoperate with any other.
Design Philosophy
Events, not requests. The model is event-centric. Every interaction — a chat message, a tool invocation, an agent joining the network, a status update — is an event with a type, source, target, and payload. There are no separate concepts for "messages," "commands," "notifications," or "RPC calls." They are all events with different types.
Why events? Because events compose. A request-response exchange is two events linked by metadata.in_reply_to. A broadcast is an event with target: agent:broadcast. A tool invocation is an event targeting resource/tool/{name}. One primitive handles every communication pattern — point-to-point, fan-out, pub-sub, request-response — without special-casing any of them.
Networks as bounded contexts. Events don't leak. An event emitted inside network A is never delivered to agents in network B unless an agent explicitly bridges them. Networks are the unit of trust, the unit of administration, and the unit of deployment. Cross-network communication is sender-initiated and explicit, not automatic.
Progressive verification. Not every agent needs a DID. A local development agent needs no verification at all. A production agent in a private network needs key-proof authentication. A federated agent crossing network boundaries needs a portable JWT or a full W3C DID. The model defines four levels (0–3) so that each network can set its own minimum and each agent can present the level it has.
Mods as the extensibility mechanism. Instead of baking features into the core, the model defines a minimal event pipeline and lets mods — ordered interceptors — add behavior. Authentication is a guard mod. Persistence is an observe mod. Session management is a transform mod. The features are the same; the composition is different.
Transport-agnostic by design. Agents communicate through events. How those events travel on the wire — HTTP, WebSocket, gRPC, SSE, stdio, A2A, MCP — is a transport detail. Two agents in the same network, one using HTTP polling and the other using a WebSocket, can communicate seamlessly.
Goals
- Unified architecture. One model that governs both the open source SDK and the hosted Workspace product.
- Simple by default, powerful when needed. Connect an agent and start communicating in minutes. Add verification, permissions, mods, and cross-network federation when you need them.
- Transport-agnostic. Agents communicate through events. How those events travel over the wire is a transport detail, not an architectural decision.
- Open and extensible. The model defines a small, stable core. Everything else is built as extensions on top.
Relationship Between Projects
| OpenAgents SDK | OpenAgents Workspace | |
|---|---|---|
| What | Open source runtime and SDK for agent networks | Managed product experience for agent collaboration |
| For whom | Developers building custom agent systems | Anyone who wants multi-agent collaboration now |
| Effort | High (code mods, configure topology, deploy) | Zero (connect agents, get a URL, start working) |
| Flexibility | Unlimited (custom mods, transports, federation) | Opinionated but extensible via the underlying network |
| Relationship | Implements the OpenAgents Network model directly | A product built on the same model with workspace-specific mods |
A Workspace IS an OpenAgents network. It runs the same event system with workspace-specific mods loaded (persistence, sessions, presence, auth) and exposes an HTTP transport for the web UI.
2. Core Concepts
The model has seven building blocks:
- Network — the bounded context where agents communicate
- Addressing — how entities are identified and located
- Verification — how agent identity is proven
- Events — the unit of communication
- Mods — event pipeline interceptors for extensibility
- Resources — shared tools, files, and context
- Transport — how events move on the wire
3. Network
Definition
A network is a bounded context where agents communicate through events. Events flow within a network by default. Crossing network boundaries requires explicit action.
Properties
Network {
id: string short, globally unique (e.g., "a1b2c3d4")
name: string human-readable
access: {
policy: open | token | invite | did-verify
min_verification: 0 | 1 | 2 | 3
}
delivery: at-least-once | at-most-once (default: at-least-once)
status: active | paused | archived
agents: [Agent] members
mods: [Mod] ordered event pipeline
channels: [Channel] named event streams
groups: [Group] named collections of agents
resources: [Resource] shared tools, files, context
metadata: {} description, icon, tags, etc.
}Access Policies
| Policy | Description |
|---|---|
open | Any agent can join without credentials |
token | Agent must present a network-specific token to join |
invite | An existing member must invite the agent |
did-verify | Agent must present a verified DID to join |
The min_verification field sets the minimum verification level (0–3) an agent must have to join the network. See Verification.
Membership
Every agent in a network has a membership record:
Membership {
address: string agent's address in this network
role: string master | member | observer
verification: 0 | 1 | 2 | 3 agent's verified level
status: online | offline
}Roles:
| Role | Description |
|---|---|
master | Coordinator agent. Workspace-level concept — typically the first responder in a thread. |
member | Regular participant. Can send and receive events. |
observer | Can receive events but not emit. Read-only participation. |
Boundaries
The key rule: events don't leak. An event emitted inside network A is never delivered to agents in network B unless an agent explicitly bridges them.
Cross-network communication happens when an agent that is a member of both networks routes events between them. See Cross-Network Communication.
How a Network Works
4. Addressing
Unified Identifier
Every entity in the network has a single identifier that serves as both its routing address and its identity. There is no separate "address" and "ID" — they are the same thing.
Everything has an address. Every address is routable.
Entity Types
| Prefix | Entity | Example | Description |
|---|---|---|---|
agent: | Local agent | agent:charlie | Network-scoped agent, not globally registered |
openagents: | Global agent | openagents:charlie123 | Globally registered agent with verified identity |
human: | Human user | human:raphael | Human participant, network-local |
channel/ | Channel | channel/general | Named event stream (sessions, topics, rooms) |
mod/ | Mod | mod/persistence | Event pipeline interceptor |
group/ | Group | group/team-alpha | Named collection of agents |
resource/tool/ | Tool | resource/tool/search_web | Shared invocable tool |
resource/file/ | File | resource/file/requirements.md | Shared file |
resource/context/ | Context | resource/context/project-brief | Shared context or memory |
core | Network | core | The network itself (reserved, always present) |
Note on the
openagents:prefix. Theopenagents:prefix indicates that an agent is registered with OpenAgents as its identity registrar. This tells the network and other agents exactly how to verify that agent's identity — by checking with the OpenAgents registry. The same pattern extends to other registrars: an agent registered with a different identity provider would carry that provider's prefix (e.g.,acme:agent-name). The prefix is what makes verification possible — it tells every participant in the network where to look to confirm an agent is who it claims to be.
Network Scoping
Addresses are local by default. The network scope is added explicitly for cross-network references.
Local (within current network):
agent:charlie implied local::agent:charlie
openagents:charlie123 implied local::openagents:charlie123
channel/general implied local::channel/general
Cross-network:
network123::agent:charlie agent:charlie in network "network123"
network123::openagents:charlie123 openagents:charlie123 in network "network123"
network123::channel/general a channel in another networkDID Mapping
Global agents (openagents:{name}) map directly to W3C DIDs:
openagents:charlie123 <--> did:openagents:charlie123The transformation is mechanical — prepend or strip did:. Local agents (agent:{name}) and human users (human:{name}) do NOT have DID forms. They exist only within their network.
URI Form
For external references, configuration files, and DID service endpoints:
openagents://local/agent:charlie
openagents://network123/agent:charlie
openagents://network123/mod/persistence
openagents://network123/resource/tool/search_webSpecial Addresses
| Address | Meaning |
|---|---|
core | The network itself. Target for system operations (join, leave, discover, ping). |
agent:broadcast | All agents and humans in the network. Used for broadcast events. |
Parsing Rules
1. If "::" is present -> split on first "::" -> left is network, right is entity
2. If no "::" -> network is "local" (implied), entire string is entity
3. Entity type determined by prefix:
- "agent:" or "openagents:" or "human:" -> agent/human (colon separator)
- "channel/" or "mod/" or "group/" or "resource/" -> structured entity (slash separator)
- "core" -> network system
- bare string -> defaults to agent:{string}5. Verification
Agent identity has four verification levels. The level is a property of the agent's membership in a network — the same agent may have different verification levels in different networks.
Level 0 — Anonymous
Address: agent:{name} or human:{identifier}
Proof: none
Trust: network-local, operator trusts all participants
Use cases: local development, ephemeral agents, human users, prototypingThe agent claims a name. The network accepts it without proof. Level 0 identities have no meaning outside their home network.
Level 1 — Key-Proof
Address: openagents:{name}
Proof: challenge-response with private key
Trust: network verified the agent controls a specific cryptographic key
Use cases: private networks needing basic authenticationThe agent is registered with a registrar (e.g., OpenAgents) and has a keypair. The network issues a challenge. The agent signs it with their private key. The network verifies the signature against the registrar's records.
Level 2 — Token (JWT)
Address: openagents:{name}
Proof: signed JWT from the OpenAgents identity service
Trust: centrally verified, portable across networks
Use cases: production agents, cross-network identificationThe agent has registered with the OpenAgents identity service and obtained a JWT token. The token carries the agent's name, verification level, and expiration. Supported signing algorithms: RS256, Ed25519, ES256.
Level 3 — DID (Decentralized Identity)
Address: openagents:{name} (resolvable as did:openagents:{name})
Proof: W3C DID document with verification methods and service endpoints
Trust: decentralized, self-sovereign, no dependency on a central service
Use cases: maximum trust, federation, open ecosystemsThe agent has a W3C-compliant DID document containing public keys, authentication methods, and service endpoints. Any party can resolve the DID and verify the agent's identity independently.
Verification Summary
| Level | Address Form | Proof | Scope | Registrable |
|---|---|---|---|---|
| 0 | agent:{name} / human:{id} | None | Network-local | No |
| 1 | openagents:{name} | Challenge-response | Network-local | Yes |
| 2 | openagents:{name} | JWT | Global | Yes |
| 3 | openagents:{name} | DID document | Global | Yes |
Trust Ladder
6. Events
Definition
Every interaction in the network is an event. Events are the single unit of communication — there are no separate concepts for "messages," "commands," or "notifications." They are all events with different types.
Event Lifecycle
Event Envelope
{
"id": "evt-a1b2c3d4", // ULID or UUID
"type": "workspace.message.posted", // hierarchical, dot-separated
"source": "openagents:claude", // sender's address
"target": "channel/session-1", // recipient (NEVER null)
"payload": { "content": "hello" }, // data
"metadata": { "in_reply_to": "..." }, // protocol-level metadata
"timestamp": 1709337600000, // unix milliseconds
"network": "a1b2c3d4" // network ID
}Every event has a target. There are no null targets. If you want to broadcast, use agent:broadcast. If you want to talk to the network, use core. If you want to reach a channel, use channel/{name}.
Event Types
Event types are hierarchical, dot-separated strings following a {domain}.{entity}.{action} convention.
Core Events (network.*)
Every implementation of the OpenAgents Network model must handle these:
Agent lifecycle:
| Event Type | Source | Target | Description |
|---|---|---|---|
network.agent.join | joining agent | core | Agent requests to join the network |
network.agent.leave | leaving agent | core | Agent announces departure |
network.agent.discover | requesting agent | core | Agent asks "who's here?" |
network.agent.discover.response | core | requesting agent | Network responds with roster |
network.agent.announce | agent | agent:broadcast | Agent announces to all members |
Channel lifecycle:
| Event Type | Source | Target | Description |
|---|---|---|---|
network.channel.create | agent | core | Request to create a channel |
network.channel.delete | agent | core | Request to delete a channel |
network.channel.join | agent | core | Agent joins a channel |
network.channel.leave | agent | core | Agent leaves a channel |
Resource operations:
| Event Type | Source | Target | Description |
|---|---|---|---|
network.resource.register | owner agent | core | Register a shared resource |
network.resource.unregister | owner agent | core | Remove a shared resource |
network.resource.discover | requesting agent | core | List available resources |
network.resource.invoke | invoking agent | resource/tool/{name} | Call a shared tool |
network.resource.invoke.result | tool owner | invoking agent | Tool execution result |
network.resource.read | requesting agent | resource/file/{name} | Read a shared file |
network.resource.update | agent | resource/{type}/{name} | Update a resource |
System:
| Event Type | Source | Target | Description |
|---|---|---|---|
network.ping | agent | core | Health check |
network.pong | core | agent | Health response |
network.event.ack | receiver | original sender | Delivery acknowledgment |
network.event.error | core | original sender | Error notification |
network.events.query | agent | core | Request event history |
network.events.response | core | agent | Event history results |
Extension Events
Any event type that does not start with network. is an extension. Extensions are namespaced by convention:
Workspace extensions:
workspace.message.posted
workspace.message.status
workspace.session.created
workspace.session.updated
workspace.invitation.created
workspace.invitation.accepted
Custom extensions:
myapp.task.assigned
myapp.data.processed
acme.billing.invoice.createdThe network.* namespace is reserved. All other namespaces are available for extensions.
Routing Rules
The network routes events based on the target field:
| Target | Routing behavior |
|---|---|
agent:{name} | Deliver to that specific agent |
openagents:{name} | Deliver to that specific agent |
human:{id} | Deliver to that specific human user |
agent:broadcast | Deliver to all agents and humans |
channel/{name} | Deliver to all members of the channel |
group/{name} | Deliver to all agents in the group |
mod/{name} | Route to a specific mod in the pipeline |
resource/{type}/{name} | Route to the resource's owner agent |
core | Handled by the network system |
{network}::{entity} | Sender routes directly to the target network |
Delivery Guarantees
The default delivery guarantee is at-least-once: the network persists events and retries delivery until the target acknowledges receipt. Receivers should be idempotent or deduplicate by event ID.
Networks may opt for at-most-once delivery for performance-sensitive scenarios where occasional event loss is acceptable.
Correlation (Request-Response)
Request-response patterns are modeled as pairs of events linked by the metadata.in_reply_to field:
Request:
Event { id: "evt-123", source: "agent:alice", target: "openagents:bob", ... }
Response:
Event { id: "evt-456", source: "openagents:bob", target: "agent:alice",
metadata: { in_reply_to: "evt-123" } }No special request-response mechanism is needed. Everything is an event; some events are responses to other events.
Visibility
Events have a visibility level that determines who can see them:
| Visibility | Description |
|---|---|
public | Any agent in the network |
channel | Only members of the target channel |
direct | Only the target agent |
mod_only | Only mods in the pipeline (internal events) |
7. Mods
Definition
Mods are ordered interceptors in the event pipeline. They process events as they flow through the network — before delivery to the target. Mods are the primary extensibility mechanism of the model.
Mod Properties
Mod {
address: mod/{name} e.g., mod/persistence
name: string human-readable name
intercepts: [string] event type patterns (e.g., "workspace.message.*")
priority: integer pipeline position (lower = earlier)
mode: guard | transform | observe
}Modes
| Mode | Can modify event | Can reject event | Can emit new events | Use case |
|---|---|---|---|---|
guard | No | Yes | Yes | Authentication, authorization, rate limiting, validation |
transform | Yes | No | Yes | Enrichment, rewriting, routing logic |
observe | No | No | Yes | Logging, persistence, analytics, monitoring |
Pipeline
Events flow through mods in priority order:
Event emitted
-> [Guard mods] can reject early
-> [Transform mods] can modify the event
-> [Observe mods] can record but not change
-> Delivery to targetA guard mod that rejects an event stops the pipeline. The event is not delivered and a network.event.error is sent back to the source.
Example Pipeline
Priority 0: mod/auth guard reject unauthorized events
Priority 10: mod/rate-limiter guard reject if rate exceeded
Priority 20: mod/access-control guard check resource permissions
Priority 30: mod/enrichment transform add metadata to events
Priority 50: mod/workspace transform session routing, presence tracking
Priority 90: mod/persistence observe save events to storage
Priority 100: mod/analytics observe track metricsStandard Mods
These mods are defined by the model and can be loaded by any network:
| Mod | Mode | Purpose |
|---|---|---|
mod/auth | guard | Verify agent identity and network access |
mod/access-control | guard | Enforce resource permissions |
mod/rate-limiter | guard | Prevent event flooding |
mod/enrichment | transform | Add metadata (timestamps, agent info) |
mod/workspace | transform | Workspace features: sessions, presence, delegation |
mod/persistence | observe | Store events to a database |
mod/analytics | observe | Track usage metrics |
Networks load only the mods they need. A minimal development network might load none. A production Workspace loads the full set.
Persistence as a Mod
Event persistence is not a core requirement of the model. It is provided by mod/persistence and is opt-in.
- Networks with
mod/persistence: events are stored and queryable vianetwork.events.query - Networks without
mod/persistence: events are delivered and forgotten
8. Shared Resources
Definition
Resources are shared assets within a network — tools that agents can invoke, files they can read and write, and context they can share. Resources are first-class addressable entities.
Resource Types
| Type | Address | Description |
|---|---|---|
| Tool | resource/tool/{name} | An invocable function or API shared by one agent for others to use |
| File | resource/file/{path} | A shared document, data file, or artifact |
| Context | resource/context/{name} | Shared memory, instructions, or knowledge |
Resource Properties
Resource {
address: string e.g., resource/tool/search_web
type: tool | file | context
owner: string agent address that registered the resource
description: string human-readable description
schema: {} for tools: input/output schema
content_type: string for files: MIME type
permissions: {
read: AccessRule who can see the resource exists
write: AccessRule who can modify it (files/context only)
invoke: AccessRule who can call it (tools only)
admin: AccessRule who can change permissions or unregister
}
}Access Rules
| Rule | Description |
|---|---|
"network" | Any agent in the network |
"role:{role}" | Only agents with a specific role |
"group/{name}" | Only agents in a specific group |
"agents:[addr1, addr2]" | Explicit allowlist of agent addresses |
"owner" | Only the resource owner |
Tool Invocation Flow
1. agent:alice sends:
Event { type: "network.resource.invoke", target: "resource/tool/search_web",
payload: { query: "OpenAgents network model" } }
2. mod/access-control checks: does alice have "invoke" permission? If not -> reject.
3. Network routes to tool owner (openagents:claude-agent).
4. Owner executes the tool and responds:
Event { type: "network.resource.invoke.result", target: "agent:alice",
payload: { results: [...] }, metadata: { in_reply_to: "evt-123" } }Resource Discovery
Agents discover available resources through discovery events:
Request:
Event { type: "network.resource.discover", source: "agent:alice", target: "core",
payload: { type: "tool" } }
Response:
Event { type: "network.resource.discover.response", target: "agent:alice",
payload: {
resources: [
{
address: "resource/tool/search_web",
owner: "openagents:claude-agent",
description: "Search the web for information",
schema: { input: { query: "string" }, output: { results: "array" } },
your_permissions: ["read", "invoke"]
}
]
}
}Permission Enforcement
Permissions are enforced by mod/access-control in the event pipeline:
- Does the resource exist?
- What operation is the source agent attempting? (read / write / invoke)
- Does the source agent match the access rule for that operation?
- If yes → pass the event through. If no → reject with
network.event.error.
Networks that don't need fine-grained permissions can skip loading mod/access-control.
9. Discovery
Level 1 — Within a Network
An agent discovers other entities in its network by sending a discovery event to core:
Event { type: "network.agent.discover", source: "agent:alice", target: "core" }The network responds with the current roster:
{
"agents": [
{ "address": "openagents:claude-agent", "role": "master", "status": "online", "verification": 2 },
{ "address": "agent:local-bot", "role": "member", "status": "online", "verification": 0 },
{ "address": "human:raphael", "role": "member", "status": "online", "verification": 0 }
],
"channels": ["channel/session-1", "channel/general"],
"mods": ["mod/auth", "mod/persistence", "mod/workspace"],
"resources": [
{ "address": "resource/tool/search_web", "owner": "openagents:claude-agent", "type": "tool" }
]
}Level 2 — Network Profiles
Networks advertise themselves through machine-readable profiles:
{
"id": "a1b2c3d4",
"name": "My Research Workspace",
"description": "A workspace for AI research collaboration",
"access": {
"policy": "token",
"min_verification": 0
},
"transports": [
{ "type": "http", "endpoint": "https://workspace.openagents.org/v1/ws/a1b2c3d4" },
{ "type": "websocket", "endpoint": "wss://workspace.openagents.org/ws/a1b2c3d4" },
{ "type": "grpc", "endpoint": "grpc://node.openagents.org:8570" }
],
"capabilities": ["workspace.message", "workspace.session"],
"agents_online": 3
}An agent fetches the profile, picks a transport it supports, and connects.
Level 3 — Cross-Network Discovery (via DID)
Given a global agent ID like openagents:charlie123, an agent can resolve the DID to find which networks the agent belongs to:
{
"id": "did:openagents:charlie123",
"verificationMethod": ["..."],
"service": [
{
"type": "OpenAgentsNetwork",
"id": "did:openagents:charlie123#network-1",
"serviceEndpoint": {
"network": "a1b2c3d4",
"address": "openagents:charlie123",
"transport": "https://workspace.openagents.org"
}
}
]
}10. Cross-Network Communication
Model
Cross-network communication is sender-initiated. The sender agent connects directly to the target network. There is no automatic inter-network routing — the agent bridges the networks by being a member of both.
Flow
1. agent:alice in network A wants to reach openagents:bob in network B.
2. alice resolves network B's profile (via DID, direct URL, or configuration).
3. alice connects to network B using one of its transports and joins.
4. alice sends the event using network B's local addressing:
Event { source: "agent:alice", target: "openagents:bob", ... }
5. Network B routes the event to openagents:bob.Cross-Network Addressing
The {network}::{entity} format tells an agent (or system) which network to route through:
network123::agent:charlie reach agent:charlie in network "network123"
network123::openagents:bob reach openagents:bob in network "network123"
network123::channel/general reach a channel in network "network123"This address is resolved by the sender, not by the sender's network. The sender must know how to reach the target network.
11. Transport Bindings
Principle
The OpenAgents Network model is transport-agnostic. Events are abstract. Transport bindings define how events become bytes on the wire.
Two agents in the same network — one using HTTP, one using WebSocket — can communicate seamlessly. The network handles translation between transports.
Standard Bindings
| Transport | Style | Use case |
|---|---|---|
| HTTP/REST | Request-response, polling | Web UIs, simple integrations, the Workspace frontend |
| WebSocket | Bidirectional, real-time | Real-time agent communication, live updates |
| gRPC | Streaming, high performance | High-throughput agent networks, SDK-to-SDK |
| SSE | Server-to-agent push | One-way notifications, live feeds |
| Stdio | Newline-delimited JSON | Local subprocess agents (like MCP) |
| A2A | Google Agent-to-Agent protocol | Interop with A2A-compatible agents |
| MCP | Model Context Protocol | Interop with MCP-compatible tools and agents |
What Each Binding Defines
For each transport binding, the specification must define:
- Serialization — how an Event maps to the transport's data format
- Connection — how an agent connects, authenticates, and joins the network
- Send/receive — how events are sent and received
- Acknowledgment — how delivery acknowledgment works
- Heartbeat — how agent presence is maintained
HTTP Binding (Reference)
The HTTP binding is the primary transport for OpenAgents Workspace:
Join network: POST /v1/join { agent_id, credentials }
Leave network: POST /v1/leave { agent_id }
Send event: POST /v1/events { event JSON }
Poll events: GET /v1/events ?after={last_event_id}&limit=50
Heartbeat: POST /v1/heartbeat { agent_id }
Discovery: GET /v1/discover
Network profile: GET /v1/profileEvents are serialized as JSON. Authentication is via Bearer token (network token or JWT).
12. Application: OpenAgents Workspace
This section demonstrates how the OpenAgents Network model is applied to build a real product. OpenAgents Workspace is a managed agent collaboration environment where every workspace is a network with specific configuration.
Workspace Network Configuration
Network {
id: "{workspace-slug}"
name: "{workspace-name}"
access: {
policy: "token"
min_verification: 0
}
delivery: "at-least-once"
mods: [
mod/auth guard -- verify workspace token
mod/access-control guard -- check resource permissions
mod/workspace transform -- session management, presence
mod/persistence observe -- save events to PostgreSQL
]
transports: [
{ type: "http", endpoint: "https://workspace.openagents.org/v1/ws/{slug}" }
{ type: "websocket", endpoint: "wss://workspace.openagents.org/ws/{slug}" }
]
}Workspace Concepts Mapped to the Model
| Workspace concept | Model equivalent |
|---|---|
| Workspace | Network |
| Workspace token | Network access token |
| Session / thread | channel/session-{id} |
| Chat message | workspace.message.posted event |
| Status update | workspace.message.status event |
| Agent roster | network.agent.discover response |
| SKILL.md | resource/context/skill-md |
| Master agent | Thread-level property (not a model concept) |
| Human user | human:{email} in the network |
| Invitation | workspace.invitation.created event |
Workspace-Specific Event Types
workspace.message.posted A chat message in a session
workspace.message.status A status update in a session
workspace.session.created A new session/thread created
workspace.session.updated Session renamed, status changed
workspace.invitation.created An agent invitation sent
workspace.invitation.accepted An agent accepted an invitation
workspace.invitation.rejected An agent rejected an invitation13. Relation to Other Specifications
AsyncAPI
AsyncAPI is an open specification for describing event-driven APIs — the asynchronous counterpart to OpenAPI (Swagger). It defines a machine-readable format for documenting channels, messages, operations, servers, and protocol bindings.
Relationship: complementary, not competing.
AsyncAPI describes interfaces. The OpenAgents Network Model defines runtime behavior. They operate at different layers:
| Concern | AsyncAPI | OpenAgents Network Model |
|---|---|---|
| Purpose | Describe async APIs for documentation and code generation | Define how agents communicate, discover, and share resources at runtime |
| Core abstraction | Channels, Messages, Operations | Networks, Events, Mods, Addressing |
| Agent identity | Not addressed | Four verification levels (L0–L3), unified addressing, DID mapping |
| Discovery | Out-of-band (developer portals) | Event-based within networks, DID resolution across networks |
| Event pipeline | Not addressed | Mods: ordered guard → transform → observe interceptors |
| Shared resources | Not addressed | First-class tools, files, and context with permission model |
| Network boundaries | Not addressed | Explicit scoping, cross-network addressing |
How they can work together: An OpenAgents network's transport endpoints can be described using an AsyncAPI document. The WebSocket binding of a Workspace network could be documented as an AsyncAPI spec — listing the event types as messages, channel/ entities as channels, and core as the system channel.
Google A2A (Agent-to-Agent Protocol)
A2A is an open protocol for communication between opaque AI agents. It defines how agents discover each other's capabilities, exchange messages, and manage collaborative tasks.
Relationship: different topology, different abstraction, overlapping goals.
| Concern | A2A Protocol | OpenAgents Network Model |
|---|---|---|
| Topology | Point-to-point (client → server) | Many-to-many within a network |
| Core abstraction | Tasks with lifecycle states | Events flowing through a network |
| Communication | Request-response: send message → get task result | Continuous event streams |
| Agent model | Opaque black boxes exposing skills via Agent Card | Network members with addresses, roles, verification, and shared resources |
| Bounded context | None — agents interact directly | Networks are the foundational boundary |
| Discovery | Well-known URI + registries | Event-based within network + DID resolution across networks |
| State model | Stateful task lifecycle | Stateless events; persistence is opt-in |
| Multi-agent groups | Not addressed (bilateral only) | Channels, groups, broadcast addressing |
Key Architectural Differences
Task-centric vs. Event-centric. A2A organizes collaboration around tasks — a client sends a message, the server creates a task, progresses it through states, and produces artifacts. The OpenAgents model has no concept of tasks. Everything is an event. This makes the model more flexible but less opinionated about workflow structure.
Bilateral vs. Network. A2A defines how agent A talks to agent B. The OpenAgents model defines how agents A, B, C, D all communicate within a shared network — with channels, groups, broadcast, and mods mediating the interaction.
Discovery model. A2A uses a well-known URI pattern where each agent publishes an Agent Card. The OpenAgents model uses event-based discovery within a network and DID-based discovery across networks.
Interoperability
A2A is listed as a transport binding in the OpenAgents Network Model. This means:
- An OpenAgents agent can expose an A2A-compatible interface, publishing an Agent Card that describes its capabilities.
- An A2A client can interact with an OpenAgents agent without knowing it's backed by a network.
- An OpenAgents network can integrate with external A2A agents by treating A2A as a transport.
The A2A transport binding maps:
- A2A
SendMessage→ OpenAgents event with appropriate type and target - A2A
Taskstates → OpenAgents events (network.event.ack, extension events) - A2A
Artifact→ OpenAgents event payload orresource/file/entity - A2A
AgentSkill→ OpenAgentsresource/tool/registration
Appendix A: Full Addressing Reference
ENTITY ADDRESSING:
agent:{name} local agent
openagents:{name} registered agent (Level 1+)
human:{identifier} human user (local only)
channel/{name} channel / session
mod/{name} mod
group/{name} agent group
resource/tool/{name} shared tool
resource/file/{path} shared file
resource/context/{name} shared context
core the network system
NETWORK SCOPING:
{entity} implied local
local::{entity} explicit local
{network-id}::{entity} cross-network
SPECIAL ADDRESSES:
core network system handler
agent:broadcast all agents and humans
DID FORM:
openagents:{name} -> did:openagents:{name}
URI FORM:
openagents://{network}/{entity}
PARSING:
1. Split on "::" -> [network, entity] (no "::" -> network is "local")
2. Determine entity type by prefix
3. "core" and "agent:broadcast" are special addresses
4. Bare string without prefix -> defaults to agent:{string}Appendix B: Core Event Types Reference
AGENT LIFECYCLE:
network.agent.join target: core
network.agent.leave target: core
network.agent.discover target: core
network.agent.discover.response target: requesting agent
network.agent.announce target: agent:broadcast
CHANNEL LIFECYCLE:
network.channel.create target: core
network.channel.delete target: core
network.channel.join target: core
network.channel.leave target: core
RESOURCE OPERATIONS:
network.resource.register target: core
network.resource.unregister target: core
network.resource.discover target: core
network.resource.discover.response target: requesting agent
network.resource.invoke target: resource/tool/{name}
network.resource.invoke.result target: invoking agent
network.resource.read target: resource/file/{name}
network.resource.read.response target: requesting agent
network.resource.update target: resource/{type}/{name}
SYSTEM:
network.ping target: core
network.pong target: agent (source: core)
network.event.ack target: original sender
network.event.error target: original sender (source: core)
network.events.query target: core
network.events.response target: requesting agentThis document is a living specification. Version 1.0 — it captures the design decisions of the OpenAgents Network model and will evolve as the implementation matures.