1919from agentex .types .text_content_param import TextContentParam
2020
2121
22+ def _task_message_poll_sort_key (message : TaskMessage ) -> tuple [int , datetime ]:
23+ """Order messages within one poll so tool lifecycle rows precede other content.
24+
25+ Streaming assistant ``text`` rows are often created before ``tool_request`` /
26+ ``tool_response`` rows from the same model turn (earlier ``created_at``). Sorting
27+ only by ``created_at`` makes consumers that ``break`` on DONE agent text exit the
28+ poll generator before tool rows in the same ``list()`` batch are yielded.
29+ """
30+ ts = message .created_at if message .created_at else datetime .min .replace (tzinfo = timezone .utc )
31+ ctype = getattr (message .content , "type" , None ) if message .content else None
32+ phase = 0 if ctype in ("tool_request" , "tool_response" ) else 1
33+ return (phase , ts )
34+
35+
2236async def send_event_and_poll_yielding (
2337 client : AsyncAgentex ,
2438 agent_id : str ,
@@ -90,7 +104,11 @@ async def poll_messages(
90104 If False, only yield each message ID once (default: False)
91105
92106 Yields:
93- TaskMessage objects as they are discovered or updated
107+ TaskMessage objects as they are discovered or updated.
108+
109+ Within each poll, ``tool_request`` and ``tool_response`` messages are yielded before
110+ other types (when present in the same batch), so streaming tests can stop on DONE
111+ agent text without missing tool lifecycle rows.
94112 """
95113 # Keep track of messages we've already yielded
96114 seen_message_ids = set ()
@@ -102,12 +120,9 @@ async def poll_messages(
102120 while (datetime .now () - start_time ).seconds < timeout :
103121 messages = await client .messages .list (task_id = task_id )
104122
105- # Sort messages by created_at to ensure chronological order
106- # Use datetime.min for messages without created_at timestamp
107- sorted_messages = sorted (
108- messages ,
109- key = lambda m : m .created_at if m .created_at else datetime .min .replace (tzinfo = timezone .utc )
110- )
123+ # Sort so tool_request / tool_response appear before agent text in the same poll;
124+ # then by created_at (see _task_message_poll_sort_key).
125+ sorted_messages = sorted (messages , key = _task_message_poll_sort_key )
111126
112127 new_messages_found = 0
113128 for message in sorted_messages :
0 commit comments