Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions src/google/adk/a2a/utils/agent_card_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async def _build_llm_agent_skills(agent: LlmAgent) -> List[AgentSkill]:
id=agent.name,
name='model',
description=agent_description,
examples=agent_examples,
examples=_extract_inputs_from_examples(agent_examples),
input_modes=_get_input_modes(agent),
output_modes=_get_output_modes(agent),
tags=['llm'],
Expand Down Expand Up @@ -239,7 +239,7 @@ async def _build_non_llm_agent_skills(agent: BaseAgent) -> List[AgentSkill]:
id=agent.name,
name=agent_name,
description=agent_description,
examples=agent_examples,
examples=_extract_inputs_from_examples(agent_examples),
input_modes=_get_input_modes(agent),
output_modes=_get_output_modes(agent),
tags=[agent_type],
Expand Down Expand Up @@ -350,6 +350,7 @@ def _build_llm_agent_description_with_instructions(agent: LlmAgent) -> str:

def _replace_pronouns(text: str) -> str:
"""Replace pronouns and conjugate common verbs for agent description.

(e.g., "You are" -> "I am", "your" -> "my").
"""
pronoun_map = {
Expand Down Expand Up @@ -460,6 +461,33 @@ def _get_default_description(agent: BaseAgent) -> str:
return 'A custom agent'


def _extract_inputs_from_examples(examples: Optional[list[dict]]) -> list[str]:
"""Extracts only the input strings so they can be added to an AgentSkill."""
if examples is None:
return []

extracted_inputs = []
for example in examples:
example_input = example.get('input')
if not example_input:
continue

parts = example_input.get('parts')
if parts is not None:
part_texts = []
for part in parts:
text = part.get('text')
if text is not None:
part_texts.append(text)
extracted_inputs.append('\n'.join(part_texts))
else:
text = example_input.get('text')
if text is not None:
extracted_inputs.append(text)

return extracted_inputs


async def _extract_examples_from_agent(
agent: BaseAgent,
) -> Optional[List[Dict]]:
Expand Down
72 changes: 72 additions & 0 deletions tests/unittests/a2a/utils/test_agent_card_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from google.adk.a2a.utils.agent_card_builder import _build_sequential_description
from google.adk.a2a.utils.agent_card_builder import _convert_example_tool_examples
from google.adk.a2a.utils.agent_card_builder import _extract_examples_from_instruction
from google.adk.a2a.utils.agent_card_builder import _extract_inputs_from_examples
from google.adk.a2a.utils.agent_card_builder import _get_agent_skill_name
from google.adk.a2a.utils.agent_card_builder import _get_agent_type
from google.adk.a2a.utils.agent_card_builder import _get_default_description
Expand All @@ -41,6 +42,7 @@
from google.adk.agents.loop_agent import LoopAgent
from google.adk.agents.parallel_agent import ParallelAgent
from google.adk.agents.sequential_agent import SequentialAgent
from google.adk.examples import Example
from google.adk.tools.example_tool import ExampleTool
import pytest

Expand Down Expand Up @@ -1100,3 +1102,73 @@ def test_extract_examples_from_instruction_odd_number_of_matches(self):
assert len(result) == 1 # Only complete pairs should be included
assert result[0]["input"] == {"text": "What is the weather?"}
assert result[0]["output"] == [{"text": "What time is it?"}]

def test_extract_inputs_from_examples_from_plain_text_input(self):
"""Test _extract_inputs_from_examples on plain text as input."""
# Arrange
examples = [
{
"input": {"text": "What is the weather?"},
"output": [{"text": "What time is it?"}],
},
{
"input": {"text": "The weather is sunny."},
"output": [{"text": "It is 3 PM."}],
},
]

# Act
result = _extract_inputs_from_examples(examples)

# Assert
assert len(result) == 2
assert result[0] == "What is the weather?"
assert result[1] == "The weather is sunny."

def test_extract_inputs_from_examples_from_example_tool(self):
"""Test _extract_inputs_from_examples as extracted from ExampleTool."""

# Arrange
# This is what would be extracted from an ExampleTool
examples = [
{
"input": {
"role": "user",
"parts": [{"text": "What is the weather?"}],
},
"output": [
{
"role": "model",
"parts": [{"text": "What time is it?"}],
},
],
},
{
"input": {
"role": "user",
"parts": [{"text": "The weather is sunny."}],
},
"output": [
{
"role": "model",
"parts": [{"text": "It is 3 PM."}],
},
],
},
]

# Act
result = _extract_inputs_from_examples(examples)

# Assert
assert len(result) == 2
assert result[0] == "What is the weather?"
assert result[1] == "The weather is sunny."

def test_extract_inputs_from_examples_none_input(self):
"""Test _extract_inputs_from_examples on None as input."""
# Act
result = _extract_inputs_from_examples(None)

# Assert
assert len(result) == 0
Loading