Delivery¶
Delivery Models¶
InboundMessage ¶
Bases: BaseModel
A message received from an external provider.
For stateful channels (voice, persistent WebSocket), set session
to the session object. After the hook pipeline passes,
process_inbound will call channel.connect_session() to bind
the long-lived session to the room.
InboundResult ¶
Bases: BaseModel
Result of processing an inbound message.
error carries a generation/transport failure raised while consuming the
intelligence channel's streaming response, so a headless caller (no
streaming target to render an error card) can observe it and react —
instead of the failure vanishing after ON_ERROR fires. None on
success. Interactive callers ignore it; the ON_ERROR hooks still fire.
response_metadata is the turn's own record, for the same reader and
the same reason. It also rides each MESSAGE segment the turn persisted,
but only segments that had text to carry: a turn ending on a tool call
persists nothing after it, so the room cannot be asked how such a turn
ended. The caller is handed the record instead of hunting for it, with
each replying channel's end under turns[channel_id]
(loop_end_reason, an ACP agent's stop reason, ai_usage).
duplicate
class-attribute
instance-attribute
¶
The event is a replay of an existing idempotency key, not a new turn.
unavailable_targets
class-attribute
instance-attribute
¶
Explicit addresses absent from the committed delivery plan.
Backfilled from execution by a deferred handle. None means no new plan was resolved (for example a duplicate); availability is not re-read on replay.
cancellation_reason
class-attribute
instance-attribute
¶
Terminal delivery cancellation reason; never changes the committed event.
Backfilled by a deferred handle's wait() or cancel() after cleanup.
An awaited process_inbound propagates the caller's own cancellation
(CancelledError) after draining; a turn cut from elsewhere (the
kit's close(), a lane that dropped the delivery) is returned
instead, its end under turns, as a deferred caller reads it (RFC
§10.1 step 18).
response_metadata
class-attribute
instance-attribute
¶
response_metadata = Field(default_factory=ResponseMetadata)
The turn's response-metadata record; empty when no turn ran.
response_events
class-attribute
instance-attribute
¶
Persisted, delivered response events belonging to this call's cascade.
Contains reentry responses and streamed segments, excluding the original
inbound, blocked events and unrelated turns in the same room. A consumer
reads this collection to attribute an answer to its call; a timeline read
after the inbound index can include a later or concurrent call's answer.
Deferred callers must await delivery.wait() for the complete collection.
Events retain their stored indices, visibility and post-hook content.
delivery_results
class-attribute
instance-attribute
¶
Per-channel outcome of this event's delivery set, keyed by channel id
(RFC §10.1 step 18). process_inbound waits for that set to complete, so
this is populated by the time it returns — for the caller's own event only,
never for a reentry's, which is a separate event with its own result. A
deferred call returns before the set executes: there it is backfilled by
delivery.wait() instead.
delivery
class-attribute
instance-attribute
¶
Set only by process_inbound(..., defer_delivery=True): the handle
on the in-flight delivery (RFC §10.1 step 18 detached completion). None
on the waiting path, where the result already reports the completed set —
and on a deferred call refused before the locked region (rate limited,
pre-commit timeout, identity block), which has no delivery to follow.
Whenever blocked is False the handle is there; a hook refusal,
decided inside the locked region, gets one too (its near-empty cascade
resolves at once).
report_cascade ¶
Report what the caller's completed cascade delivered (RFC §10.1 step 18): its delivery set, the answers it committed, its record, and its error or cancellation unless the result already names an error.
The one report of a cascade, whichever call waited for it: an inbound event, a deferred delivery's handle, a regeneration.
DeliveryHandle ¶
A deferred caller's grip on its in-flight delivery (RFC §10.1 step 18).
process_inbound(..., defer_delivery=True) returns at the commit; this
handle, on :attr:InboundResult.delivery, is what remains of step 18:
the event's delivery set, the reentry passes it transitively spawns (an
AI reply included) and the consumption of streamed responses, all running
in the room's delivery lane. wait() resolves once that whole tail has
run — not merely the cascade, because a streamed reply is only generated
while its stream is consumed, which starts after the cascade completes.
The cascade is structurally typed (:class:_CascadeLike): models do not
import from :mod:roomkit.core.
done
property
¶
Whether the deferred delivery will make no further progress.
True once the turn finished — but also for a consumer cancelled by
close(), where the turn was abandoned mid-flight: this reports
"nothing more will happen", not "everything ran". wait()'s
backfill is where the two read differently.
cancel
async
¶
Cancel this turn and drain its tools, generation and streams.
Returns the original result with cancellation_reason set. Already
committed events remain stored. Other turns and shared providers are
unaffected. Repeated calls are safe and preserve the first reason.
TimeoutError means cleanup is STILL running: retain the resources
it uses and await this handle before disposing them. Cancellation of
this call is propagated only after cleanup (or its timeout). Calling
from the room's lane or under its lock raises RuntimeError.
A completed handle is returned unchanged.
wait
async
¶
Wait for the deferred delivery to complete, then report it.
Backfills delivery_results, error and response_metadata on
the result this handle belongs to — after this the result reads exactly
like a non-deferred call's — and returns that result. A
consumer cancelled by close() resolves the wait too, with whatever
the cascade recorded by then.
Called from a context that must not wait on this room's delivery — the room's own lane executor (a tool handler) or under the room lock (a sync hook), where the lane cannot progress past the caller — it returns the result immediately, unwaited and un-backfilled: the same short-circuit the waiting path's step 18 applies, with delivery following in lane order.
DeliveryOutcome ¶
Bases: BaseModel
Outcome of a proactive RoomKit.deliver() request (RFC §22).
sent means publication or provider acceptance, not agent completion.
inbound exposes the text turn's existing result/handle, in-process only.
A duplicate identifies an earlier publication without replaying its turn.
Keyed realtime injections reuse their recorded per-session outcomes.
session_outcomes
class-attribute
instance-attribute
¶
Per-session voice outcomes; child outcomes have no nested session outcomes.
VoiceDeliveryRecord ¶
Bases: BaseModel
One reserved injection, retained until its room is deleted.
An absent outcome means unresolved submission, never permission to retry.
attempt_id fences completion from previous owners. Only a recorded
retryable failure known to precede submission can be claimed again.
VoiceInjectionResult ¶
Bases: BaseModel
Report what the provider knows after inject_text.
sent means its send operation completed, not that audio was heard.
not_sent guarantees no submission or pending submission exists.
unknown covers acceptance that cannot be established, including input
queued locally for later sending. Only not_sent may allow retry.
Exceptions and None returns are conservatively unknown.
DeliveryResult ¶
Bases: BaseModel
The outcome of delivering one event to one channel (RFC §5.13).
ProviderResult ¶
Bases: BaseModel
Result from a provider delivery attempt.
Delivery Strategies¶
DeliveryStrategy ¶
Bases: ABC
Controls when content is delivered; report its actual outcome.
deliver
abstractmethod
async
¶
Deliver the request. A custom strategy may leave its outcome unknown.
Immediate ¶
Bases: DeliveryStrategy
Send now. On a voice session, it plays once the playback under way has been sent whole: a response never cuts the agent off (RFC §12.2).
WaitForIdle ¶
Queued ¶
Bases: DeliveryStrategy
Batch compatible unkeyed requests at idle; preserve each caller's outcome.
Keyed requests publish individually, including duplicate keys. One caller owns the drain; followers wait for their own request to be processed.
Delivery Backend¶
DeliveryBackend ¶
Bases: ABC
ABC for persistent delivery queue backends.
Implementations provide a durable queue with at-least-once
semantics via the enqueue / dequeue / ack / nack
lifecycle.
dequeue
abstractmethod
async
¶
Claim up to batch_size items. Blocks up to timeout seconds.
ack
abstractmethod
async
¶
Consume a terminal item (sent, blocked or unknown); removes it.
nack
abstractmethod
async
¶
Negative-acknowledge. Re-enqueues or dead-letters the item.
An item with retries left is attempted again after
:func:retry_delay, not at once: a destination that is briefly
unreachable (a voice session reconnecting) would otherwise spend
every retry within milliseconds.
dead_letter
abstractmethod
async
¶
Move an item to the dead-letter queue.
get_queue_depth
abstractmethod
async
¶
Return the number of pending items (observability).
get_dead_letter_items
abstractmethod
async
¶
Return up to limit items of the dead-letter queue, the most recently dead-lettered first.
DeliveryItem ¶
Bases: BaseModel
Serializable delivery request — the unit of work in the queue.
max_retries
class-attribute
instance-attribute
¶
Retries after the first attempt, as a binding's RetryPolicy counts
them (RFC §13.2): 3 means four attempts at most.
DeliveryItemStatus ¶
Bases: StrEnum
Lifecycle status of a delivery item.
InMemoryDeliveryBackend ¶
InMemoryDeliveryBackend(max_queue_size=1000, max_dead_letter_size=1000, *, retry_delay=1.0, max_retry_delay=60.0)
Bases: DeliveryBackend
Asyncio-queue-based delivery backend (single process, no persistence).
Items flow through _queue → _in_flight → acked/dead-lettered;
a nacked item with retries left waits in _delayed before it is queued
again. A background worker task drains the queue and executes deliveries.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_queue_size
|
int
|
Bound on the queue. |
1000
|
max_dead_letter_size
|
int
|
Bound on the dead-letter queue (oldest dropped). |
1000
|
retry_delay
|
float
|
Seconds before the first retry; each next one waits twice as long, up to max_retry_delay. 0 retries at once. |
1.0
|
max_retry_delay
|
float
|
Cap on the wait before a retry. |
60.0
|