diff --git a/a2a_agents/python/adk/samples/orchestrator/agent_executor.py b/a2a_agents/python/adk/samples/orchestrator/agent_executor.py index 0d053379c..366cbb0fd 100644 --- a/a2a_agents/python/adk/samples/orchestrator/agent_executor.py +++ b/a2a_agents/python/adk/samples/orchestrator/agent_executor.py @@ -14,6 +14,7 @@ import asyncio import logging +import json from typing import List, Optional, override from google.adk.agents.invocation_context import new_invocation_context_id from google.adk.events.event_actions import EventActions @@ -84,6 +85,20 @@ def convert_event_to_a2a_events_and_save_surface_id_to_subagent_name( ) for a2a_event in a2a_events: + # Try to populate subagent agent card if available. + subagent_card = None + if (active_subagent_name := event.author): + # We need to find the subagent by name + if (subagent := next((sub for sub in invocation_context.agent.sub_agents if sub.name == active_subagent_name), None)): + try: + subagent_card = json.loads(subagent.description) + except Exception: + logger.warning(f"Failed to parse agent description for {active_subagent_name}") + if subagent_card: + if a2a_event.metadata is None: + a2a_event.metadata = {} + a2a_event.metadata["a2a_subagent"] = subagent_card + for a2a_part in a2a_event.status.message.parts: if ( is_a2ui_part(a2a_part) diff --git a/samples/client/angular/projects/a2a-chat-canvas/src/lib/components/chat/message/message.html b/samples/client/angular/projects/a2a-chat-canvas/src/lib/components/chat/message/message.html index fbec4b619..3c30f5cc8 100644 --- a/samples/client/angular/projects/a2a-chat-canvas/src/lib/components/chat/message/message.html +++ b/samples/client/angular/projects/a2a-chat-canvas/src/lib/components/chat/message/message.html @@ -23,7 +23,7 @@ > @if (isRoleAgent(role)) { this.message().contents.filter((content) => containsAgentThought(content)), diff --git a/samples/client/angular/projects/a2a-chat-canvas/src/lib/services/chat-service.ts b/samples/client/angular/projects/a2a-chat-canvas/src/lib/services/chat-service.ts index c849594eb..27093c0da 100644 --- a/samples/client/angular/projects/a2a-chat-canvas/src/lib/services/chat-service.ts +++ b/samples/client/angular/projects/a2a-chat-canvas/src/lib/services/chat-service.ts @@ -17,7 +17,7 @@ import { AgentCard, SendMessageSuccessResponse } from '@a2a-js/sdk'; import { PART_RESOLVERS } from '@a2a_chat_canvas/a2a-renderer/tokens'; import { A2A_SERVICE } from '@a2a_chat_canvas/interfaces/a2a-service'; -import { UiMessage, UiMessageContent } from '@a2a_chat_canvas/types/ui-message'; +import { UiAgent, UiMessage, UiMessageContent } from '@a2a_chat_canvas/types/ui-message'; import { extractA2aPartsFromResponse } from '@a2a_chat_canvas/utils/a2a'; import { extractA2uiDataParts } from '@a2a_chat_canvas/utils/a2ui'; import { convertPartToUiMessageContent } from '@a2a_chat_canvas/utils/ui-message-utils'; @@ -148,6 +148,7 @@ export class ChatService { this.updateLastMessage((msg) => ({ ...msg, + role: this.createRole(response), contents: [...msg.contents, ...newContents], status: 'completed', lastUpdated: new Date().toISOString(), @@ -246,15 +247,36 @@ export class ChatService { type: 'ui_message', id: uuid(), contextId: this.contextId() ?? '', - role: { - type: 'ui_agent', - name: this.agentCard()?.name ?? 'Agent', - iconUrl: this.agentCard()?.iconUrl ?? 'gemini-color.svg', - }, + role: this.createRole(), contents: [], status: 'pending', created: nowTimestamp, lastUpdated: nowTimestamp, }; } + + /** + * Creates the agent role based on the agent card and the message response if available. + * + * @param response The reponse message received from the agent. + * @returns A new UiAgent object representing the agent that the user is chatting with. + */ + private createRole(response?: SendMessageSuccessResponse): UiAgent { + const rootagentRole: UiAgent = { + type: 'ui_agent', + name: this.agentCard()?.name ?? 'Agent', + iconUrl: this.agentCard()?.iconUrl ?? 'gemini-color.svg', + }; + + const subagentCard = response?.result?.metadata?.['a2a_subagent']; + if (!subagentCard) { + return rootagentRole; + } + const agentRole: UiAgent = { + ...rootagentRole, + subagentName: (subagentCard as AgentCard).name, + } + + return agentRole; + } } diff --git a/samples/client/angular/projects/a2a-chat-canvas/src/lib/types/ui-message.ts b/samples/client/angular/projects/a2a-chat-canvas/src/lib/types/ui-message.ts index c7bab2616..b17b8148a 100644 --- a/samples/client/angular/projects/a2a-chat-canvas/src/lib/types/ui-message.ts +++ b/samples/client/angular/projects/a2a-chat-canvas/src/lib/types/ui-message.ts @@ -35,6 +35,10 @@ export interface UiAgent { readonly name: string; /** The URL of the agent's icon. */ readonly iconUrl: string; + /** The display name of the sub-agent. */ + readonly subagentName?: string; + /** The URL of the sub-agent's icon. */ + readonly subagentIconUrl?: string; } /**