Typed messaging: tractor.msg#

All inter-actor communication rides a small, strictly-typed msgpack wire protocol built from msgspec.Struct types — the “SC-shuttle” protocol that powers contexts, streams, RPC and cancellation. You normally never touch these msg types directly (the Context API speaks them for you) but you do use this subpackage to define payload type contracts: per endpoint via @tractor.context(pld_spec=...) or per channel via custom codecs.

Violations of an active msg-spec surface as MsgTypeError (see Errors and cancellation types); the full typed-payload workflow is shown in examples/typed_payloads.py.

The protocol message set#

PayloadMsg

An abstract payload boxing/shuttling IPC msg type.

Aid

Actor-identity msg.

SpawnSpec

Initial runtime spec handed down from a spawning parent to its child subactor immediately following first contact via an Aid msg.

Start

Initial request to remotely schedule an RPC trio.Task via Actor.start_remote_task().

StartAck

Init response to a Cmd request indicating the far end's RPC spec, namely its callable "type".

Started

Packet to shuttle the "first value" delivered by Context.started(value: Any) from a @tractor.context decorated IPC endpoint.

Yield

Per IPC transmission of a value from await MsgStream.send(<value>).

Stop

Stream termination signal much like an IPC version of StopAsyncIteration.

Return

Final return <value> from a remotely scheduled func-as-trio.Task.

CancelAck

Deliver the bool return-value from a cancellation Actor method scheduled via and prior RPC request.

Error

A pkt that wraps RemoteActorErrors for relay and raising.

Aid (identity handshake) and SpawnSpec (parent -> child init) run at connection setup; Start/StartAck initiate an RPC task; Started/Yield/Stop/Return are the Context dialog phases; CancelAck and Error close the loop on cancellation and (boxed) failure. Msg is a legacy alias of PayloadMsg. The union of all of the above is exported as MsgType (also __msg_spec__).

Define our strictly typed IPC message spec for the SCIPP:

that is,

the “Structurred-Concurrency-Inter-Process-(dialog)-(un)Protocol”.

Codec construction and override#

tractor.msg.mk_codec(ipc_pld_spec=<class 'msgspec.Raw'>, libname='msgspec', enc_hook=None, ext_types=None, ext_dec=None)[source]#

Convenience factory for creating codecs eventually meant to be interchange lib agnostic (i.e. once we support more then just msgspec ;).

Parameters:
Return type:

MsgCodec

class tractor.msg.MsgCodec(_enc, _dec, _pld_spec, lib=<module 'msgspec' from '/home/runner/work/tractor/tractor/.venv/lib/python3.14/site-packages/msgspec/__init__.py'>, _buf=<factory>)[source]#

A IPC msg interchange format lib’s encoder + decoder pair.

Pretty much nothing more then delegation to underlying msgspec.<interchange-protocol>.Encoder/Decoders for now.

Parameters:
encode(py_obj, use_buf=False, as_ext_type=False, hide_tb=True)[source]#

Encode input python objects to msgpack bytes for transfer on a tranport protocol connection.

When use_buf == True use the output buffer optimization: https://jcristharif.com/msgspec/perf-tips.html#reusing-an-output-buffer

Parameters:
  • py_obj (Any | PayloadMsg)

  • use_buf (bool)

  • as_ext_type (bool)

  • hide_tb (bool)

Return type:

bytes

decode(msg)[source]#

Decode received msgpack bytes into a local python object with special msgspec.Struct (or other type) handling determined by the

Parameters:

msg (bytes)

Return type:

Any

tractor.msg.mk_dec(spec, dec_hook=None, ext_types=None)[source]#

Create an IPC msg decoder, a slightly higher level wrapper around a msgspec.msgpack.Decoder which provides,

  • easier introspection of the underlying type spec via the .spec and .spec_str attrs,

  • .hook access to the Decoder.dec_hook(),

  • automatic custom extension-types decode support when dec_hook() is provided such that any PayloadMsg.pld tagged as a type from from ext_types (presuming the MsgCodec.encode() also used a .enc_hook()) is processed and constructed by a PldRx implicitily.

NOTE, as mentioned a MsgDec is normally used for PayloadMsg.pld: PayloadT field decoding inside an IPC-ctx-oriented PldRx.

Parameters:
Return type:

MsgDec

class tractor.msg.MsgDec(_dec)[source]#

An IPC msg (payload) decoder.

Normally used to decode only a payload: MsgType.pld: PayloadT field before delivery to IPC consumer code.

Parameters:

_dec (Decoder)

tractor.msg.apply_codec(codec, ctx=None)[source]#

Dynamically apply a MsgCodec to the current task’s runtime context such that all (of a certain class of payload containing i.e. MsgType.pld: PayloadT) IPC msgs are processed with it for that task.

Uses a contextvars.ContextVar to ensure the scope of any codec setting matches the current Context or ._rpc.process_messages() feeder task’s prior setting without mutating any surrounding scope.

When a ctx is supplied, only mod its Context.pld_codec.

matches the @cm block and DOES NOT change to the original (default) value in new tasks (as it does for ContextVar).

Parameters:
Return type:

MsgCodec

tractor.msg.current_codec()[source]#

Return the current trio.Task.context’s value for msgspec_codec used by Channel.send/.recv() for wire serialization.

Return type:

MsgCodec

Note

apply_codec() swaps the codec via a contextvars.ContextVar — the override only applies to the current task (and tasks it starts), not sibling tasks already running in the actor. Payload-decoding is layered: the outer codec leaves .pld fields as msgspec.Raw and each context’s payload-receiver decodes them against its spec (the “cheap-or-nasty” validation pattern).

Namespace pointers#

class tractor.msg.NamespacePath[source]#

A serializeable str-subtype implementing a “namespace pointer” to any Python object reference (like a function) using the same format as the built-in pkgutil.resolve_name() system.

A value describes a target’s module-path and namespace-key separated by a ‘:’ and thus can be easily used as a IPC-message-native reference-type allowing memory isolated actors to point-and-load objects via a minimal str value.

The 'module.path:obj_name' str-subtype used to address every RPC target function over the wire (same format as pkgutil.resolve_name()).

Pretty structs#

class tractor.msg.Struct[source]#

Bases: Struct

A “human friendlier” (aka repl buddy) struct subtype.

A msgspec.Struct subtype with a multi-line pretty __repr__ — handy as a base for your own IPC payload types so crash logs stay readable.

See also

Contexts and streaming for where pld_spec typing plugs into the @context decorator, Errors and cancellation types for MsgTypeError semantics, and Typed messaging for the guided typed-messaging tour.