SW4RM Agentic Protocol
SW4RM is an open coordination protocol for agent swarms. It provides guaranteed message delivery, persistent scheduling, multi-agent negotiation, crash-safe handoffs, and rich observability -- the runtime layer that sits between your agents and lets them work together reliably.
This repository contains five SDKs (Python, Rust, JavaScript, Elixir, Common Lisp), three reference services (Registry, Router, Scheduler), an A2A protocol gateway, and a Docker Compose stack that brings everything up in one command.
Try It in 2 Minutes
git clone https://github.com/rahulrajaram/sw4rm.git && cd sw4rm
# Start the full stack (Registry, Router, Scheduler, A2A Gateway)
docker compose up --build -d
# Verify the A2A gateway is running
curl http://localhost:8080/.well-known/agent.json
# Run the quickstart demo (registers agents, sends messages, heartbeats)
./quickstart.sh --local
Or use the JSON-RPC interface:
curl -X POST http://localhost:8080/ \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"GetAgentCard","params":{},"id":1}'
SDKs
| SDK | Directory | Tests | README |
|---|---|---|---|
| Python | sdks/py_sdk |
770 | README |
| Rust | sdks/rust_sdk |
329 | README |
| JavaScript/TypeScript | sdks/js_sdk |
410 | README |
| Elixir | sdks/ex_sdk |
331 | README |
| Common Lisp | sdks/cl_sdk |
87+333 | README |
All SDKs implement the same protocol (17 proto3 service definitions) and follow the same layered architecture adapted to language idioms.
A2A Gateway
The a2a_gateway/ module exposes any SW4RM agent swarm via the A2A (Agent-to-Agent) protocol. External A2A clients see standard Agent Cards and JSON-RPC 2.0; internally, SW4RM handles scheduling, negotiation, and crash recovery.
| Endpoint | Description |
|---|---|
GET /.well-known/agent.json |
A2A Agent Card for the gateway |
POST / (JSON-RPC) SendMessage |
Route a message to a SW4RM agent |
POST / (JSON-RPC) GetTask |
Query task state |
POST / (JSON-RPC) CancelTask |
Cancel via Scheduler preemption |
POST / (JSON-RPC) GetAgentCard |
Get agent card by ID |
See a2a_gateway/README.md for details.
Core Features
- Guaranteed Delivery: Router with persistent message queues, ACK lifecycle (received/read/fulfilled/rejected/failed/timed_out), and automatic reconciliation
- Scheduling and Preemption: Priority-based task scheduling with cooperative preemption, urgent lane semantics, and activity buffer persistence
- Multi-Agent Negotiation: Proposal/vote/decision protocol with configurable quorum policies, confidence-weighted vote aggregation, and timeout profiles
- Crash-Safe Handoffs: Structured agent-to-agent work transfer with context serialization, capability matching, and full audit trail
- Worktree Isolation: Policy-driven worktree binding with persistent state across restarts
- A2A Interoperability: Gateway translates between A2A protocol and SW4RM, with
.well-known/agent.jsondiscovery - Five SDKs: Python, Rust, JavaScript/TypeScript, Elixir, Common Lisp -- all wire-compatible
Installation
Python
pip install sw4rm-sdk
# or from source:
pip install -e ".[dev]"
Rust
[dependencies]
sw4rm-sdk = "0.6.0"
tokio = { version = "1.0", features = ["full"] }
JavaScript / TypeScript
npm install @sw4rm/js-sdk
Elixir
# mix.exs
defp deps do
[{:sw4rm, "~> 0.6.0"}]
end
Common Lisp
(push (truename "sdks/cl_sdk/") asdf:*central-registry*)
(ql:quickload :sw4rm-sdk)
Quick Start
Python
import grpc
from sw4rm.clients.registry import RegistryClient
from sw4rm.clients.router import RouterClient
# Connect to services
registry_ch = grpc.insecure_channel("localhost:50052")
router_ch = grpc.insecure_channel("localhost:50051")
registry = RegistryClient(registry_ch)
router = RouterClient(router_ch)
# Register agent
registry.register({
"agent_id": "my-agent",
"name": "My Agent",
"capabilities": ["processing"],
})
# Send message
router.send_message({
"producer_id": "my-agent",
"consumer_id": "target-agent",
"message_type": 2, # DATA
"payload": b"hello",
"content_type": "text/plain",
"correlation_id": "req-001",
})
# Heartbeat and deregister
registry.heartbeat(agent_id="my-agent", state=1)
registry.deregister(agent_id="my-agent")
Rust
use sw4rm_sdk::*;
use async_trait::async_trait;
struct EchoAgent {
config: AgentConfig,
preemption: PreemptionManager,
}
#[async_trait]
impl Agent for EchoAgent {
async fn on_message(&mut self, envelope: EnvelopeData) -> Result<()> {
if let Ok(text) = envelope.string_payload() {
println!("Echo: {}", text);
}
Ok(())
}
fn config(&self) -> &AgentConfig { &self.config }
fn preemption_manager(&self) -> &PreemptionManager { &self.preemption }
}
#[tokio::main]
async fn main() -> Result<()> {
let config = AgentConfig::new("echo-1".into(), "Echo Agent".into());
let agent = EchoAgent { config: config.clone(), preemption: PreemptionManager::new() };
AgentRuntime::new(config).run(agent).await
}
JavaScript / TypeScript
import { RegistryClient, RouterClient, buildEnvelope, MessageType, CommunicationClass } from '@sw4rm/js-sdk';
const registry = new RegistryClient('localhost:50052');
const router = new RouterClient({ address: 'localhost:50051' });
await registry.registerAgent({
agent_id: 'echo-1',
name: 'EchoAgent',
capabilities: ['echo'],
communication_class: CommunicationClass.STANDARD,
});
const stream = router.streamIncoming('echo-1');
for await (const item of stream) {
const reply = buildEnvelope({
producer_id: 'echo-1',
message_type: MessageType.DATA,
payload: item.msg.payload,
content_type: 'application/json',
});
await router.sendMessage(reply);
}
Elixir
# Register and send a message
{:ok, channel} = GRPC.Stub.connect("localhost:50052")
Sw4rm.Transport.Client.register(channel, %{agent_id: "my-agent", capabilities: ["echo"]})
See sdks/ex_sdk/examples/reference_demo.exs for a full demo exercising all 12 SDK features.
Reference Services
Three reference service implementations run the SW4RM protocol:
| Service | Port | Metrics | Description |
|---|---|---|---|
| Registry | 50052 | 9100 | Agent discovery, heartbeat, deregistration |
| Router | 50051 | 9101 | Message routing, delivery queues, streaming |
| Scheduler | 50053 | 9102 | Task scheduling, preemption, activity buffer |
Start locally:
cd sdks/py_sdk/reference-services
bash start_services.sh --local
Or via Docker:
docker compose up --build -d
Examples
Tutorials
- Code-Agent Tutorial: 3-agent code review swarm (writer + reviewers + deployer) using negotiation and handoff --
code_agent_tutorial.py|walkthrough
Python
echo_agent.py-- Minimal echo agentvoting_example.py-- Multi-reviewer votingnegotiation_debate_example.py-- Negotiation room debatehandoff_example.py-- Agent-to-agent handoffhitl_escalation_example.py-- Human-in-the-loopworkflow_orchestration_example.py-- Multi-step workflowtool_streaming_example.py-- Tool call streamingthree_id_demo.py-- Three-ID correlation
Rust
echo_agent.rs-- Minimal echo agentadvanced_agent.rs-- Full-featured agenthandoff.rs-- Agent handoffworkflow.rs-- Workflow orchestrationnegotiation_room.rs-- Negotiation roomactivity_demo.rs-- Activity buffer
JavaScript / TypeScript
echoAgent.ts-- Minimal echo agentadvancedAgent.ts-- Full-featured agenthandoffExample.ts-- Agent handoffworkflowExample.ts-- Workflow orchestrationnegotiationRoomExample.ts-- Negotiation roomhitlEscalation.ts-- Human-in-the-loop
Elixir
reference_demo.exs-- Full SDK feature demobasic_agent.exs-- Minimal agentnegotiation_flow.exs-- Negotiation flowhandoff.exs-- Agent handofftool_execution.exs-- Tool execution
Common Lisp
echo-agent.lisp-- Minimal echo agentnegotiation-voting.lisp-- Negotiation votingsecret-management.lisp-- Secret managementtool-streaming.lisp-- Tool streaming
Architecture
All five SDKs follow the same layered architecture:
+---------------------------+
| Integration Layer | ACK lifecycle, message processing, workflows
+---------------------------+
| Client Layer | Registry, Router, Scheduler, HITL, Negotiation,
| | Handoff, Tool, Worktree, Connector, Reasoning
+---------------------------+
| Protocol Layer | Proto3 wire format (17 service definitions)
+---------------------------+
| Runtime Layer | Activity buffer, worktree state, state machine
+---------------------------+
Each SDK adapts this to language idioms: Python uses classes and context managers, Rust uses async/await traits, JavaScript uses Promises and async iterators, Elixir uses GenServers and supervisors, and Common Lisp uses the condition/restart system.
CI Workflows
| Workflow | What it does |
|---|---|
| Python CI | Python 3.12, pytest, smoke tests |
| Rust CI | cargo test --all --locked with protoc |
| JS CI | Node 20, npm ci && npm run build && npm test |
| Elixir CI | Elixir 1.16 / OTP 26, mix test + reference demo |
| Common Lisp CI | SBCL + Quicklisp, FiveAM test suite |
| Proto Check | Protocol file validation |
| Version Guard | Cross-SDK version consistency |
| Secrets Scan | Trufflehog credential scanning |
Reproduce locally
# All SDKs
make test
# Individual
make test-python # pytest -q sdks/py_sdk/tests
make test-rust # cd sdks/rust_sdk && cargo test --all --locked
make test-js # cd sdks/js_sdk && npm ci && npm run build && npm test
make test-lisp # cd sdks/cl_sdk && sbcl --load test/suite.lisp
# Elixir (Docker, no local Elixir required)
docker run --rm -v $(pwd):/app -w /app/sdks/ex_sdk elixir:1.16 \
bash -c "mix local.hex --force && mix local.rebar --force && mix deps.get && mix test"
Development
Generate Protocol Buffers
pip install -e ".[dev]"
make protos
Smoke Test
# Local mode (starts services, runs checks, cleans up)
./scripts/smoke_test.sh
# Docker mode (includes A2A gateway checks)
./scripts/smoke_test.sh --docker
Release
Publishing is tag-driven per language via GitHub Actions:
# Python → PyPI
git tag py-v0.6.0 && git push origin py-v0.6.0
# JavaScript → npm
git tag npm-v0.6.0 && git push origin npm-v0.6.0
# Rust → crates.io
git tag rs-v0.6.0 && git push origin rs-v0.6.0
Requires environment secrets (PYPI_API_TOKEN, NPM_TOKEN, CRATES_IO_TOKEN) in the production GitHub Actions Environment.
See CONTRIBUTING.md for versioning policy, commit hooks, and PR guidelines.
License
Metadata
Release files for sw4rm-sdk 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sw4rm_sdk-0.6.0.tar.gz | 146.9 kB | Without provenance | Details for sw4rm_sdk-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sw4rm_sdk-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for sw4rm_sdk-0.6.0-py3-none-any.whl |
Total release size: 328.3 kB
Release files / sw4rm_sdk-0.6.0.tar.gz
| Download URL | sw4rm_sdk-0.6.0.tar.gz |
|---|---|
| Size | 146.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
de7c996e74a3e5c61d0a25e463d5e6b5939ea18b454c240763f94090280a8053
|
|
BLAKE2b-256 checksum How to use checksums |
a0e425e0311b2ac7501ab42a7726094e4a73edb1b184c1610674f20f4839f145
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / sw4rm_sdk-0.6.0-py3-none-any.whl
| Download URL | sw4rm_sdk-0.6.0-py3-none-any.whl |
|---|---|
| Size | 181.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5e1e09e385c822f24b1e4b020710c220f55c03b34bc1a1b296a3c8cf80c560ba
|
|
BLAKE2b-256 checksum How to use checksums |
c5b54f1913d170e464929d48a6e9b1ae625e2813cadd784fd9abdb7ad66c8c72
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for sw4rm-sdk 0.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.