Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
35 changes: 31 additions & 4 deletions samples/python/agents/helloworld/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,42 @@

Hello World example agent that only returns Message events

## Getting started
## Running the Agent

1. Start the server
This agent can be run with several command-line flags to demonstrate different agent card features.

#### 1. Start the server

To start the server with a basic, static card (the default behavior), run:

```bash
uv run .
uv run __main__.py
```

2. Run the test client
#### 2. Run with different card configurations

You can control the agent card's features using the following flags:

* `--dynamic-public-card`: Enables a dynamic public-facing card. The card's description will include a timestamp to show it's generated on each request.
* `--enable-extended-card`: Enables support for an extended card for authenticated users. This adds the `super_hello_world` skill.
* `--dynamic-extended-card`: Makes the extended card dynamic. This requires `--enable-extended-card` to be set.

**Examples:**

* Run with a dynamic public card:
```bash
uv run __main__.py --dynamic-public-card
```
* Run with a static extended card:
```bash
uv run __main__.py --enable-extended-card
```
* Run with both a dynamic public card and a dynamic extended card:
```bash
uv run __main__.py --dynamic-public-card --enable-extended-card --dynamic-extended-card
```

## Testing the Agent

```bash
uv run test_client.py
Expand Down
153 changes: 122 additions & 31 deletions samples/python/agents/helloworld/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import datetime

import click
import uvicorn

from a2a.server.agent_execution import RequestContext
from a2a.server.apps import A2AStarletteApplication
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.tasks import InMemoryTaskStore
Expand All @@ -13,26 +17,94 @@
)


if __name__ == '__main__':
# --8<-- [start:AgentSkill]
skill = AgentSkill(
id='hello_world',
name='Returns hello world',
description='just returns hello world',
tags=['hello world'],
examples=['hi', 'hello world'],
)
# --8<-- [end:AgentSkill]
def create_dynamic_public_card(base_card: AgentCard) -> AgentCard:
"""Dynamically modifies the public agent card.
This function is called for each request to the public card endpoint.
It can be used to add dynamic information, like a timestamp.
Args:
base_card: The base agent card to use as a template.
Returns:
A new, dynamically generated AgentCard.
"""
# Start with a copy of the base card to avoid modifying the original
public_card = base_card.model_copy(deep=True)
now = datetime.datetime.now(datetime.timezone.utc).isoformat()
# Set the description directly to make the function more robust.
# This avoids depending on the description from the base_card.
public_card.description = f'Just a hello world agent (last updated: {now})'
return public_card


def create_dynamic_extended_card(
base_card: AgentCard, context: RequestContext
) -> AgentCard:
"""Dynamically creates an extended agent card from a base card.
This function is called for each request to the extended card endpoint,
allowing the card to be customized based on the request context, such as
authentication headers.
Args:
base_card: The public agent card to use as a template.
context: The server call context, containing request information.
Returns:
A new, dynamically generated AgentCard.
"""
# Start with a copy of the base card to avoid modifying the original
extended_card = base_card.model_copy(deep=True)

# Add the extended skill that is always present for authenticated users
extended_skill = AgentSkill(
id='super_hello_world',
name='Returns a SUPER Hello World',
description='A more enthusiastic greeting, only for authenticated users.',
tags=['hello world', 'super', 'extended'],
examples=['super hi', 'give me a super hello'],
)
extended_card.skills.append(extended_skill)

# Update basic properties for the extended card
extended_card.name = 'Hello World Agent - Extended Edition'
extended_card.description = (
'The full-featured hello world agent for authenticated users.'
)
extended_card.version = '1.0.1'

return extended_card


@click.command()
@click.option(
'--dynamic-public-card',
is_flag=True,
default=False,
help='Enable dynamic public agent card.',
)
@click.option(
'--enable-extended-card',
is_flag=True,
default=False,
help='Enable support for an extended agent card.',
)
@click.option(
'--dynamic-extended-card',
is_flag=True,
default=False,
help='Make the extended agent card dynamic (requires --enable-extended-card).',
)
def main(dynamic_public_card, enable_extended_card, dynamic_extended_card):
skill = AgentSkill(
id='hello_world',
name='Returns hello world',
description='just returns hello world',
tags=['hello world'],
examples=['hi', 'hello world'],
)

# --8<-- [start:AgentCard]
# This will be the public-facing agent card
public_agent_card = AgentCard(
name='Hello World Agent',
Expand All @@ -42,36 +114,55 @@
default_input_modes=['text'],
default_output_modes=['text'],
capabilities=AgentCapabilities(streaming=True),
skills=[skill], # Only the basic skill for the public card
supports_authenticated_extended_card=True,
)
# --8<-- [end:AgentCard]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add these region tags back, they are used in the public tutorial https://a2a-protocol.org/latest/tutorials/python/3-agent-skills-and-card/#agent-skills


# This will be the authenticated extended agent card
# It includes the additional 'extended_skill'
specific_extended_agent_card = public_agent_card.model_copy(
update={
'name': 'Hello World Agent - Extended Edition', # Different name for clarity
'description': 'The full-featured hello world agent for authenticated users.',
'version': '1.0.1', # Could even be a different version
# Capabilities and other fields like url, default_input_modes, default_output_modes,
# supports_authenticated_extended_card are inherited from public_agent_card unless specified here.
'skills': [
skill,
extended_skill,
], # Both skills for the extended card
}
skills=[skill],
supports_authenticated_extended_card=enable_extended_card,
)

request_handler = DefaultRequestHandler(
agent_executor=HelloWorldAgentExecutor(),
task_store=InMemoryTaskStore(),
)

card_modifier_func = (
create_dynamic_public_card if dynamic_public_card else None
)
extended_card_modifier_func = None
static_extended_card = None

if enable_extended_card:
if dynamic_extended_card:
extended_card_modifier_func = create_dynamic_extended_card
else:
# Create a static extended card if dynamic is not requested
extended_skill = AgentSkill(
id='super_hello_world',
name='Returns a SUPER Hello World',
description='A more enthusiastic greeting, only for authenticated users.',
tags=['hello world', 'super', 'extended'],
examples=['super hi', 'give me a super hello'],
)
static_extended_card = public_agent_card.model_copy(
update={
'name': 'Hello World Agent - Extended Edition',
'description': 'The full-featured hello world agent for authenticated users.',
'version': '1.0.1',
'skills': [
skill,
extended_skill,
],
}
)

server = A2AStarletteApplication(
agent_card=public_agent_card,
http_handler=request_handler,
extended_agent_card=specific_extended_agent_card,
card_modifier=card_modifier_func,
extended_agent_card=static_extended_card,
extended_card_modifier=extended_card_modifier_func,
)

uvicorn.run(server.build(), host='0.0.0.0', port=9999)


if __name__ == '__main__':
main()
1 change: 0 additions & 1 deletion samples/python/agents/helloworld/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ requires-python = ">=3.10"
dependencies = [
"a2a-sdk>=0.2.16",
"click>=8.1.8",
"dotenv>=0.9.9",
"httpx>=0.28.1",
"langchain-google-genai>=2.1.4",
"langgraph>=0.4.1",
Expand Down
Loading