chore: initialize sandbox and overwrite remote content
Some checks failed
Pre-commit / run (ubuntu-latest) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_en (ubuntu-latest, 3.10) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_zh (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.12) (push) Has been cancelled
Some checks failed
Pre-commit / run (ubuntu-latest) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_en (ubuntu-latest, 3.10) (push) Has been cancelled
Deploy Sphinx documentation to Pages / build_zh (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (macos-15, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (ubuntu-latest, 3.12) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.10) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.11) (push) Has been cancelled
Python Unittest Coverage / test (windows-latest, 3.12) (push) Has been cancelled
This commit is contained in:
47
examples/agent/a2a_agent/README.md
Normal file
47
examples/agent/a2a_agent/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Agent-to-Agent Protocol Example
|
||||
|
||||
The `A2AAgent` in AgentScope is an A2A client that connects to an external agent server via the Agent-to-Agent (A2A) protocol.
|
||||
This example demonstrates how to set up and use the `A2AAgent` to interact with an agent hosted on an A2A server.
|
||||
|
||||
Note the A2A feature is experimental and subject to change, and due to the limitations of A2A protocol, the `A2AAgent`
|
||||
currently
|
||||
|
||||
1. only supports chatbot scenarios, where only a user and an agent are involved
|
||||
2. does not support realtime steering/interruption during the conversation
|
||||
3. does not support agentic structured outputs
|
||||
4. stores the observed messages locally and send them together with the input message(s) of the `reply` function
|
||||
|
||||
## Files
|
||||
|
||||
The example contains the following files:
|
||||
|
||||
```
|
||||
examples/agent/a2a_agent
|
||||
├── main.py # The main script to run the A2A agent example
|
||||
├── setup_a2a_server.py # The script to set up a simple A2A server
|
||||
├── agent_card.py # The agent card definition for the A2A agent
|
||||
└── README.md # This README file
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
This example provides a simple setup to demonstrate how to use the `A2AAgent` in AgentScope.
|
||||
First you need to install the required dependencies:
|
||||
|
||||
```bash
|
||||
uv pip install a2a-sdk[http-server] agentscope[a2a]
|
||||
# or
|
||||
pip install a2a-sdk[http-server] agentscope[a2a]
|
||||
```
|
||||
|
||||
Then we first set up a simple A2A server that hosts a ReAct agent:
|
||||
```bash
|
||||
uvicorn setup_a2a_server:app --host 0.0.0.0 --port 8000
|
||||
```
|
||||
This will start an A2A server locally on port 8000.
|
||||
|
||||
After that, you can run the A2A agent example to run a chatbot conversation with the agent hosted on the A2A server:
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
37
examples/agent/a2a_agent/agent_card.py
Normal file
37
examples/agent/a2a_agent/agent_card.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""The agent card definition for the A2A agent."""
|
||||
from a2a.types import AgentCard, AgentCapabilities, AgentSkill
|
||||
|
||||
agent_card = AgentCard(
|
||||
name="Friday",
|
||||
description="A simple ReAct agent that handles input queries",
|
||||
url="http://localhost:8000",
|
||||
version="1.0.0",
|
||||
capabilities=AgentCapabilities(
|
||||
push_notifications=False,
|
||||
state_transition_history=True,
|
||||
streaming=True,
|
||||
),
|
||||
default_input_modes=["text/plain"],
|
||||
default_output_modes=["text/plain"],
|
||||
skills=[
|
||||
AgentSkill(
|
||||
name="execute_python_code",
|
||||
id="execute_python_code",
|
||||
description="Execute Python code snippets.",
|
||||
tags=["code_execution"],
|
||||
),
|
||||
AgentSkill(
|
||||
name="execute_shell_command",
|
||||
id="execute_shell_command",
|
||||
description="Execute shell commands on the server.",
|
||||
tags=["code_execution"],
|
||||
),
|
||||
AgentSkill(
|
||||
name="view_text_file",
|
||||
id="view_text_file",
|
||||
description="View the content of a text file on the server.",
|
||||
tags=["file_viewing"],
|
||||
),
|
||||
],
|
||||
)
|
||||
28
examples/agent/a2a_agent/main.py
Normal file
28
examples/agent/a2a_agent/main.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""The main entry for the A2A agent example."""
|
||||
import asyncio
|
||||
|
||||
from agent_card import agent_card
|
||||
|
||||
from agentscope.agent import UserAgent, A2AAgent
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""The main entry for the example, where we build a simple conversation
|
||||
between the A2A agent and the user."""
|
||||
|
||||
user = UserAgent("user")
|
||||
|
||||
agent = A2AAgent(
|
||||
agent_card=agent_card,
|
||||
)
|
||||
|
||||
msg = None
|
||||
while True:
|
||||
msg = await user(msg)
|
||||
if msg.get_text_content() == "exit":
|
||||
break
|
||||
msg = await agent(msg)
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
132
examples/agent/a2a_agent/setup_a2a_server.py
Normal file
132
examples/agent/a2a_agent/setup_a2a_server.py
Normal file
@@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Set up an A2A server with a ReAct agent to handle the input query"""
|
||||
import os
|
||||
import uuid
|
||||
from typing import AsyncGenerator, Any
|
||||
|
||||
from agent_card import agent_card
|
||||
|
||||
from a2a.server.events import Event
|
||||
from a2a.types import (
|
||||
TaskStatus,
|
||||
TaskState,
|
||||
MessageSendParams,
|
||||
TaskStatusUpdateEvent,
|
||||
)
|
||||
from a2a.server.apps import A2AStarletteApplication
|
||||
|
||||
from agentscope.agent import ReActAgent
|
||||
from agentscope.formatter import DashScopeChatFormatter, A2AChatFormatter
|
||||
from agentscope.model import DashScopeChatModel
|
||||
from agentscope.pipeline import stream_printing_messages
|
||||
from agentscope.session import JSONSession
|
||||
from agentscope.tool import (
|
||||
Toolkit,
|
||||
execute_python_code,
|
||||
execute_shell_command,
|
||||
view_text_file,
|
||||
)
|
||||
|
||||
|
||||
class SimpleStreamHandler:
|
||||
"""A simple request handler that handles the input query by an
|
||||
ReAct agent."""
|
||||
|
||||
async def on_message_send_stream(
|
||||
self, # pylint: disable=unused-argument
|
||||
params: MessageSendParams,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> AsyncGenerator[Event, None]:
|
||||
"""Handles the message_send method by the agent
|
||||
|
||||
Args:
|
||||
params (`MessageSendParams`):
|
||||
The parameters for sending the message.
|
||||
|
||||
Returns:
|
||||
`AsyncGenerator[Event, None]`:
|
||||
An asynchronous generator that yields task status update
|
||||
events.
|
||||
"""
|
||||
task_id = params.message.task_id or uuid.uuid4().hex
|
||||
context_id = params.message.context_id or "default-context"
|
||||
# ============ Agent Logic ============
|
||||
|
||||
# Register the tool functions
|
||||
toolkit = Toolkit()
|
||||
toolkit.register_tool_function(execute_python_code)
|
||||
toolkit.register_tool_function(execute_shell_command)
|
||||
toolkit.register_tool_function(view_text_file)
|
||||
|
||||
# Create the agent instance
|
||||
agent = ReActAgent(
|
||||
name="Friday",
|
||||
sys_prompt="You're a helpful assistant named Friday.",
|
||||
model=DashScopeChatModel(
|
||||
model_name="qwen-max",
|
||||
api_key=os.getenv("DASHSCOPE_API_KEY"),
|
||||
),
|
||||
formatter=DashScopeChatFormatter(),
|
||||
toolkit=toolkit,
|
||||
)
|
||||
|
||||
session = JSONSession(save_dir="./sessions")
|
||||
await session.load_session_state(
|
||||
session_id="test-a2a-agent",
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
# Convert the A2A message to AgentScope Msg objects
|
||||
formatter = A2AChatFormatter()
|
||||
as_msg = await formatter.format_a2a_message(
|
||||
name="Friday",
|
||||
message=params.message,
|
||||
)
|
||||
|
||||
yield TaskStatusUpdateEvent(
|
||||
task_id=task_id,
|
||||
context_id=context_id,
|
||||
status=TaskStatus(state=TaskState.working),
|
||||
final=False,
|
||||
)
|
||||
|
||||
async for msg, last in stream_printing_messages(
|
||||
agents=[agent],
|
||||
coroutine_task=agent(as_msg),
|
||||
):
|
||||
# The A2A streaming response is one complete Message object rather
|
||||
# than accumulated or incremental text
|
||||
if last:
|
||||
a2a_message = await formatter.format([msg])
|
||||
|
||||
yield TaskStatusUpdateEvent(
|
||||
task_id=task_id,
|
||||
context_id=context_id,
|
||||
status=TaskStatus(
|
||||
state=TaskState.working,
|
||||
message=a2a_message,
|
||||
),
|
||||
final=False,
|
||||
)
|
||||
|
||||
# Finish the task
|
||||
yield TaskStatusUpdateEvent(
|
||||
task_id=task_id,
|
||||
context_id=context_id,
|
||||
status=TaskStatus(state=TaskState.completed),
|
||||
final=True,
|
||||
)
|
||||
|
||||
await session.save_session_state(
|
||||
session_id="test-a2a-agent",
|
||||
agent=agent,
|
||||
)
|
||||
|
||||
|
||||
handler = SimpleStreamHandler()
|
||||
app_instance = A2AStarletteApplication(
|
||||
agent_card,
|
||||
handler,
|
||||
)
|
||||
app = app_instance.build()
|
||||
Reference in New Issue
Block a user