Skip to content

Commit d892446

Browse files
fix(sample): fix beginner case a2a sample
fix beginner case a2a sample
2 parents 5424417 + 62b9262 commit d892446

File tree

4 files changed

+94
-23
lines changed

4 files changed

+94
-23
lines changed

02-use-cases/beginner/a2a_simple/README.md

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,31 @@
1515
## 🏗️ 架构
1616

1717
```
18+
方式一:直接客户端调用
1819
本地客户端 (local_client.py)
1920
2021
A2A 协议 (HTTP/JSONRPC)
2122
22-
远程 Agent 服务 (remote/agent.py)
23+
远程 Agent 服务 (remote/agent.py:8001)
2324
├── roll_die 工具 (投掷骰子)
2425
│ └── 状态管理:rolls 历史
2526
2627
└── check_prime 工具 (检查质数)
28+
29+
方式二:Agent 级联调用
30+
本地 Agent (agent.py:8000)
31+
├── add 工具 (加法)
32+
└── RemoteVeAgent → 远程 Agent 服务 (remote/agent.py:8001)
33+
├── roll_die 工具 (投掷骰子)
34+
└── check_prime 工具 (检查质数)
2735
```
2836

2937
### 核心组件
3038

3139
| 组件 | 描述 |
3240
|-----------|-------------|
33-
| **远程 Agent** | [remote/agent.py](remote/agent.py:14-40) - hello_world_agent,提供工具服务 |
41+
| **远程 Agent** | [remote/agent.py](remote/agent.py:14-40) - hello_world_agent,提供工具服务(端口 8001) |
42+
| **本地 Agent** | [agent.py](agent.py:16-21) - a2a_sample_agent,具有 add 工具和 sub_agents(端口 8000) |
3443
| **本地客户端** | [local_client.py](local_client.py) - A2ASimpleClient,调用远程服务 |
3544
| **工具:roll_die** | [remote/tools/roll_die.py](remote/tools/roll_die.py) - 投掷骰子 |
3645
| **工具:check_prime** | [remote/tools/check_prime.py](remote/tools/check_prime.py) - 检查质数 |
@@ -39,6 +48,16 @@ A2A 协议 (HTTP/JSONRPC)
3948

4049
### 代码特点
4150

51+
**本地 Agent 定义**[agent.py](agent.py:16-21)):
52+
```python
53+
agent = Agent(
54+
name="a2a_sample_agent",
55+
instruction="You are a helpful assistant that can add numbers and delegate tasks to a remote agent that can roll dice and check prime numbers.",
56+
tools=[add],
57+
sub_agents=[remote_agent],
58+
)
59+
```
60+
4261
**远程 Agent 定义**[remote/agent.py](remote/agent.py:14-40)):
4362
```python
4463
root_agent = Agent(
@@ -67,7 +86,7 @@ agent_card = AgentCard(
6786
defaultOutputModes=["text"],
6887
provider=AgentProvider(organization="agentkit", url=""),
6988
skills=[AgentSkill(id="0", name="chat", description="Chat", tags=["chat"])],
70-
url="0.0.0.0",
89+
url="http://localhost:8001",
7190
version="1.0.0",
7291
)
7392
```
@@ -208,6 +227,20 @@ cd 02-use-cases/beginner/a2a_simple
208227
python local_client.py
209228
```
210229

230+
**步骤 3(可选):启动本地 Agent 服务**
231+
```bash
232+
# 在终端窗口 3 中运行(需要先启动远程 Agent)
233+
cd 02-use-cases/beginner/a2a_simple
234+
python agent.py
235+
236+
# 服务启动后,可访问 Agent Card
237+
# http://localhost:8000/.well-known/agent-card.json
238+
```
239+
240+
此时您有两个 Agent 服务:
241+
- **远程 Agent**(端口 8001):提供 roll_die 和 check_prime 工具
242+
- **本地 Agent**(端口 8000):提供 add 工具,并可调用远程 Agent
243+
211244
#### 方式四:部署到火山引擎 veFaaS
212245

213246
**安全提示**
@@ -293,9 +326,10 @@ No prime numbers found.
293326

294327
```
295328
a2a_simple/
329+
├── agent.py # 本地 Agent 服务(端口 8000,可调用远程 Agent)
296330
├── local_client.py # A2A 客户端实现
297331
├── remote/ # 远程 Agent 服务
298-
│ ├── agent.py # Agent 定义和 A2A App
332+
│ ├── agent.py # Agent 定义和 A2A App(端口 8001)
299333
│ ├── agentkit.yaml # AgentKit 部署配置
300334
│ ├── requirements.txt # Python 依赖
301335
│ ├── Dockerfile # Docker 镜像构建
@@ -326,7 +360,11 @@ Agent Card 提供以下信息:
326360

327361
访问方式:
328362
```
363+
# 远程 Agent Card
329364
http://localhost:8001/.well-known/agent-card.json
365+
366+
# 本地 Agent Card(如果启动了 agent.py)
367+
http://localhost:8000/.well-known/agent-card.json
330368
```
331369

332370
### 工具状态管理
@@ -342,11 +380,43 @@ tool_context.state['rolls'] = tool_context.state['rolls'] + [result]
342380

343381
### 远程调用流程
344382

