Python SDK reference.
cosmonapse Python package - verified against packages/python-sdk. If something here disagrees with the code, the code wins.
Signal & SignalType
A Signal is the in-memory representation of an envelope - a Pydantic v2 model. Every method that publishes or receives a message uses it. See the envelope spec for the full wire-level field reference.
cosmonapse.SignalPydantic BaseModel mirroring the envelope schema. encode() / decode() round-trip with the wire format; field validators reject ids that don't carry the evt_ / trc_ prefixes.
class Signal(BaseModel): # pydantic v2 model v: str = "1" id: str # evt_<ULID>, auto-generated trace_id: str # trc_<ULID>, auto-generated parent_id: str | None = None type: SignalType directed: Directed | None = None # unified addressing ts: datetime # UTC, auto-set on construction payload: dict = {} meta: dict = {} # Field validators reject ids that don't start with evt_ / trc_. def encode(self) -> bytes: ... # compact JSON bytes for the wire @classmethod def decode(cls, data: bytes | str) -> "Signal": ... def reply(self, type, payload=None, directed=None, meta=None) -> "Signal": ... # Child Signal sharing this trace, parented to this id. directed # propagates from the source unless overridden. class Directed(BaseModel): # precedence on receive: id > type > capabilities id: str | None = None # direct address (neuron_id or engram_id) type: str | None = None # type routing (neuron type or engram_kind) capabilities: list[str] = [] # capability routing # Producer identity rides directed too: an AGENT_OUTPUT's directed.id # is the neuron_id that produced it (there is no Signal.neuron field).
cosmonapse.SignalTypeString enum of every legal type. SYNAPSE_TYPES is a frozenset of the values a Dendrite is allowed to publish - anything else passed to dendrite.emit() raises DendriteProtocolError.
class SignalType(str, Enum): # Lifecycle TASK = "TASK" AGENT_OUTPUT = "AGENT_OUTPUT" FINAL = "FINAL" ERROR = "ERROR" # Routing TASK_OFFER = "TASK_OFFER" BID = "BID" TASK_AWARDED = "TASK_AWARDED" TASK_DECLINED = "TASK_DECLINED" # Cognition THOUGHT_DELTA = "THOUGHT_DELTA" PLAN = "PLAN" TOOL_CALL = "TOOL_CALL" TOOL_RESULT = "TOOL_RESULT" # Memory MEMORY_APPEND = "MEMORY_APPEND" ESCALATION = "ESCALATION" # Coordination CONSENSUS = "CONSENSUS" CONTEXT_SYNC = "CONTEXT_SYNC" CRITIQUE = "CRITIQUE" CLARIFICATION = "CLARIFICATION" PERMISSION = "PERMISSION" PERMISSION_DECISION = "PERMISSION_DECISION" CLARIFICATION_ANSWER = "CLARIFICATION_ANSWER" # Engram - shared memory RECALL = "RECALL" RECALLED = "RECALLED" IMPRINT = "IMPRINT" IMPRINTED = "IMPRINTED" # Agent management REGISTER = "REGISTER" DEREGISTER = "DEREGISTER" HEARTBEAT = "HEARTBEAT" # Discovery DISCOVER = "DISCOVER" # Workflow control - cooperative cancellation of a whole trace STOP = "STOP" STOPPED = "STOPPED" # Frozensets defining who may emit what: AXON_TYPES # AGENT_OUTPUT, CLARIFICATION, PERMISSION, ERROR, REGISTER, DEREGISTER, HEARTBEAT SYNAPSE_TYPES # every type a Dendrite is allowed to emit (incl. ERROR)
stop_signal(...) / stopped_signal(...)Envelope builders for the workflow-control pair. stop_signal(*, trace_id, rollback=False, reason=None) builds a STOP; stopped_signal(*, trace_id, parent_id, rolled_back=False, cancelled=0, compensated=0, node=None) builds the ack. You rarely call these directly - Dendrite.emit_stop / stop_trace build and publish them for you.
Have a feature in mind?
The protocol, SDKs, and CLI are still pre-1.0. If something here is missing, ambiguous, or wrong - open an issue and propose a change. Every breaking change is debated in DECISIONS.md first.