Skip to content
Merged
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
78 changes: 74 additions & 4 deletions 02-use-cases/beginner/a2a_simple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,31 @@
## 🏗️ 架构

```
方式一:直接客户端调用
本地客户端 (local_client.py)
A2A 协议 (HTTP/JSONRPC)
远程 Agent 服务 (remote/agent.py)
远程 Agent 服务 (remote/agent.py:8001)
├── roll_die 工具 (投掷骰子)
│ └── 状态管理:rolls 历史
└── check_prime 工具 (检查质数)

方式二:Agent 级联调用
本地 Agent (agent.py:8000)
├── add 工具 (加法)
└── RemoteVeAgent → 远程 Agent 服务 (remote/agent.py:8001)
├── roll_die 工具 (投掷骰子)
└── check_prime 工具 (检查质数)
```

### 核心组件

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

### 代码特点

**本地 Agent 定义**([agent.py](agent.py:16-21)):
```python
agent = Agent(
name="a2a_sample_agent",
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.",
tools=[add],
sub_agents=[remote_agent],
)
```

**远程 Agent 定义**([remote/agent.py](remote/agent.py:14-40)):
```python
root_agent = Agent(
Expand Down Expand Up @@ -67,7 +86,7 @@ agent_card = AgentCard(
defaultOutputModes=["text"],
provider=AgentProvider(organization="agentkit", url=""),
skills=[AgentSkill(id="0", name="chat", description="Chat", tags=["chat"])],
url="0.0.0.0",
url="http://localhost:8001",
version="1.0.0",
)
```
Expand Down Expand Up @@ -208,6 +227,20 @@ cd 02-use-cases/beginner/a2a_simple
python local_client.py
```

**步骤 3(可选):启动本地 Agent 服务**
```bash
# 在终端窗口 3 中运行(需要先启动远程 Agent)
cd 02-use-cases/beginner/a2a_simple
python agent.py

# 服务启动后,可访问 Agent Card
# http://localhost:8000/.well-known/agent-card.json
```

此时您有两个 Agent 服务:
- **远程 Agent**(端口 8001):提供 roll_die 和 check_prime 工具
- **本地 Agent**(端口 8000):提供 add 工具,并可调用远程 Agent

#### 方式四:部署到火山引擎 veFaaS

**安全提示**:
Expand Down Expand Up @@ -293,9 +326,10 @@ No prime numbers found.

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

访问方式:
```
# 远程 Agent Card
http://localhost:8001/.well-known/agent-card.json

# 本地 Agent Card(如果启动了 agent.py)
http://localhost:8000/.well-known/agent-card.json
```

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

### 远程调用流程

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

**方式二:Agent 级联调用(agent.py)**
1. **定义 RemoteVeAgent**:配置远程 Agent 的 URL
2. **注册为 sub_agents**:将远程 Agent 注册到本地 Agent
3. **自动路由**:本地 Agent 自动将任务委派给合适的 Agent
4. **统一接口**:对外提供统一的 A2A 接口

### Agent 级联(Sub-Agents)

通过 `sub_agents` 参数,可以构建 Agent 级联架构:

```python
from veadk.a2a.remote_ve_agent import RemoteVeAgent

remote_agent = RemoteVeAgent(
name="a2a_agent",
url="http://localhost:8001/",
)

agent = Agent(
name="a2a_sample_agent",
tools=[add],
sub_agents=[remote_agent], # 级联远程 Agent
)
```

**优势**:
- 本地 Agent 可以同时使用本地工具和远程 Agent 的工具
- 自动处理工具路由和调用
- 支持多个远程 Agent 级联
- 对外暴露统一的 A2A 接口

### AgentKit A2A App

```python
Expand Down
33 changes: 17 additions & 16 deletions 02-use-cases/beginner/a2a_simple/agent.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from veadk import Agent, Runner
from veadk.a2a.remote_ve_agent import RemoteVeAgent
from veadk.agent import Agent
from veadk.memory import ShortTermMemory
from agentkit.app import AgentkitA2aApp
from agentkit.apps import AgentkitA2aApp
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
from a2a.types import AgentCard, AgentProvider, AgentSkill, AgentCapabilities

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

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

agent = Agent(
name="a2a_sample_agent",
instruction="You are a helpful assistant.",
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.",
tools=[add],
sub_agents=[remote_agent],
)

a2aApp = AgentkitA2aApp(
agent=agent,
app_name="a2a_sample_app",
short_term_memory=ShortTermMemory(),
)
runner = Runner(agent=agent)


a2aApp = AgentkitA2aApp()

@a2aApp.agent_executor(runner=runner)
class MyAgentExecutor(A2aAgentExecutor):
pass

if __name__ == "__main__":
from a2a.types import AgentCard, AgentProvider, AgentSkill, AgentCapabilities

agent_card = AgentCard(
capabilities=AgentCapabilities(streaming=True), # 启用流式
capabilities=AgentCapabilities(streaming=True),
description=agent.description,
name=agent.name,
defaultInputModes=["text"],
defaultOutputModes=["text"],
provider=AgentProvider(organization="veadk", url=""),
provider=AgentProvider(organization="agentkit", url=""),
skills=[AgentSkill(id="0", name="chat", description="Chat", tags=["chat"])],
url="http://0.0.0.0:8000",
version="1.0.0",
)
a2a_app.run(

a2aApp.run(
agent_card=agent_card,
host="0.0.0.0",
port=8000,
Expand Down
2 changes: 1 addition & 1 deletion 02-use-cases/beginner/a2a_simple/local_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async def test_trending_topics() -> None:
"""Test news topics agent."""
for i in range(0, 10):
trending_topics = await a2a_client.create_task(
f'http://localhost:8000', "hello , show me one number of 6-sided"
f'http://localhost:8001', "hello , show me one number of 6-sided"
)
print(trending_topics)

Expand Down
4 changes: 2 additions & 2 deletions 02-use-cases/beginner/a2a_simple/remote/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ class MyAgentExecutor(A2aAgentExecutor):
defaultOutputModes=["text"],
provider=AgentProvider(organization="agentkit", url=""),
skills=[AgentSkill(id="0", name="chat", description="Chat", tags=["chat"])],
url="0.0.0.0",
url="http://localhost:8001",
version="1.0.0",
)

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

# a2a_app = to_a2a(root_agent, port=8001)
if __name__ == '__main__':
a2a_app.run(agent_card=agent_card, host="0.0.0.0", port=8000)
a2a_app.run(agent_card=agent_card, host="0.0.0.0", port=8001)
Loading