383+
**方式一:直接客户端调用(local_client.py)**
345384
1. **获取 Agent Card**:了解远程 Agent 的能力
346385
2. **创建客户端**:基于 Agent Card 创建 A2A 客户端
347386
3. **发送消息**:通过 A2A 协议发送请求
348387
4. **接收响应**:处理远程 Agent 的响应
349388

389+
**方式二:Agent 级联调用(agent.py)**
390+
1. **定义 RemoteVeAgent**:配置远程 Agent 的 URL
391+
2. **注册为 sub_agents**:将远程 Agent 注册到本地 Agent
392+
3. **自动路由**:本地 Agent 自动将任务委派给合适的 Agent
393+
4. **统一接口**:对外提供统一的 A2A 接口
394+
395+
### Agent 级联(Sub-Agents)
396+
397+
通过 `sub_agents` 参数,可以构建 Agent 级联架构:
398+
399+
```python
400+
from veadk.a2a.remote_ve_agent import RemoteVeAgent
401+
402+
remote_agent = RemoteVeAgent(
403+
name="a2a_agent",
404+
url="http://localhost:8001/",
405+
)
406+
407+
agent = Agent(
408+
name="a2a_sample_agent",
409+
tools=[add],
410+
sub_agents=[remote_agent], # 级联远程 Agent
411+
)
412+
```
413+
414+
**优势**
415+
- 本地 Agent 可以同时使用本地工具和远程 Agent 的工具
416+
- 自动处理工具路由和调用
417+
- 支持多个远程 Agent 级联
418+
- 对外暴露统一的 A2A 接口
419+
350420
### AgentKit A2A App
351421

352422
```python

02-use-cases/beginner/a2a_simple/agent.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
from veadk import Agent, Runner
12
from veadk.a2a.remote_ve_agent import RemoteVeAgent
2-
from veadk.agent import Agent
3-
from veadk.memory import ShortTermMemory
4-
from agentkit.app import AgentkitA2aApp
3+
from agentkit.apps import AgentkitA2aApp
4+
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
55
from a2a.types import AgentCard, AgentProvider, AgentSkill, AgentCapabilities
66

77
remote_agent = RemoteVeAgent(
88
name="a2a_agent",
9-
url="http://localhost:8000/", # <--- url from cloud platform
9+
url="http://localhost:8001/", # <--- url from remote agent service
1010
)
1111

1212
def add(a: int, b: int) -> int:
@@ -15,33 +15,34 @@ def add(a: int, b: int) -> int:
1515

1616
agent = Agent(
1717
name="a2a_sample_agent",
18-
instruction="You are a helpful assistant.",
18+
instruction="You are a helpful assistant that can add numbers and delegate tasks to a remote agent that can roll dice and check prime numbers.",
1919
tools=[add],
2020
sub_agents=[remote_agent],
2121
)
2222

23-
a2aApp = AgentkitA2aApp(
24-
agent=agent,
25-
app_name="a2a_sample_app",
26-
short_term_memory=ShortTermMemory(),
27-
)
23+
runner = Runner(agent=agent)
24+
25+
26+
a2aApp = AgentkitA2aApp()
27+
28+
@a2aApp.agent_executor(runner=runner)
29+
class MyAgentExecutor(A2aAgentExecutor):
30+
pass
2831

2932
if __name__ == "__main__":
30-
from a2a.types import AgentCard, AgentProvider, AgentSkill, AgentCapabilities
31-
3233
agent_card = AgentCard(
33-
capabilities=AgentCapabilities(streaming=True), # 启用流式
34+
capabilities=AgentCapabilities(streaming=True),
3435
description=agent.description,
3536
name=agent.name,
3637
defaultInputModes=["text"],
3738
defaultOutputModes=["text"],
38-
provider=AgentProvider(organization="veadk", url=""),
39+
provider=AgentProvider(organization="agentkit", url=""),
3940
skills=[AgentSkill(id="0", name="chat", description="Chat", tags=["chat"])],
4041
url="http://0.0.0.0:8000",
4142
version="1.0.0",
4243
)
43-
44-
a2a_app.run(
44+
45+
a2aApp.run(
4546
agent_card=agent_card,
4647
host="0.0.0.0",
4748
port=8000,

02-use-cases/beginner/a2a_simple/local_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ async def test_trending_topics() -> None:
102102
"""Test news topics agent."""
103103
for i in range(0, 10):
104104
trending_topics = await a2a_client.create_task(
105-
f'http://localhost:8000', "hello , show me one number of 6-sided"
105+
f'http://localhost:8001', "hello , show me one number of 6-sided"
106106
)
107107
print(trending_topics)
108108

02-use-cases/beginner/a2a_simple/remote/agent.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ class MyAgentExecutor(A2aAgentExecutor):
5353
defaultOutputModes=["text"],
5454
provider=AgentProvider(organization="agentkit", url=""),
5555
skills=[AgentSkill(id="0", name="chat", description="Chat", tags=["chat"])],
56-
url="0.0.0.0",
56+
url="http://localhost:8001",
5757
version="1.0.0",
5858
)
5959

6060
print('agent start successfully ', root_agent.name)
6161

6262
# a2a_app = to_a2a(root_agent, port=8001)
6363
if __name__ == '__main__':
64-
a2a_app.run(agent_card=agent_card, host="0.0.0.0", port=8000)
64+
a2a_app.run(agent_card=agent_card, host="0.0.0.0", port=8001)

0 commit comments

Comments
 (0)