Skip to content

Commit 034af74

Browse files
committed
support for stateless txns and clean up
Change-Id: If8efb709923d8cfe261e2317a222a3fd172ade13
1 parent eb696dd commit 034af74

File tree

12 files changed

+444
-373
lines changed

12 files changed

+444
-373
lines changed

‎examples/demo/__main__.py‎

Lines changed: 0 additions & 23 deletions
This file was deleted.

‎examples/demo/agent_proxy.py‎

Lines changed: 0 additions & 110 deletions
This file was deleted.

‎examples/demo/test_client.py‎

Lines changed: 0 additions & 40 deletions
This file was deleted.

‎examples/helloworld/__main__.py‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from agent_executor import HelloWorldAgentExecutor
2+
3+
from a2a.server import A2AServer, DefaultA2ARequestHandler
4+
from a2a.types import (
5+
AgentAuthentication,
6+
AgentCapabilities,
7+
AgentCard,
8+
AgentSkill,
9+
)
10+
11+
12+
if __name__ == '__main__':
13+
skill = AgentSkill(
14+
id='hello_world',
15+
name='Returns hello world',
16+
description='just returns hello world',
17+
tags=['hello world'],
18+
examples=['hi', 'hello world'],
19+
)
20+
21+
agent_card = AgentCard(
22+
name='Hello World Agent',
23+
description='Just a hello world agent',
24+
url='http://localhost:9999/',
25+
version='1.0.0',
26+
defaultInputModes=['text'],
27+
defaultOutputModes=['text'],
28+
capabilities=AgentCapabilities(),
29+
skills=[skill],
30+
authentication=AgentAuthentication(schemes=['public']),
31+
)
32+
33+
request_handler = DefaultA2ARequestHandler(
34+
agent_executor=HelloWorldAgentExecutor()
35+
)
36+
37+
server = A2AServer(agent_card=agent_card, request_handler=request_handler)
38+
server.start(host='0.0.0.0', port=9999)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import asyncio
2+
3+
from collections.abc import AsyncGenerator
4+
from typing import Any
5+
from uuid import uuid4
6+
7+
from a2a.server import AgentExecutor
8+
from a2a.types import (
9+
CancelTaskRequest,
10+
CancelTaskResponse,
11+
JSONRPCErrorResponse,
12+
Message,
13+
Part,
14+
Role,
15+
SendMessageRequest,
16+
SendMessageResponse,
17+
SendMessageStreamingRequest,
18+
SendMessageStreamingResponse,
19+
SendMessageStreamingSuccessResponse,
20+
SendMessageSuccessResponse,
21+
Task,
22+
TaskResubscriptionRequest,
23+
TextPart,
24+
UnsupportedOperationError,
25+
)
26+
27+
28+
class HelloWorldAgent:
29+
"""Hello World Agent."""
30+
31+
async def invoke(self):
32+
return 'Hello World'
33+
34+
async def stream(self) -> AsyncGenerator[dict[str, Any], None]:
35+
yield {'content': 'Hello ', 'done': False}
36+
await asyncio.sleep(2)
37+
yield {'content': 'World', 'done': True}
38+
39+
40+
class HelloWorldAgentExecutor(AgentExecutor):
41+
"""Test AgentProxy Implementation."""
42+
43+
def __init__(self):
44+
self.agent = HelloWorldAgent()
45+
46+
async def on_message_send(
47+
self, request: SendMessageRequest, task: Task | None
48+
) -> SendMessageResponse:
49+
result = await self.agent.invoke()
50+
51+
message: Message = Message(
52+
role=Role.agent,
53+
parts=[Part(root=TextPart(text=result))],
54+
messageId=str(uuid4()),
55+
)
56+
57+
return SendMessageResponse(
58+
root=SendMessageSuccessResponse(id=request.id, result=message)
59+
)
60+
61+
async def on_message_stream( # type: ignore
62+
self, request: SendMessageStreamingRequest, task: Task | None
63+
) -> AsyncGenerator[SendMessageStreamingResponse, None]:
64+
async for chunk in self.agent.stream():
65+
message: Message = Message(
66+
role=Role.agent,
67+
parts=[Part(root=TextPart(text=chunk['content']))],
68+
messageId=str(uuid4()),
69+
final=chunk['done'],
70+
)
71+
yield SendMessageStreamingResponse(
72+
root=SendMessageStreamingSuccessResponse(
73+
id=request.id, result=message
74+
)
75+
)
76+
77+
async def on_cancel(
78+
self, request: CancelTaskRequest, task: Task
79+
) -> CancelTaskResponse:
80+
return CancelTaskResponse(
81+
root=JSONRPCErrorResponse(
82+
id=request.id, error=UnsupportedOperationError()
83+
)
84+
)
85+
86+
async def on_resubscribe( # type: ignore
87+
self, request: TaskResubscriptionRequest, task: Task
88+
) -> AsyncGenerator[SendMessageStreamingResponse, None]:
89+
yield SendMessageStreamingResponse(
90+
root=JSONRPCErrorResponse(
91+
id=request.id, error=UnsupportedOperationError()
92+
)
93+
)

‎examples/helloworld/test_client.py‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from a2a.client import A2AClient
2+
from typing import Any
3+
import httpx
4+
from uuid import uuid4
5+
from a2a.types import SendMessageSuccessResponse, Task
6+
7+
8+
async def main() -> None:
9+
async with httpx.AsyncClient() as httpx_client:
10+
client = await A2AClient.get_client_from_agent_card_url(
11+
httpx_client, 'http://localhost:9999'
12+
)
13+
send_message_payload: dict[str, Any] = {
14+
'message': {
15+
'role': 'user',
16+
'parts': [
17+
{'type': 'text', 'text': 'how much is 10 USD in INR?'}
18+
],
19+
'messageId': uuid4().hex,
20+
},
21+
}
22+
23+
response = await client.send_message(payload=send_message_payload)
24+
print(response.model_dump(mode='json', exclude_none=True))
25+
26+
if isinstance(response.root, SendMessageSuccessResponse) and isinstance(
27+
response.root.result, Task
28+
):
29+
task_id: str = response.root.result.id
30+
get_task_payload = {'id': task_id}
31+
get_response = await client.get_task(payload=get_task_payload)
32+
print(get_response.model_dump(mode='json', exclude_none=True))
33+
34+
cancel_task_payload = {'id': task_id}
35+
cancel_response = await client.cancel_task(
36+
payload=cancel_task_payload
37+
)
38+
print(cancel_response.model_dump(mode='json', exclude_none=True))
39+
else:
40+
print(
41+
'Received an instance of Message, getTask and cancelTask are not applicable for invocation'
42+
)
43+
44+
stream_response = client.send_message_streaming(
45+
payload=send_message_payload
46+
)
47+
async for chunk in stream_response:
48+
print(chunk.model_dump(mode='json', exclude_none=True))
49+
50+
51+
if __name__ == '__main__':
52+
import asyncio
53+
54+
asyncio.run(main())

0 commit comments

Comments
 (0)