Skip to content

Commit b9d0743

Browse files
增加“A2A协议深度解析(2)”
1 parent 9b33c99 commit b9d0743

16 files changed

Lines changed: 1054 additions & 0 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13

A2A协议深度解析(2)/flight/README.md

Whitespace-only changes.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from a2a.server.apps import A2AStarletteApplication
2+
from a2a.server.request_handlers import DefaultRequestHandler
3+
from a2a.server.tasks import InMemoryTaskStore
4+
from a2a.types import (
5+
AgentCapabilities,
6+
AgentCard,
7+
AgentSkill,
8+
)
9+
10+
from agent_executor import FlightAgentExecutor
11+
12+
13+
def main(host: str, port: int):
14+
capabilities = AgentCapabilities(streaming=True)
15+
query_flight_skill = AgentSkill(
16+
id='查询机票信息',
17+
name='查询机票信息',
18+
description='给定时间,查询对应的机票信息',
19+
tags=['查询', '机票'],
20+
examples=['给我查询5月1日的机票信息'],
21+
)
22+
book_skill = AgentSkill(
23+
id='预定机票',
24+
name='预定机票',
25+
description='预定机票',
26+
tags=['预定', '机票'],
27+
examples=['给我预定5月1日从纽约飞往旧金山的机票'],
28+
)
29+
30+
agent_card = AgentCard(
31+
name='机票 Agent',
32+
description='提供机票查询和预订功能',
33+
url=f'http://{host}:{port}',
34+
version='1.0.0',
35+
defaultInputModes=['text'],
36+
defaultOutputModes=['text'],
37+
capabilities=capabilities,
38+
skills=[query_flight_skill, book_skill],
39+
)
40+
41+
request_handler = DefaultRequestHandler(
42+
agent_executor=FlightAgentExecutor(),
43+
task_store=InMemoryTaskStore(),
44+
)
45+
server = A2AStarletteApplication(
46+
agent_card=agent_card, http_handler=request_handler
47+
)
48+
import uvicorn
49+
50+
uvicorn.run(server.build(), host=host, port=port)
51+
52+
53+
if __name__ == '__main__':
54+
main("127.0.0.1", 10001)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import uuid
2+
3+
from a2a.server.agent_execution import AgentExecutor, RequestContext
4+
from a2a.server.events import EventQueue
5+
from a2a.server.tasks import TaskUpdater
6+
from a2a.types import (Part, Task, TextPart, UnsupportedOperationError, TaskArtifactUpdateEvent, Artifact)
7+
from a2a.utils import new_task
8+
from a2a.utils.errors import ServerError
9+
10+
11+
class FlightAgentExecutor(AgentExecutor):
12+
13+
async def execute(
14+
self,
15+
context: RequestContext,
16+
event_queue: EventQueue,
17+
) -> None:
18+
task = context.current_task
19+
if not task:
20+
task = new_task(context.message)
21+
event_queue.enqueue_event(task)
22+
updater = TaskUpdater(event_queue, task.id, task.contextId)
23+
24+
artifact_id = str(uuid.uuid4())
25+
event_queue.enqueue_event(
26+
TaskArtifactUpdateEvent(
27+
taskId=task.id,
28+
contextId=task.contextId,
29+
artifact=Artifact(
30+
artifactId=artifact_id,
31+
parts=[Part(root=TextPart(text="你要查询的机票"))],
32+
),
33+
append=False,
34+
lastChunk=False
35+
)
36+
)
37+
event_queue.enqueue_event(
38+
TaskArtifactUpdateEvent(
39+
taskId=task.id,
40+
contextId=task.contextId,
41+
artifact=Artifact(
42+
artifactId=artifact_id,
43+
parts=[Part(root=TextPart(text="如下:"))],
44+
),
45+
append=True,
46+
lastChunk=False
47+
)
48+
)
49+
event_queue.enqueue_event(
50+
TaskArtifactUpdateEvent(
51+
taskId=task.id,
52+
contextId=task.contextId,
53+
artifact=Artifact(
54+
artifactId=artifact_id,
55+
parts=[Part(root=TextPart(text="1. 航班号 FAKE-001,起飞时间 20:00,余票 30 张;2. 航班号 FAKE-002,起飞时间 23:00,余票 50 张"))],
56+
),
57+
append=True,
58+
lastChunk=True
59+
)
60+
)
61+
updater.complete()
62+
63+
async def cancel(
64+
self, request: RequestContext, event_queue: EventQueue
65+
) -> Task | None:
66+
raise ServerError(error=UnsupportedOperationError())
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[project]
2+
name = "flight"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
readme = "README.md"
6+
requires-python = ">=3.13"
7+
dependencies = [
8+
"a2a-sdk>=0.2.5",
9+
"uvicorn>=0.34.2",
10+
]

