SDK · 10

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.

modelcosmonapse.Signal

Pydantic 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.

signal.pyi
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).
enumcosmonapse.SignalType

String 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.

signal_type.pyi
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)
buildersstop_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.