chore: Send user message to the agent that returned a corresponding function call if user message is a function response

PiperOrigin-RevId: 773895971
This commit is contained in:
Xiang (Sean) Zhou
2025-06-20 17:15:29 -07:00
committed by Copybara-Service
parent fb13963ded
commit 7c670f638b
2 changed files with 524 additions and 0 deletions
+43
View File
@@ -337,6 +337,8 @@ class Runner:
"""Finds the agent to run to continue the session.
A qualified agent must be either of:
- The agent that returned a function call and the last user message is a
function response to this function call.
- The root agent;
- An LlmAgent who replied last and is capable to transfer to any other agent
in the agent hierarchy.
@@ -348,6 +350,15 @@ class Runner:
Returns:
The agent of the last message in the session or the root agent.
"""
# If the last event is a function response, should send this response to
# the agent that returned the corressponding function call regardless the
# type of the agent. e.g. a remote a2a agent may surface a credential
# request as a special long running function tool call.
event = _find_function_call_event_if_last_event_is_function_response(
session
)
if event and event.author:
return root_agent.find_agent(event.author)
for event in filter(lambda e: e.author != 'user', reversed(session.events)):
if event.author == root_agent.name:
# Found root agent.
@@ -527,3 +538,35 @@ class InMemoryRunner(Runner):
session_service=self._in_memory_session_service,
memory_service=InMemoryMemoryService(),
)
def _find_function_call_event_if_last_event_is_function_response(
session: Session,
) -> Optional[Event]:
events = session.events
if not events:
return None
last_event = events[-1]
if (
last_event.content
and last_event.content.parts
and any(part.function_response for part in last_event.content.parts)
):
function_call_id = next(
part.function_response.id
for part in last_event.content.parts
if part.function_response
)
for i in range(len(events) - 2, -1, -1):
event = events[i]
# looking for the system long running request euc function call
function_calls = event.get_function_calls()
if not function_calls:
continue
for function_call in function_calls:
if function_call.id == function_call_id:
return event
return None