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
15 changes: 8 additions & 7 deletions src/google/adk/a2a/utils/agent_card_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,20 +350,20 @@ def _build_agent_description(agent: BaseNode) -> str:


def _build_llm_agent_description_with_instructions(agent: LlmAgent) -> str:
"""Build agent description including instructions for LlmAgents."""
"""Build agent description including static instructions for LlmAgents."""
description_parts = []

# Add agent description
if agent.description:
description_parts.append(agent.description)

# Add instruction (with pronoun replacement) - only for LlmAgent
if agent.instruction:
# Instruction providers require runtime context, which is unavailable while
# building a static agent card.
if isinstance(agent.instruction, str) and agent.instruction:
instruction = _replace_pronouns(agent.instruction)
description_parts.append(instruction)

# Add global instruction (with pronoun replacement) - only for LlmAgent
if agent.global_instruction:
if isinstance(agent.global_instruction, str) and agent.global_instruction:
global_instruction = _replace_pronouns(agent.global_instruction)
description_parts.append(global_instruction)

Expand Down Expand Up @@ -551,8 +551,9 @@ async def _extract_examples_from_agent(
except Exception as e:
logger.warning('Failed to extract examples from tools: %s', e)

# If no example_tool found, try to extract examples from instruction
if agent.instruction:
# Dynamic instructions need runtime context and cannot provide static
# examples for an agent card.
if isinstance(agent.instruction, str) and agent.instruction:
return _extract_examples_from_instruction(agent.instruction)

return None
Expand Down
51 changes: 51 additions & 0 deletions tests/unittests/a2a/utils/test_agent_card_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from unittest.mock import AsyncMock
from unittest.mock import Mock
from unittest.mock import patch

Expand Down Expand Up @@ -322,6 +323,56 @@ async def test_build_succeeds_for_llm_agent(self):
skill_ids = [skill.id for skill in card.skills]
assert "writer" in skill_ids

async def test_build_omits_sync_instruction_provider(self):
"""A static card omits a sync instruction that needs runtime context."""
instruction_provider = Mock(return_value="You use runtime context.")
agent = LlmAgent(
name="provider_agent",
description="Uses runtime instructions.",
instruction=instruction_provider,
)

card = await AgentCardBuilder(agent=agent).build()

assert card.skills[0].description == "Uses runtime instructions."
instruction_provider.assert_not_called()

async def test_build_omits_async_instruction_provider(self):
"""A static card omits an async instruction that needs runtime context."""
instruction_provider = AsyncMock(
return_value="You use async runtime context."
)
agent = LlmAgent(
name="async_provider_agent",
description="Uses async runtime instructions.",
instruction=instruction_provider,
)

card = await AgentCardBuilder(agent=agent).build()

assert card.skills[0].description == "Uses async runtime instructions."
instruction_provider.assert_not_called()

async def test_build_omits_global_instruction_provider(self):
"""A static card omits a global instruction that needs runtime context."""
global_instruction_provider = Mock(
return_value="You use global runtime context."
)
agent = LlmAgent(
name="global_provider_agent",
description="Answers questions.",
instruction="You answer user questions.",
global_instruction=global_instruction_provider,
)

card = await AgentCardBuilder(agent=agent).build()

assert (
card.skills[0].description
== "Answers questions. I answer user questions."
)
global_instruction_provider.assert_not_called()

async def test_build_succeeds_for_workflow_with_llm_agent_node(self):
"""AgentCardBuilder.build succeeds for a Workflow (no sub_agents)."""
writer = LlmAgent(
Expand Down