1+ # ruff: noqa
12import json
23import logging
34
@@ -39,9 +40,7 @@ async def generate_summary(self) -> str:
3940 client = genai .Client ()
4041 response = client .models .generate_content (
4142 model = 'gemini-2.0-flash' ,
42- contents = prompts .SUMMARY_COT_INSTRUCTIONS .replace (
43- '{travel_data}' , str (self .results )
44- ),
43+ contents = prompts .SUMMARY_COT_INSTRUCTIONS .replace ('{travel_data}' , str (self .results )),
4544 config = {'temperature' : 0.0 },
4645 )
4746 return response .text
@@ -51,9 +50,7 @@ def answer_user_question(self, question) -> str:
5150 client = genai .Client ()
5251 response = client .models .generate_content (
5352 model = 'gemini-2.0-flash' ,
54- contents = prompts .QA_COT_PROMPT .replace (
55- '{TRIP_CONTEXT}' , str (self .travel_context )
56- )
53+ contents = prompts .QA_COT_PROMPT .replace ('{TRIP_CONTEXT}' , str (self .travel_context ))
5754 .replace ('{CONVERSATION_HISTORY}' , str (self .query_history ))
5855 .replace ('{TRIP_QUESTION}' , question ),
5956 config = {
@@ -66,9 +63,7 @@ def answer_user_question(self, question) -> str:
6663 logger .info (f'Error answering user question: { e } ' )
6764 return '{"can_answer": "no", "answer": "Cannot answer based on provided context"}'
6865
69- def set_node_attributes (
70- self , node_id , task_id = None , context_id = None , query = None
71- ):
66+ def set_node_attributes (self , node_id , task_id = None , context_id = None , query = None ):
7267 attr_val = {}
7368 if task_id :
7469 attr_val ['task_id' ] = task_id
@@ -81,21 +76,23 @@ def set_node_attributes(
8176
8277 def add_graph_node (
8378 self ,
84- task_id ,
8579 context_id ,
8680 query : str ,
8781 node_id : str = None ,
8882 node_key : str = None ,
8983 node_label : str = None ,
9084 ) -> WorkflowNode :
91- """Add a node to the graph."""
92- node = WorkflowNode (
93- task = query , node_key = node_key , node_label = node_label
94- )
85+ """Add a node to the graph.
86+
87+ Child nodes must not inherit the orchestrator's task_id. A2A
88+ treats a present taskId as a resume of a task on the receiving
89+ agent, and the child has not created that task yet.
90+ """
91+ node = WorkflowNode (task = query , node_key = node_key , node_label = node_label )
9592 self .graph .add_node (node )
9693 if node_id :
9794 self .graph .add_edge (node_id , node .id )
98- self .set_node_attributes (node .id , task_id , context_id , query )
95+ self .set_node_attributes (node .id , context_id = context_id , query = query )
9996 return node
10097
10198 def clear_state (self ):
@@ -104,9 +101,7 @@ def clear_state(self):
104101 self .travel_context .clear ()
105102 self .query_history .clear ()
106103
107- async def stream (
108- self , query , context_id , task_id
109- ) -> AsyncIterable [dict [str , any ]]:
104+ async def stream (self , query , context_id , task_id ) -> AsyncIterable [dict [str , any ]]:
110105 """Execute and stream response."""
111106 logger .info (
112107 f'Running { self .agent_name } stream for session { context_id } , task { task_id } - { query } '
@@ -124,7 +119,6 @@ async def stream(
124119 if not self .graph :
125120 self .graph = WorkflowGraph ()
126121 planner_node = self .add_graph_node (
127- task_id = task_id ,
128122 context_id = context_id ,
129123 query = query ,
130124 node_key = 'planner' ,
@@ -138,59 +132,45 @@ async def stream(
138132
139133 # This loop can be avoided if the workflow graph is dynamic or
140134 # is built from the results of the planner when the planner
141- # iself is not a part of the graph.
135+ # itself is not a part of the graph.
142136 # TODO: Make the graph dynamically iterable over edges
143137 while True :
144- # Set attributes on the node so we propagate task and context
138+ # Propagate context only. Child task ids are stored on the
139+ # node from the child's stream and must not be overwritten
140+ # with the orchestrator's task_id.
145141 self .set_node_attributes (
146142 node_id = start_node_id ,
147- task_id = task_id ,
148143 context_id = context_id ,
149144 )
150145 # Resume workflow, used when the workflow nodes are updated.
151146 should_resume_workflow = False
152- async for chunk in self .graph .run_workflow (
153- start_node_id = start_node_id
154- ):
147+ async for chunk in self .graph .run_workflow (start_node_id = start_node_id ):
155148 if isinstance (chunk .root , SendStreamingMessageSuccessResponse ):
156- # The graph node retured TaskStatusUpdateEvent
149+ # The graph node returned TaskStatusUpdateEvent
157150 # Check if the node is complete and continue to the next node
158151 if isinstance (chunk .root .result , TaskStatusUpdateEvent ):
159152 task_status_event = chunk .root .result
160153 context_id = task_status_event .context_id
161- if (
162- task_status_event .status .state
163- == TaskState .completed
164- and context_id
165- ):
166- ## yeild??
154+ if task_status_event .status .state == TaskState .completed and context_id :
155+ ## yield??
167156 continue
168- if (
169- task_status_event .status .state
170- == TaskState .input_required
171- ):
172- question = task_status_event .status .message .parts [
173- 0
174- ].root .text
157+ if task_status_event .status .state == TaskState .input_required :
158+ question = task_status_event .status .message .parts [0 ].root .text
175159
176160 try :
177- answer = json .loads (
178- self .answer_user_question (question )
179- )
161+ answer = json .loads (self .answer_user_question (question ))
180162 logger .info (f'Agent Answer { answer } ' )
181163 if answer ['can_answer' ] == 'yes' :
182164 # Orchestrator can answer on behalf of the user set the query
183165 # Resume workflow from paused state.
184166 query = answer ['answer' ]
185167 start_node_id = self .graph .paused_node_id
186- self .set_node_attributes (
187- node_id = start_node_id , query = query
188- )
168+ self .set_node_attributes (node_id = start_node_id , query = query )
189169 should_resume_workflow = True
190170 except Exception :
191171 logger .info ('Cannot convert answer data' )
192172
193- # The graph node retured TaskArtifactUpdateEvent
173+ # The graph node returned TaskArtifactUpdateEvent
194174 # Store the node and continue.
195175 if isinstance (chunk .root .result , TaskArtifactUpdateEvent ):
196176 artifact = chunk .root .result .artifact
@@ -205,11 +185,8 @@ async def stream(
205185 )
206186 # Define the edges
207187 current_node_id = start_node_id
208- for idx , task_data in enumerate (
209- artifact_data ['tasks' ]
210- ):
188+ for idx , task_data in enumerate (artifact_data ['tasks' ]):
211189 node = self .add_graph_node (
212- task_id = task_id ,
213190 context_id = context_id ,
214191 query = task_data ['description' ],
215192 node_id = current_node_id ,
0 commit comments