GrayMatter SWARM Protocol v0.1
GrayMatter SWARM is the canonical coordination contract for ValkyrAI, ValorIDE, OpenClaw, Codex, Claude adapters, human operators, and business automation agents. WebSocket/STOMP is the live command bus. SwarmOps and the Agent Directory are the live registration and coordination surfaces. GrayMatter memory stores durable memory and replay context; it does not treat SwarmOps as a memory primitive.
The goal is direct agent-to-agent operation without Discord as the primary control plane. Discord, Slack, email, and other channels can remain notification adapters, but agents should publish and consume SWARM events through this protocol.
v0.1 is the canonical contract. Older ValkyrAI and ValorIDE envelopes are accepted only as dashboard fallback input while adapters are replaced; new agent implementations should emit GrayMatter SWARM events directly.
Machine-readable schema: graymatter-swarm-v0.1.schema.json
Canonical source in ValkyrAI OpenAPI inputs:
valkyrai/src/main/resources/openapi/schemas/graymatter-swarm-v0.1.schema.json
Design Principles
- One envelope across every agent: Codex, OpenClaw, Valor, Valklaw, ValorIDE, Claude, workflows, services, and humans all emit the same top-level event shape.
- Agent Directory first: every autonomous agent touching ValkyrAI creates or
refreshes a durable
Agentrecord, then includesagentRecordIdin SWARM events. SwarmOps-only heartbeats are visible but non-compliant. - Live bus plus durable memory: WebSocket is for low-latency coordination; SwarmOps records live coordination state, while GrayMatter memory stores replayable decisions, preferences, todos, artifacts, configuration, and context.
- Explicit capability gates: every command declares who sent it, what they are allowed to do, what target environment it touches, and whether an ack is required.
- Idempotent by event ID: agents de-duplicate by
eventIdand preserve the latest terminal state for eachcorrelationId. - Show work, do not leak secrets: status, proof, artifacts, and errors are shared; secrets, raw tokens, and private customer data are not broadcast.
Transport Topology
The current ValkyrAI and ValorIDE implementation already uses Spring WebSocket/STOMP with these broker prefixes and app destinations:
| Surface | Current Contract | Use |
|---|---|---|
| STOMP endpoint | /swarm | Preferred SWARM broker endpoint for agents and ValorIDE. |
| Workflow endpoint | /ws | Workflow monitoring and Workflow Studio telemetry. |
| Legacy chat endpoint | /chat | Compatibility path for existing web chat traffic. |
| Broker prefixes | /topic, /queue | Broadcast and direct delivery. |
| App prefix | /app | Client-to-server actions such as chat, register, ack, announce. |
| REST operations | /v1/swarm-ops plus legacy /v1/swarmOps and /v1/SwarmOps aliases | Register, unregister, command, graph, agent list, discovery. |
| Agent discovery/chat | /v1/swarm/... | Hierarchy, discovery, quota, and agent chat operations. |
STOMP Channels
| Channel | SWARM stream | Purpose |
|---|---|---|
/topic/messages | swarm.audit, swarm.memory, swarm.command | System-wide events, compatibility broadcasts, web console messages. |
/topic/statuses | swarm.presence, swarm.task, swarm.audit | Status, readiness, health, and progress. |
/topic/agents | swarm.presence | Agent roster, heartbeat, registration changes. |
/topic/agent-commands | swarm.command | Broadcast commands for eligible agents. |
/queue/agents/{instanceId}/commands | swarm.command | Direct commands for one agent instance. |
/topic/workflow-monitoring | swarm.task, swarm.audit | Workflow telemetry and execution state. |
/topic/workflow/{workflowId} | swarm.task | Workflow-specific status. |
/topic/swarm-graph | swarm.audit, swarm.presence | SwarmOps graph and dashboard telemetry. |
/topic/git-activity | swarm.git | Branch, PR, merge, and review events. |
/topic/team-projects, /topic/team-progress | swarm.task | Team orchestration progress. |
Agents publish to /app/chat for compatibility broadcasts, and to
/app/agent/register, /app/agent/ack, and /app/agent/announce when those
server handlers are available. REST fallback uses SwarmOps command and
register endpoints.
Registration Sequence
Every autonomous agent uses this order before it accepts work:
- Create or refresh a ValkyrAI
Agentobject through/v1/Agent. - Register the live instance through
/v1/swarm-ops/registeror/v1/swarm/agents. - Publish
swarm.presence.registeredto/topic/agentswithsource.agentRecordId. - Start heartbeat events with the same
agentRecordId,instanceId, and capability set.
The LCARS SwarmOps dashboard reads both /v1/Agent and the live SwarmOps
registry. Agents without a durable Agent object are shown as Needs Agent so
humans and other agents can see the difference between live presence and trusted
directory identity.
Event Envelope
Every v0.1 message is a SwarmEvent.
{
"protocol": "graymatter.swarm",
"version": "0.1",
"eventId": "018f1de2-7ef6-7c3f-bd51-8d8a0e8dbad1",
"type": "swarm.task.assigned",
"timestamp": "2026-05-03T18:42:00Z",
"source": {
"agentId": "codex-john-macbook",
"agentRecordId": "agent-codex-john-macbook",
"agentType": "codex",
"instanceId": "codex-desktop-01",
"principalId": "john",
"displayName": "Codex"
},
"target": {
"agentId": "valklaw",
"agentRecordId": "agent-valklaw",
"agentType": "openclaw",
"instanceId": "valklaw-01"
},
"workspace": {
"repo": "ValkyrAI",
"branch": "p0exec/2297-20260503-swarm-protocol",
"environment": "loki"
},
"correlationId": "swarm-2297",
"parentEventId": null,
"requiresAck": true,
"ttlMs": 300000,
"priority": "urgent",
"capability": {
"name": "deploy.loki",
"scope": "ValkyrAI",
"risk": "high"
},
"durability": {
"mode": "swarm-task",
"grayMatterObjectType": "SwarmTask",
"memoryEntryType": "todo"
},
"security": {
"authContext": "jwt",
"rbac": ["ROLE_ADMIN"],
"deploymentTarget": "loki",
"productionAllowed": false,
"containsSecrets": false
},
"payload": {
"action": "deploy",
"data": {
"target": "loki.valkyrlabs.com",
"reason": "QA latest rc-6 build"
},
"metadata": {
"githubIssue": 2297
}
}
}
Required Fields
| Field | Requirement |
|---|---|
protocol | Always graymatter.swarm. |
version | Current value is 0.1. |
eventId | Globally unique event identifier. Receivers must de-duplicate on this field. |
type | Dot-delimited event name such as swarm.task.assigned. |
timestamp | UTC ISO-8601 creation time. |
source | Sending agent, service, workflow, or human. Autonomous agents must include durable agentRecordId. |
payload | Action-specific payload. |
correlationId | Stable thread/task/workflow identifier for tracing and replay. |
Legacy Field Mapping
Current ValorIDE and ValkyrAI clients use a smaller SwarmMessage envelope. v0.1
keeps it compatible through this mapping:
| Legacy field | v0.1 field |
|---|---|
id | eventId |
type: command | type: swarm.command.requested |
type: response | type: swarm.command.completed or swarm.task.completed |
type: broadcast | type: swarm.audit.broadcast or more specific stream type |
type: event | Specific swarm.* event type |
type: ack | type: swarm.command.ack |
type: nack | type: swarm.command.nack |
from | source |
to | target |
ackId | parentEventId, with payload.data.ackId preserved for legacy traceability |
ttl | ttlMs |
payload.action | payload.action |
payload.data | payload.data |
payload.metadata.workflowId | workspace.workflowId or payload.metadata.workflowId |
payload.metadata.correlationId | correlationId |
security.signature | security.signature |
security.encrypted | security.encrypted |
Dashboard consumers may accept both envelopes to keep LCARS visibility during adapter replacement. Producers should emit v0.1 directly; compatibility does not guarantee command execution for legacy envelopes.
Event Types
Use one of these top-level streams, then a concrete verb:
| Stream | Examples | Durable object |
|---|---|---|
swarm.presence | swarm.presence.registered, swarm.presence.heartbeat, swarm.presence.left | SwarmAgent, SwarmSession |
swarm.task | swarm.task.ready, swarm.task.assigned, swarm.task.started, swarm.task.blocked, swarm.task.completed | SwarmTask |
swarm.memory | swarm.memory.write, swarm.memory.query, swarm.memory.linked | MemoryEntry, GrayMatter |
swarm.git | swarm.git.pr-opened, swarm.git.reviewed, swarm.git.merged, swarm.git.check-failed | SwarmAuditRecord |
swarm.deploy | swarm.deploy.requested, swarm.deploy.loki-started, swarm.deploy.loki-completed, swarm.deploy.denied | SwarmDeployment |
swarm.crm | swarm.crm.lead-created, swarm.crm.activity-logged, swarm.crm.opportunity-updated | SwarmCrmAction |
swarm.cms | swarm.cms.article-drafted, swarm.cms.page-published, swarm.cms.asset-linked | SwarmCmsAction |
swarm.command | swarm.command.requested, swarm.command.ack, swarm.command.nack, swarm.command.completed | SwarmEvent, SwarmTask |
swarm.audit | swarm.audit.notice, swarm.audit.policy-violation, swarm.audit.proof | SwarmAuditRecord |
Durable Object Contracts
These are logical object contracts. Implementations may map them onto current ThorAPI models, GrayMatter records, SwarmOps graph nodes/edges, or future first-class generated models.
| Object | Purpose | Minimum fields |
|---|---|---|
SwarmAgent / Agent | Durable agent identity and capability declaration. | agentRecordId, agentId, agentType, displayName, capabilities, ownerPrincipalId, status, lastSeenAt |
SwarmSession | Live connection and heartbeat state. | sessionId, agentId, instanceId, connectedAt, lastHeartbeatAt, stompEndpoint, subscriptions |
SwarmTask | Work item state tied to GitHub, workflows, deployments, CRM, or CMS. | taskId, correlationId, title, priority, status, assigneeAgentId, sourceIssue, acceptanceCriteria |
SwarmEvent | Replayable event envelope. | all required envelope fields, normalized type, payload hash |
SwarmCapability | Permissioned capability declaration. | name, agentId, scope, risk, requiresHumanApproval, allowedTargets |
SwarmDeployment | Deployment request and proof state. | deploymentId, environment, repo, branch, commit, actor, status, proofUrl |
SwarmCrmAction | Lead, opportunity, and activity work. | actionId, customerId, opportunityId, campaignId, status, evidence |
SwarmCmsAction | Article, page, media, and SEO work. | actionId, contentId, spaceId, status, url, evidence |
SwarmAuditRecord | Non-repudiation and compliance trail. | auditId, eventId, actor, decision, policy, result, timestamp |
Task Lifecycle
SWARM tasks move through a small, explicit lifecycle:
| Status | Meaning |
|---|---|
ready | The work is eligible. P0 Ready tickets are the primary work queue. |
assigned | A responsible agent has accepted ownership. |
started | Work has begun and the agent has emitted a heartbeat. |
blocked | The task cannot proceed without a dependency or human decision. |
review | A PR, artifact, deployment, or content entry is ready for review. |
completed | Acceptance criteria are met and proof is linked. |
canceled | The work was intentionally stopped. |
failed | The agent hit a terminal error and emitted recovery guidance. |
Every state change should include correlationId, source, target when
applicable, and a concise payload.data.proof link or note when evidence exists.
Ack, Nack, and Error Semantics
requiresAck: truemeans the target must respond withswarm.command.ackorswarm.command.nackbefore the sender considers the command accepted.swarm.command.ackmeans accepted for execution, not completed.swarm.command.completedor a terminalswarm.task.completedevent proves completion.swarm.command.nackmust includepayload.data.codeandpayload.data.message.- Timeouts use
ttlMs. Senders may retry with the samecorrelationIdand a neweventId; receivers must de-duplicate identical command payload hashes. - Errors that indicate policy refusal use
swarm.audit.policy-violationand should not be retried automatically.
Idempotency and Replay
Receivers maintain a short-term cache of processed eventId values and a durable
record of terminal task state keyed by correlationId. Durable replay is rebuilt
from GrayMatter and SwarmOps:
- Load
SwarmAgentand latestSwarmSessionrecords. - Load active
SwarmTaskrecords by priority and status. - Replay
SwarmEventrecords bytimestamp. - Reconcile missing live agents by sending
swarm.presence.rollcall. - Re-emit only non-terminal tasks that are still within policy and TTL.
Capability and RBAC Guardrails
Capabilities are declared in source.capabilities or the durable
SwarmCapability object, then checked against security.
| Actor | Allowed default behavior | Guardrail |
|---|---|---|
valklaw | Triage, bug fixes, feature patches, Loki QA deploys. | May deploy to loki.valkyrlabs.com only. Never production. |
valor | Marketing research, CMS content, lead-gen campaigns, CRM activity creation. | Must emit CRM/CMS proof events, not only article drafts. |
codex | Code review, implementation, PR creation, issue triage, protocol/spec work. | Merge only with green required checks or explicit human approval. |
valoride | Desktop/code editing, prompt broadcast, local execution, agent UI. | Must respect workspace ownership and user approval settings. |
valkyrai-native | ValkyrAI-hosted native agent and workflow execution. | Must create an Agent record before touching app/customer data. |
human | Prioritization, approvals, production deploys, policy overrides. | Production deploy authority is reserved for John. |
The protocol intentionally separates deploymentTarget from productionAllowed.
A command can name production as context, but productionAllowed must be true
and the actor must be a human with the required role before any production action
can proceed.
Examples
Valklaw Registers Presence
{
"protocol": "graymatter.swarm",
"version": "0.1",
"eventId": "018f1df8-8544-77ad-a1be-6bd2e9d6f5f9",
"type": "swarm.presence.registered",
"timestamp": "2026-05-03T19:00:00Z",
"source": {
"agentId": "valklaw",
"agentRecordId": "agent-valklaw",
"agentType": "openclaw",
"instanceId": "valklaw-01",
"displayName": "Valklaw"
},
"correlationId": "presence-valklaw-01",
"requiresAck": false,
"priority": "normal",
"durability": {
"mode": "memory-entry",
"grayMatterObjectType": "SwarmAgent"
},
"security": {
"authContext": "jwt",
"deploymentTarget": "none",
"productionAllowed": false,
"containsSecrets": false
},
"payload": {
"action": "register",
"data": {
"agentRecordId": "agent-valklaw",
"status": "online",
"capabilities": ["bugfix", "feature.patch", "deploy.loki"],
"stompSubscriptions": [
"/topic/agent-commands",
"/queue/agents/valklaw-01/commands"
]
}
}
}
Assign a Loki Deploy Task
{
"protocol": "graymatter.swarm",
"version": "0.1",
"eventId": "018f1df9-b388-79fd-b2ff-1eb86bbdc595",
"type": "swarm.deploy.requested",
"timestamp": "2026-05-03T19:03:00Z",
"source": {
"agentId": "codex-john-macbook",
"agentRecordId": "agent-codex-john-macbook",
"agentType": "codex",
"displayName": "Codex"
},
"target": {
"agentId": "valklaw",
"agentRecordId": "agent-valklaw",
"agentType": "openclaw",
"instanceId": "valklaw-01"
},
"workspace": {
"repo": "ValkyrAI",
"branch": "rc-6",
"environment": "loki"
},
"correlationId": "deploy-loki-rc-6-20260503",
"requiresAck": true,
"ttlMs": 300000,
"priority": "urgent",
"capability": {
"name": "deploy.loki",
"scope": "ValkyrAI",
"risk": "high"
},
"durability": {
"mode": "swarm-task",
"grayMatterObjectType": "SwarmDeployment"
},
"security": {
"authContext": "jwt",
"deploymentTarget": "loki",
"productionAllowed": false,
"containsSecrets": false
},
"payload": {
"action": "deploy",
"data": {
"target": "loki.valkyrlabs.com",
"acceptanceCriteria": [
"deploy latest rc-6 build",
"publish health check proof",
"emit swarm.deploy.loki-completed or swarm.deploy.denied"
]
},
"metadata": {
"githubIssue": 2297
}
}
}
Valor Completes CMS and CRM Work
{
"protocol": "graymatter.swarm",
"version": "0.1",
"eventId": "018f1dfa-576d-785b-a4a2-f690a2849e29",
"type": "swarm.crm.activity-logged",
"timestamp": "2026-05-03T19:07:00Z",
"source": {
"agentId": "valor",
"agentRecordId": "agent-valor",
"agentType": "openclaw",
"instanceId": "valor-01"
},
"correlationId": "campaign-graymatter-trustfabric",
"requiresAck": false,
"priority": "high",
"durability": {
"mode": "memory-entry",
"grayMatterObjectType": "SwarmCrmAction"
},
"security": {
"authContext": "jwt",
"deploymentTarget": "none",
"productionAllowed": false,
"containsSecrets": false
},
"payload": {
"action": "crm.activity.log",
"data": {
"campaign": "GrayMatter TrustFabric",
"leadCount": 12,
"cmsUrls": ["/blog/agentic-memory-trustfabric"],
"crmObjects": ["Customer", "Opportunity", "SalesActivity"],
"proof": "SwarmCrmAction:campaign-graymatter-trustfabric"
}
}
}
Codex Completes PR Review
{
"protocol": "graymatter.swarm",
"version": "0.1",
"eventId": "018f1dfb-1d4d-70b7-a2ca-fd5f8f21111c",
"type": "swarm.git.reviewed",
"timestamp": "2026-05-03T19:11:00Z",
"source": {
"agentId": "codex-john-macbook",
"agentRecordId": "agent-codex-john-macbook",
"agentType": "codex"
},
"workspace": {
"repo": "ValkyrAI",
"branch": "p0exec/2297-20260503-swarm-protocol"
},
"correlationId": "github-pr-2297",
"requiresAck": false,
"priority": "high",
"durability": {
"mode": "swarm-audit",
"grayMatterObjectType": "SwarmAuditRecord"
},
"security": {
"authContext": "github",
"deploymentTarget": "none",
"productionAllowed": false,
"containsSecrets": false
},
"payload": {
"action": "review",
"data": {
"pullRequest": 2297,
"decision": "changes-requested",
"reason": "required checks are failing",
"proof": "https://github.com/ValkyrLabs/ValkyrAI/pull/2297"
}
}
}
Implementation Profiles
ValkyrAI Server
- Keep
/swarmas the preferred STOMP endpoint for SWARM traffic. - Ensure
/v1/Agentcan create durable Agent Directory records for autonomous agents before SwarmOps registration. - Keep
/topic/agents,/topic/agent-commands, and/queue/agents/{instanceId}/commandsfor compatibility. - Normalize incoming REST and WebSocket command payloads into
SwarmEventbefore persistence or graph emission. - Store live coordination state through SwarmOps and write durable memory
through GrayMatter
MemoryEntry/GrayMatterpaths when the event contains reusable decisions, preferences, todos, artifacts, configuration, or context.
ValorIDE
- Replace the shared
SwarmMessagehelper with v0.1 adapter functions that translate currentid/type/from/to/ackIdmessages intoSwarmEvent. - On connect, create or refresh an
Agentrecord, register with capabilities, publishswarm.presence.registered, then subscribe to direct and broadcast command channels. - The current
presence:joinandauth:ackevents should map toswarm.presence.registeredandswarm.command.ack.
OpenClaw, Codex, Claude, and Other Agents
- Agents should implement the schema as their public contract, even if their first adapter only writes HTTP REST fallback events.
- Agents must create or refresh a ValkyrAI
Agentrecord and carryagentRecordIdin every SWARM event before they work on ValkyrAI, GrayMatter, ValorIDE, CRM, CMS, or deployment tasks. - Agents that cannot open a WebSocket should still write durable
SwarmEventrecords and poll assignedSwarmTaskobjects until a live adapter exists. - Agents should emit compact proof events for PRs, deployments, CRM work, CMS publishing, and blockers.