1212import json
1313import logging
1414import mimetypes
15+ import uuid
1516from typing import Any , Literal
1617
1718from a2a .server .agent_execution import AgentExecutor , RequestContext
1819from a2a .server .events import EventQueue
1920from a2a .server .tasks import TaskUpdater
20- from a2a .types import DataPart , FilePart , InternalError , Part , TaskState , TextPart , UnsupportedOperationError
21- from a2a .utils import new_agent_text_message , new_task
21+ from a2a .types import DataPart , FilePart , InternalError , Part , TextPart , UnsupportedOperationError
22+ from a2a .utils import new_task
2223from a2a .utils .errors import ServerError
2324
2425from ...agent .agent import Agent as SAAgent
@@ -104,12 +105,18 @@ async def _execute_streaming(self, context: RequestContext, updater: TaskUpdater
104105 else :
105106 raise ValueError ("No content blocks available" )
106107
108+ self ._current_artifact_id = str (uuid .uuid4 ())
109+ self ._is_first_chunk = True
110+
107111 try :
108112 async for event in self .agent .stream_async (content_blocks ):
109113 await self ._handle_streaming_event (event , updater )
110114 except Exception :
111115 logger .exception ("Error in streaming execution" )
112116 raise
117+ finally :
118+ self ._current_artifact_id = None
119+ self ._is_first_chunk = True
113120
114121 async def _handle_streaming_event (self , event : dict [str , Any ], updater : TaskUpdater ) -> None :
115122 """Handle a single streaming event from the Strands Agent.
@@ -125,31 +132,42 @@ async def _handle_streaming_event(self, event: dict[str, Any], updater: TaskUpda
125132 logger .debug ("Streaming event: %s" , event )
126133 if "data" in event :
127134 if text_content := event ["data" ]:
128- await updater .update_status (
129- TaskState .working ,
130- new_agent_text_message (
131- text_content ,
132- updater .context_id ,
133- updater .task_id ,
134- ),
135+ await updater .add_artifact (
136+ [Part (root = TextPart (text = text_content ))],
137+ artifact_id = self ._current_artifact_id ,
138+ name = "agent_response" ,
139+ append = not self ._is_first_chunk ,
135140 )
141+ self ._is_first_chunk = False
136142 elif "result" in event :
137143 await self ._handle_agent_result (event ["result" ], updater )
138144
139145 async def _handle_agent_result (self , result : SAAgentResult | None , updater : TaskUpdater ) -> None :
140146 """Handle the final result from the Strands Agent.
141147
142- Processes the agent's final result, extracts text content from the response,
143- and adds it as an artifact to the task before marking the task as complete .
148+ Sends the final artifact chunk marker and marks the task as complete.
149+ If no data chunks were previously sent, includes the result content .
144150
145151 Args:
146152 result: The agent result object containing the final response, or None if no result.
147153 updater: The task updater for managing task state and adding the final artifact.
148154 """
149- if final_content := str (result ):
155+ if self ._is_first_chunk :
156+ final_content = str (result ) if result else ""
157+ parts = [Part (root = TextPart (text = final_content ))] if final_content else []
158+ await updater .add_artifact (
159+ parts ,
160+ artifact_id = self ._current_artifact_id ,
161+ name = "agent_response" ,
162+ last_chunk = True ,
163+ )
164+ else :
150165 await updater .add_artifact (
151- [Part (root = TextPart (text = final_content ))],
166+ [],
167+ artifact_id = self ._current_artifact_id ,
152168 name = "agent_response" ,
169+ append = True ,
170+ last_chunk = True ,
153171 )
154172 await updater .complete ()
155173
0 commit comments