First Five Minutes.
Install Cosmonapse, build an Axon backed by Hugging Face, wire a Dendrite, boot a local Synapse, watch Signals flow. No Docker. No running broker. Just pip install (or npm install) and a few files.
Python 3.11+ or Node 18+. The cosmo CLI ships with the Python package - run it from your virtualenv even when using the TypeScript SDK.
# Python 3.11+
pip install cosmonapse httpxcosmo synapse start memory boots a local TCP+NDJSON broker - no Docker, no NATS, no Postgres. Swap the URL for nats:// or kafka:// when you move to production - the rest of your code stays the same.
$ cosmo synapse start memory --namespace=quickstart URL: cosmo://127.0.0.1:7070 Namespace: quickstart Transport: TCP + NDJSON (single-host dev only) ────────────────────────────────────────────────
Two steps, the lower-level way: Neuron(source="huggingface", ...) returns a pure async callable, and Axon(neuron_id=..., neuron_fn=...) gives it an identity on the bus. The Axon validates the Neuron's raw output into a Signal; the Neuron itself never sees the protocol. The one-call factory Axon.huggingface() - and .openai(), .anthropic(), .ollama(), .mcp() - is shorthand for exactly this. Set HF_TOKEN to your Hugging Face access token before running.
import os from cosmonapse import Axon, Neuron # Lower level, two steps. Neuron(source=...) is a pure async callable; # the Axon gives it an identity and validates its output into a Signal. neuron = Neuron(source="huggingface", endpoint="https://router.huggingface.co", model="meta-llama/Llama-3.1-8B-Instruct", api_key=os.environ["HF_TOKEN"], use_chat_api=True) axon = Axon(neuron_id="llama", neuron_fn=neuron, capabilities=["chat"])
The Dendrite is the only component that touches the Synapse - it hosts the Axon, emits REGISTER / HEARTBEAT / DEREGISTER, and routes inbound TASKs. Run this in a second terminal; it registers and waits for tasks.
import asyncio, os from cosmonapse import Axon, Dendrite, Neuron, connect_synapse # Build the Neuron, then wire it into an Axon (the two-step, lower-level form). # role="worker": hosts Axons, replies to TASKs, cannot dispatch. neuron = Neuron(source="huggingface", endpoint="https://router.huggingface.co", model="meta-llama/Llama-3.1-8B-Instruct", api_key=os.environ["HF_TOKEN"], use_chat_api=True) axon = Axon(neuron_id="llama", neuron_fn=neuron, capabilities=["chat"]) async def main(): synapse = await connect_synapse("cosmo://127.0.0.1:7070") worker = Dendrite(synapse=synapse, namespace="quickstart", role="worker") worker.attach_axon(axon) async with worker: await asyncio.sleep(float("inf")) # serve until Ctrl-C asyncio.run(main())
A role="orchestrator" Dendrite has no Axon - its job is to dispatch tasks and collect results. Keep your web framework at the edge and dispatch TASK Signals from route handlers via the orchestrator Dendrite. Install Flask with pip install flask or Express with npm install express.
import asyncio, threading from flask import Flask, jsonify, request from cosmonapse import Dendrite, connect_synapse # asyncio loop in a background thread - Flask stays synchronous. loop = asyncio.new_event_loop() threading.Thread(target=loop.run_forever, daemon=True).start() orch: Dendrite = None async def setup(): global orch synapse = await connect_synapse("cosmo://127.0.0.1:7070") orch = Dendrite(synapse=synapse, namespace="quickstart", role="orchestrator") await orch.start() asyncio.run_coroutine_threadsafe(setup(), loop).result(timeout=10) app = Flask(__name__) @app.post("/task") def submit(): # dispatch_and_wait: emit a TASK, await the first terminal Signal, # close the Pathway, return the Signal. No manual future plumbing. fut = asyncio.run_coroutine_threadsafe( orch.dispatch_and_wait(neuron="llama", input=request.get_json(), timeout_s=30.0), loop, ) reply = fut.result(timeout=32) return jsonify(reply.payload["output"]) app.run(port=5000)
Attach a Doppler to see every Signal as it crosses the Synapse. It is a passive read-only subscriber - it never competes with Dendrites for messages.
$ cosmo doppler --url=cosmo://127.0.0.1:7070 -n quickstart REGISTER neuron=llama capabilities=['chat'] TASK trace=trc_01... neuron=llama AGENT_OUTPUT trace=trc_01... neuron=llama # filter to specific signal types $ cosmo doppler -n quickstart --type TASK --type AGENT_OUTPUT # or open Prism - the live browser visualization (http://127.0.0.1:7071) $ cosmo doppler --prism --url=cosmo://127.0.0.1:7070 -n quickstart
With the synapse, worker, and server all running, send a task:
$ curl -s -X POST http://localhost:5000/task \ -H "Content-Type: application/json" \ -d '{"prompt": "Say hello to Cosmonapse."}' {"response": "Hello! Great to meet you, Cosmonapse..."}
Watch the Doppler terminal - you'll see the full REGISTER → TASK → AGENT_OUTPUT trace as it happens.