Message Queue API¶
The message queue injects messages into a running agent — steering (delivered
before the next model request) or follow-up (delivered when the agent would
otherwise stop). Pass one via message_queue= on
create_deep_agent. See
Message queue (steering) for the overview.
MessageQueue¶
pydantic_deep.features.message_queue.MessageQueue
¶
Asyncio-safe dual-priority queue for mid-run message delivery.
Usage::
queue = MessageQueue()
agent = create_deep_agent(message_queue=queue)
# From another coroutine / task while the agent is running:
await queue.steer("stop that, try a different approach")
await queue.follow_up("when done, also summarise")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_pending
|
int | None
|
Cap on pending messages per priority. |
DEFAULT_MAX_PENDING
|
steer(content, *, delivery_mode='one_at_a_time', metadata=None)
async
¶
Queue a steering message (delivered before the next LLM call).
Raises:
| Type | Description |
|---|---|
QueueFullError
|
When |
follow_up(content, *, delivery_mode='one_at_a_time', metadata=None)
async
¶
Queue a follow-up message (delivered when the agent would otherwise stop).
Raises:
| Type | Description |
|---|---|
QueueFullError
|
When |
drain_steering()
async
¶
Return queued steering messages and remove them from the queue.
drain_follow_up()
async
¶
Return queued follow-up messages and remove them from the queue.
discard_follow_up(*, keep=None)
async
¶
Remove every pending follow-up and return the removed ones.
Messages for which keep returns True stay queued, in order. Callers use
this to prune follow-ups that a cancelled run made stale while sparing the
ones no longer tied to it — an externally submitted message was never about
the cancelled task, and dropping it reads to its sender as being ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keep
|
Callable[[QueuedMessage], bool] | None
|
Predicate deciding which pending messages survive. |
None
|
Returns:
| Type | Description |
|---|---|
list[QueuedMessage]
|
The messages removed from the queue, in submission order. |
has_follow_up()
¶
Return True if there are pending follow-up messages (without the lock, display only).
pending_count()
¶
Return (steering_count, follow_up_count) without the lock (display only).
MessageQueueCapability¶
pydantic_deep.features.message_queue.MessageQueueCapability
dataclass
¶
Bases: AbstractCapability[DeepAgentDeps]
Injects queued steering messages before each model request.
Register via create_deep_agent(message_queue=queue) or directly::
capability = MessageQueueCapability(queue=queue)
agent = Agent(model, capabilities=[capability])
run_with_queue¶
pydantic_deep.features.message_queue.run_with_queue(agent, prompt, *, deps, queue, message_history=None, **run_kwargs)
async
¶
Run an agent and re-enter the loop when follow-up messages arrive.
Steering messages are handled automatically by :class:MessageQueueCapability
(injected before each LLM request). Follow-up messages are consumed here
after each completed run, before the next iteration starts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
Agent[Any, Any]
|
The agent to run. |
required |
prompt
|
str
|
The initial user prompt. |
required |
deps
|
Any
|
Agent dependencies. |
required |
queue
|
MessageQueue
|
The shared |
required |
message_history
|
list[Any] | None
|
Existing conversation history (passed through to agent.run). |
None
|
**run_kwargs
|
Any
|
Extra keyword arguments forwarded to |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
The final :class: |
queued_source¶
pydantic_deep.features.message_queue.queued_source(message)
¶
Return the metadata["source"] label of message, or None when it has none.
The value is written by whoever enqueued the message and is interpolated into
the label the model reads, so it is reduced to word characters plus ., :
and - and truncated. A message with no source was submitted locally.
QueueFullError¶
pydantic_deep.features.message_queue.QueueFullError
¶
Bases: RuntimeError
Raised when a message cannot be queued because that priority is at capacity.
Enqueueing fails loudly rather than dropping: an external bridge needs to know a submission did not land so it can report that back to whoever sent it.