marla.messaging
The SPADE message envelope, advisory payload schemas, and parsing/validation.
Message envelope schema shared by every SPADE message MARLA sends.
Per spec section 10, every message carries this metadata regardless of
payload: performative, message_type, schema_version, run_id,
conversation_id, request_id, sender_alias, receiver_alias.
Advisory request/response payload schemas (section 9) are added in
Milestone 6/7; this module covers the envelope plus the five lifecycle
message types that may travel directly between the RL Orchestrator and any
participant (section 4/5): READY_CHECK, READY, START_EXPERIMENT,
STOP_EXPERIMENT, EXPERIMENT_FAILED.
- class marla.messaging.schemas.AdvisoryActionDescriptor(*, action_id, type, target=None, parameters=<factory>)[source]
Bases:
BaseModelThe Plan Maker’s view of a legal action: public fields only.
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class marla.messaging.schemas.AdvisoryObjective(*, type, description)[source]
Bases:
BaseModel- model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class marla.messaging.schemas.AdvisoryRequestPayload(*, schema_version, run_id, request_id, episode_id, step, source_observation_id, objective, observation, legal_actions)[source]
Bases:
BaseModel- Parameters:
- legal_actions: list[AdvisoryActionDescriptor]
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- objective: AdvisoryObjective
- class marla.messaging.schemas.AdvisoryResponsePayload(*, schema_version, run_id, request_id, scores, model_version, prompt_version, knowledge_version, inference_latency_ms, retrieved_rule_ids=<factory>)[source]
Bases:
BaseModel- Parameters:
- model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class marla.messaging.schemas.MessageMetadata(performative, message_type, schema_version, run_id, conversation_id, request_id, sender_alias, receiver_alias)[source]
Bases:
objectThe envelope fields required on every MARLA SPADE message.
- Parameters:
- message_type: MessageType
- class marla.messaging.schemas.MessageType(value)[source]
-
An enumeration.
- ADVISORY_REQUEST = 'ADVISORY_REQUEST'
- ADVISORY_RESPONSE = 'ADVISORY_RESPONSE'
- CORRECTION_REQUEST = 'CORRECTION_REQUEST'
- EXPERIMENT_FAILED = 'EXPERIMENT_FAILED'
- READY = 'READY'
- READY_CHECK = 'READY_CHECK'
- START_EXPERIMENT = 'START_EXPERIMENT'
- STOP_EXPERIMENT = 'STOP_EXPERIMENT'
- exception marla.messaging.schemas.MessageValidationError[source]
Bases:
ExceptionRaised when a received message’s envelope is missing or malformed.
Build SPADE messages carrying the MARLA envelope (spec section 10).
- marla.messaging.builders.build_message(to_jid, metadata, extra_metadata=None, payload=None)[source]
Build a SPADE
Messagewith the full MARLA envelope as metadata.payload, if given, is JSON-encoded into the message body; envelope fields always live in metadata, never in the body, so the Gatekeeper can validate correlation/routing without parsing JSON.The body is never left empty, even when there is no
payload: slixmpp only fires its generic"message"event (the one SPADE’s dispatcher listens on) for stanzas matchingmessage/body– a message that is all metadata and no body is silently never delivered to any behaviour, on any server, in-process or across a real connection."{}"is a harmless placeholder (valid, empty JSON) for messages that carry no payload, such as the READY_CHECK/READY/STOP_EXPERIMENT handshake.
Parse the MARLA envelope and JSON payload out of a received SPADE message.
- marla.messaging.parsers.parse_metadata(message)[source]
- Parameters:
message (spade.message.Message)
- Return type:
Gatekeeper-side advisory response validation (spec sections 9-10), SPADE-free.
Separated from the schema models themselves because “exact legal action-ID coverage” and “expected sender/request correlation” checks need context (the original request’s action IDs, the expected requester alias) that a standalone Pydantic model can’t carry. Kept independent of SPADE so it is directly unit-testable.
- exception marla.messaging.advisory_validation.AdvisoryValidationError(reason, detail='')[source]
Bases:
ExceptionA single reason an advisory response was rejected, matching spec section 10’s checklist.
- marla.messaging.advisory_validation.validate_advisory_response_body(raw_body, expected_run_id, expected_request_id, expected_action_ids)[source]
Validate a Plan Maker response body against its originating request’s context.
Raises
AdvisoryValidationErrorwith a specificreasonon the first failing check:invalid_schema,run_id_mismatch,request_id_mismatch, oraction_id_coverage_mismatch. Score numeric-type and[0,1]bound checks happen insideAdvisoryResponsePayloaditself and surface asinvalid_schema.