Adapters¶
Claudeway is the coordination layer other frameworks don't have. The adapters below make that layer drop into the frameworks you may already be using — without forcing you to rewrite your app around a new SDK.
Four adapters ship today. All of them keep the core claudeway package
dependency-free: the host framework is imported lazily, so pip install
claudeway never pulls LangGraph, CrewAI, MAF, or Nostr in.
| Adapter | Install | Use when |
|---|---|---|
| Buzz (Nostr transport) | claudeway[nostr] |
You want consensus events on the open Nostr wire. |
| LangGraph | claudeway[langgraph] |
You own a StateGraph and want consensus as one node. |
| CrewAI | claudeway[crewai] |
Your crew calls Claudeway as a @tool or Flow. |
| Microsoft Agent Framework | claudeway[maf] |
You want consensus as a typed MAF executor / workflow. |
Buzz adapter (Nostr transport)¶
Buzz coordinates agents via workflows. Claudeway is how they reach signed agreement.
Buzz shipped July 2026 with coordination primitives built around workflows and agent memberships — not cryptographic consensus. Claudeway ships the complementary primitive: signed, tamper-evident receipts that any framework can verify, on the same Nostr wire Buzz speaks.
The adapter isn't a separate package — it's the Nostr NIP-78
transport. A signed Claudeway consensus
receipt renders as a kind: 30078 event that lands in any Nostr relay.
Agents already monitoring a relay see the consensus event; the BIP-340
signature means anyone can verify it wasn't tampered with.
from claudeway.transports import to_nostr_event
event = to_nostr_event(
receipt,
private_key_hex=nostr_key,
d_tag="room-42", # addressable: replaces prior events with the same d-tag
)
# publish `event` to your relay of choice — relay.damus.io, your own relay,
# or any public Nostr relay.
End-to-end demo¶
examples/buzz_consensus_demo.py
runs the full loop: three Claude agents reach consensus, the receipt is
signed, a NIP-78 event is produced and published to a relay, then read back
and verified. The demo runs offline (mock agents) or online (real Swarm).
Verify it yourself¶
The events Claudeway emits verify under the reference Nostr CLI:
See TESTLOG.md
for the four-layer evidence trail: BIP-340 KAT vectors, the test suite,
nak verify, and the end-to-end demo.
LangGraph adapter¶
LangGraph makes you wire coordination by hand. The adapter is the seam.
LangGraph is production-grade orchestration, but its coordination story is "build it yourself": you wire state reducers, fan-out/fan-in nodes, checkpoints, and synthesis logic per graph. The Claudeway adapter collapses all of that into one node that produces a signed agreement the agents actually reached.
from langgraph.graph import StateGraph
from claudeway.adapters.langgraph import make_consensus_node
swarm = ... # your Claudeway Swarm
graph = StateGraph(dict)
graph.add_node("consensus", make_consensus_node(swarm))
graph.set_entry_point("consensus")
graph.set_exit_point("consensus")
app = graph.compile()
result = await app.ainvoke({"question": "Should we ship v0.3.0 today?"})
# result carries the signed consensus receipt
Two entry points¶
The adapter ships two functions, both compile-once (per LangGraph project guidance — never compile inside a node, never return a subgraph from a node):
make_consensus_node(swarm)— returns an async node function youadd_node()into your ownStateGraph. Use this when you own the graph.build_consensus_graph(swarm)— returns a prebuiltCompiledStateGraph:{"question": str}in, signed agreement out. Use standalone, oradd_node()the compiled graph into a parent graph.
State schema¶
The node composes with chat-style graphs out of the box:
messagesaccumulates via LangGraph'sadd_messagesreducer.- Scalar fields (
question,consensus,agreement,disagreed,receipt) overwrite — each run is the latest consensus.
Install¶
Pulls langgraph>=0.2.0 and langchain-core>=0.3.0. The import is lazy;
without the extra, import claudeway never touches LangGraph.
Live demo¶
examples/langgraph_adapter_demo.py
runs the adapter end-to-end with real Claude agents. The LangGraph
integration test is opt-in (set CLAUDEWAY_TEST_LANGGRAPH=1).
CrewAI adapter¶
CrewAI gives you the crew. Claudeway gives the crew a way to agree.
CrewAI shines at multi-role orchestration with great DX. Its coordination story is shallow, though — tasks run in sequence, a synthesizer agent writes the final answer, and there's no signed agreement. The Claudeway adapter inverts the killer demo: instead of Claudeway calling CrewAI, a CrewAI crew calls Claudeway for agreement.
Two entry points, both with lazy imports:
reach_consensus(swarm, sign=True)— returns a CrewAI@tool. Drop it into any agent's tool belt. The agent decides when to escalate a question to consensus.ConsensusFlow(swarm, sign=True, task_id=...)— a prebuilt CrewAI Flow.questionin → signed agreement out. Use standalone or compose into a larger flow.
from claudeway import AgentConfig, Swarm, SwarmConfig
from claudeway.adapters.crewai import ConsensusFlow, reach_consensus
swarm = Swarm(SwarmConfig(
name="CrewChoice",
agents=[
AgentConfig("Dba", "Senior DBA", "You weigh reliability and ops cost."),
AgentConfig("Indie", "Indie Hacker", "You optimize for setup time."),
AgentConfig("Security", "Security Engineer", "You care about data safety."),
],
), api_key=...)
# Flow 1 — tool: a CrewAI agent decides when to call consensus
tool = reach_consensus(swarm, sign=True)
# Flow 2 — prebuilt: question in, signed agreement out
flow = ConsensusFlow(swarm, sign=True, task_id="demo-flow-1")
await flow.kickoff_async(inputs={"question": "Postgres, SQLite, or Supabase?"})
Install¶
Live demo¶
examples/crewai_adapter_demo.py
runs both flows end-to-end with real Claude agents.
Microsoft Agent Framework (MAF) adapter¶
MAF gives you typed executors and a graph. Claudeway is the executor that does the agreement for you.
MAF is Microsoft's unified successor to AutoGen + Semantic Kernel — typed executors, a workflow builder, and structured intermediate events. The Claudeway adapter exposes consensus as both:
build_consensus_workflow(swarm, sign=True, stream=False)— returns a prebuilt workflow.await workflow.run(question)→ final payload with signed receipt. The zero-config path.make_consensus_executor(swarm)— returns a factory that builds a consensusExecutoryou drop into your ownWorkflowBuilder. This is the wedge case: upstream research executor, downstream consensus, both in one graph.
from claudeway import AgentConfig, Swarm, SwarmConfig
from claudeway.adapters.maf import build_consensus_workflow, make_consensus_executor
swarm = Swarm(SwarmConfig(
name="DbChoice",
agents=[
AgentConfig("Dba", "Senior DBA", "You weigh reliability and ops cost."),
AgentConfig("Indie", "Indie Hacker", "You optimize for setup time."),
AgentConfig("Security", "Security Engineer", "You care about data safety."),
],
), api_key=...)
# Flow 1 — prebuilt: zero config
workflow = build_consensus_workflow(swarm, sign=True, task_id="flow-1")
result = await workflow.run("Postgres, SQLite, or Supabase for a side project?")
# Flow 2 — embedded: consensus as one executor in your own workflow
from agent_framework import Executor, WorkflowBuilder, WorkflowContext, handler
class ResearchExecutor(Executor):
@handler
async def research(self, message: str, ctx: WorkflowContext[str]) -> None:
await ctx.send_message(f"prior art on: {message}")
research = ResearchExecutor(id="research")
consensus = make_consensus_executor(swarm)(id="claudeway_consensus")
builder = WorkflowBuilder(start_executor=research, output_from=[consensus])
builder.add_edge(research, consensus)
workflow = builder.build()
Streaming¶
Set stream=True on build_consensus_workflow and the workflow emits
intermediate events as agents finish (kind="agent_completed"), when
consensus resolves (kind="consensus_resolved"), and when the receipt is
signed (kind="consensus_receipt"). This is what "observable consensus"
looks like in practice.
workflow = build_consensus_workflow(swarm, stream=True, sign=True, task_id="flow-3")
async for event in workflow.run(question, stream=True):
if event.type != "intermediate":
continue
data = event.data
if data.get("kind") == "agent_completed":
print(f" [{data['agent']}] conf={data['confidence']:.2f}")
elif data.get("kind") == "consensus_resolved":
print(f" agreement={data['agreement']:.0%}")
Install¶
Live demo¶
examples/maf_adapter_demo.py
runs three flows end-to-end: prebuilt, embedded, and streaming.
Adapter design rules¶
Both adapters follow the same invariants:
- Lazy host imports. The core
claudewaypackage never imports the host framework. Install the extra only if you need the adapter. - Async→sync bridge is always a fresh worker thread. When wrapping an
async
Swarm.processcall into a sync surface, never reuse the caller's event loop — it self-deadlocks underpytest-asyncio, CrewAI's async runtime, and LangGraph's async executor. Always spawn a daemon thread with its own loop andjoin()from the caller. Seeclaudeway/adapters/crewai.py:_run_syncfor the canonical pattern. - Rebuild
AgentResponseobjects from dict forms before signing.Swarmstoresresult.to_dict(), butConsensusReceipt.from_resultreadsr.agent_nameon each response. Adapters rebuild the typed objects before signing rather than mutatingConsensusResult.to_dict().
Follow these if you write your own adapter (A2A, AutoGen, etc.).