xr_ai_interaction#

Transport-neutral participant interaction messages for XR agents.

Classes#

Interrupted

Notification that participant-scoped or global work was interrupted.

ParticipantJoined

Notification that one participant joined the interaction.

ParticipantLeft

Notification that one participant left the interaction.

ResponseOutput

One complete response or one fragment of a streamed response.

UserQuery

One accepted user query from an input boundary such as voice or text.

Reply

Async context manager that publishes one reply, streamed or single.

ResponseOutputs

Publish replies and updates without building protocol messages.

Package Contents#

class xr_ai_interaction.Interrupted#

Notification that participant-scoped or global work was interrupted.

class xr_ai_interaction.ParticipantJoined#

Notification that one participant joined the interaction.

class xr_ai_interaction.ParticipantLeft#

Notification that one participant left the interaction.

class xr_ai_interaction.ResponseOutput#

One complete response or one fragment of a streamed response.

A producer declares what kind of output it emits; the consumer decides when and how to render it, for example as speech or text. A reply answers one request. An update is unprompted information. A withdraw carries no content: it asks the consumer to drop the updates this producer queued for the participant that have not started playing.

Without response_id, this is a complete standalone response. Otherwise, ordered messages with the same participant, producer, and response_id form one streamed reply: append each message’s text until final=True closes it. The final message may contain text or be an empty terminator.

This model validates individual messages, not stream state. Consumers own stream tracking and their duplicate-handling policy.

kind: Literal['reply', 'update', 'withdraw']#

reply answers request_id; update is unprompted information; withdraw drops this producer’s not-yet-played updates.

text: str = ''#

Complete response text or one streamed fragment.

request_id: str | None#

Request a reply answers. Required for replies and forbidden for updates.

urgent: bool = False#

Updates only: cut current output and play this update next.

response_id: str | None#

Identifier shared by the fragments of one streamed reply from one participant and producer.

final: bool = True#

Whether this message completes the response.

timestamp_us: int | None#

Optional originating input timestamp propagated to the consumer.

validate_boundary() → ResponseOutput#

Require identity for streamed replies and text for finite output.

class xr_ai_interaction.UserQuery#

One accepted user query from an input boundary such as voice or text.

text: str#

Gate-accepted speech or direct typed text.

timestamp_us: int#

Input presentation time as Unix microseconds.

class xr_ai_interaction.Reply(
outputs: ResponseOutputs,
participant_id: str,
*,
request_id: str,
timestamp_us: int | None = None,
started: collections.abc.Callable[[], collections.abc.Awaitable[None]] | None = None,
)#

Async context manager that publishes one reply, streamed or single.

Create it with ResponseOutputs.reply(). Every send() publishes one fragment of the reply, and leaving the context publishes the empty terminator that completes it. A single-message reply is one send.

  • Fragments that are blank before the first published fragment are skipped.

  • A canceled task never publishes: send raises asyncio.CancelledError when the current task is being canceled, even if the code it awaited swallowed the cancellation.

  • On exit, whether normal, by exception, or by cancellation, the terminator is published if any fragment was published and no publish failed. A failed publish is never retried or closed. Exceptions listed in the closed_errors of the ResponseOutputs are suppressed when they come from the terminator.

  • Calling send after the context exits raises RuntimeError.

property delivered: bool#

Whether the terminator was published; meaningful after the context exits.

async send(text: str) → None#

Publish one fragment of the reply.

class xr_ai_interaction.ResponseOutputs(
publisher: _Publisher,
topic: Any,
*,
source: str | None = None,
closed_errors: tuple[type[BaseException], Ellipsis] = (),
)#

Publish replies and updates without building protocol messages.

A producer declares what it emits. The consumer decides when it is rendered, so a producer never chooses interruption flags or stream identifiers.

Parameters:
  • publisher – Object with an async publish(topic, message, *, participant_id=...) method, such as AgentRuntime or RuntimeContext.

  • topic – Topic that carries ResponseOutput messages.

  • source – Producer name passed to publish as source. Omitted from the call when None.

  • closed_errors – Exception types that mean the consumer is already closed. Reply suppresses them when it publishes the terminator.

async update(
participant_id: str,
text: str,
*,
urgent: bool = False,
timestamp_us: int | None = None,
) → None#

Publish unprompted information; blank text publishes nothing.

An urgent update cuts the output being played and plays next.

Parameters:
  • participant_id – Participant that hears the update.

  • text – Update text.

  • urgent – Whether the update cuts current output and plays next.

  • timestamp_us – Originating input time as Unix microseconds.

async withdraw(participant_id: str) → None#

Drop this producer’s updates for a participant that have not started playing.

Output already playing and other producers’ updates are kept.

Parameters:

participant_id – Participant whose queued updates are dropped.

reply(
participant_id: str,
*,
request_id: str,
timestamp_us: int | None = None,
started: collections.abc.Callable[[], collections.abc.Awaitable[None]] | None = None,
) → Reply#

Return the context manager for one reply to request_id.

Parameters:
  • participant_id – Participant that hears the reply.

  • request_id – Request the reply answers.

  • timestamp_us – Originating input time as Unix microseconds.

  • started – Awaited once, before the first fragment is published.