A2A协议深度解析(2)/flight/uv.lock

Lines changed: 358 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# 介绍
2+
3+
本项目是一个示例用的天气 Agent,用于在 A2A 演示中作为 Remote Agent 使用。
4+
5+
# 启动方法
6+
7+
在当前目录下执行如下命令即可启动:
8+
9+
```sh
10+
uv run .
11+
```
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from a2a.server.apps import A2AStarletteApplication
2+
from a2a.server.request_handlers import DefaultRequestHandler
3+
from a2a.server.tasks import InMemoryTaskStore
4+
from a2a.types import (
5+
AgentCapabilities,
6+
AgentCard,
7+
AgentSkill,
8+
)
9+
10+
from agent_executor import WeatherAgentExecutor
11+
12+
13+
def main(host: str, port: int):
14+
capabilities = AgentCapabilities(streaming=False)
15+
forecast_skill = AgentSkill(
16+
id='天气预告',
17+
name='天气预告',
18+
description='给出某地的天气预告',
19+
tags=['天气', '预告'],
20+
examples=['给我纽约未来 7 天的天气预告'],
21+
)
22+
air_quality_skill = AgentSkill(
23+
id='空气质量报告',
24+
name='空气质量报告',
25+
description='给出某地当前时间的空气质量报告,不做预告',
26+
tags=['空气', '质量'],
27+
examples=['给我纽约当前的空气质量报告'],
28+
)
29+
30+
agent_card = AgentCard(
31+
name='天气 Agent',
32+
description='提供天气相关的查询功能',
33+
url=f'http://{host}:{port}',
34+
version='1.0.0',
35+
defaultInputModes=['text'],
36+
defaultOutputModes=['text'],
37+
capabilities=capabilities,
38+
skills=[forecast_skill, air_quality_skill],
39+
)
40+
41+
request_handler = DefaultRequestHandler(
42+
agent_executor=WeatherAgentExecutor(),
43+
task_store=InMemoryTaskStore(),
44+
)
45+
server = A2AStarletteApplication(
46+
agent_card=agent_card, http_handler=request_handler
47+
)
48+
import uvicorn
49+
50+
uvicorn.run(server.build(), host=host, port=port)
51+
52+
53+
if __name__ == '__main__':
54+
main("127.0.0.1", 10000)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from a2a.server.agent_execution import AgentExecutor, RequestContext
2+
from a2a.server.events import EventQueue
3+
from a2a.types import (Part, Task, TextPart, UnsupportedOperationError)
4+
from a2a.utils import (completed_task, new_artifact)
5+
from a2a.utils.errors import ServerError
6+
7+
8+
class WeatherAgentExecutor(AgentExecutor):
9+
10+
async def execute(
11+
self,
12+
context: RequestContext,
13+
event_queue: EventQueue,
14+
) -> None:
15+
text="""您要查询的天气信息如下:5 月 1 日:晴天;5 月 2 日:小雨;5 月 3 日:大雨。"""
16+
event_queue.enqueue_event(
17+
completed_task(
18+
context.task_id,
19+
context.context_id,
20+
[new_artifact(parts=[Part(root=TextPart(text=text))], name="天气查询结果")],
21+
[context.message],
22+
)
23+
)
24+
25+
async def cancel(
26+
self, request: RequestContext, event_queue: EventQueue
27+
) -> Task | None:
28+
raise ServerError(error=UnsupportedOperationError())

0 commit comments

Comments
 (0)