from strands_tools.a2a_client import A2AClientToolProvider

# 告诉客户端所有可用的服务器地址
provider = A2AClientToolProvider(known_agent_urls=[
    "http://localhost:9000",  # 计算器
    "http://localhost:9001",  # 翻译
    "http://localhost:9002"   # 天气
])

# 客户端Agent会自动选择合适的服务
client_agent = Agent(tools=provider.tools)
client_agent("帮我算 5+3")        # 自动选择计算器Agent
client_agent("翻译hello")         # 自动选择翻译Agent
client_agent("今天天气怎么样")     # 自动选择天气Agent

以通过这个 A2A 方案实现对话,但关于对话流程如何运作,有一些重要的注意事项。让我为您解释并展示如何针对对话进行优化:

当前行为分析
根据您当前的设置:

python

from strands_tools.a2a_client import A2AClientToolProvider
provider = A2AClientToolProvider(known_agent_urls=[
    "http://localhost:9000",  # 数学智能体
    "http://localhost:9001",  # 翻译智能体
    "http://localhost:9002"   # 天气智能体
])
client_agent = Agent(tools=provider.tools)

# 每次调用都是独立的
client_agent("帮我计算 5+3")      # 调用数学智能体
client_agent("翻译 hello")            # 调用翻译智能体
client_agent("今天天气怎么样")  # 调用天气智能体

发生的情况:

  • 每次调用都是独立的 - 调用之间没有对话记忆

  • 客户端智能体将请求路由到相应的专业智能体

  • 每个专业智能体处理请求并返回结果

  • 跨多次交互没有持久化的对话状态

支持对话的增强型 A2A 设置
以下是实现具有对话记忆的真正对话的方法:

1. 支持会话的客户端智能体

from strands import Agent
from strands_tools.a2a_client import A2AClientToolProvider
from strands.session.s3_session_manager import S3SessionManager

# 创建支持会话的客户端智能体
session_manager = S3SessionManager(
    session_id="user_conversation_session", # 用户会话会话ID
    bucket="agent-conversations", # 智能体对话存储桶
    prefix="client_sessions" # 客户端会话前缀
)

provider = A2AClientToolProvider(known_agent_urls=[
    "http://localhost:9000",  # 数学智能体
    "http://localhost:9001",  # 翻译智能体
    "http://localhost:9002"   # 天气智能体
])

client_agent = Agent(
    name="对话式客户端智能体", # 对话式客户端智能体
    session_manager=session_manager,  # 启用对话记忆
    tools=provider.tools,
    prompt="""
    您是一个可以帮助处理数学、翻译和天气问题的对话助手。
    您可以通过 A2A 协议访问专业智能体。
    
    重要提示:
    - 记住我们的对话历史
    - 基于之前的交互进行构建
    - 在适当时提出后续问题
    - 在多个请求之间保持上下文
    
    可用的专家:
    - 数学计算 (localhost:9000)
    - 语言翻译 (localhost:9001)
    - 天气信息 (localhost:9002)
    """
)

# 现在您可以进行真正的对话了
print("=== 对话 1 ===")
response1 = client_agent("帮我计算 5+3")
print(f"智能体: {response1}")

print("\n=== 对话 2 ===")
response2 = client_agent("你能再计算一下那个结果的平方吗?")
print(f"智能体: {response2}")

print("\n=== 对话 3 ===")
response3 = client_agent("现在把短语 '答案是 64' 翻译成西班牙语")
print(f"智能体: {response3}")

print("\n=== 对话 4 ===")
response4 = client_agent("马德里今天的天气怎么样?")
print(f"智能体: {response4}")

2. 对话式专业智能体
让您的专业智能体也支持对话:

# math_agent.py (localhost:9000)
from strands import Agent, tool
from strands.multiagent.a2a import A2AServer
from strands.session.s3_session_manager import S3SessionManager

@tool
def calculate(expression: str) -> str:
    """执行数学计算"""
    try:
        result = eval(expression)
        return f"{expression} 的结果是 {result}"
    except Exception as e:
        return f"计算 {expression} 时出错: {str(e)}"

@tool
def remember_calculation(expression: str, result: str) -> str:
    """记住一个计算以供将来参考"""
    # 这可以存储在共享内存或会话中
    return f"我会记住 {expression} = {result}"

# 支持会话的数学智能体
math_session_manager = S3SessionManager(
    session_id="math_agent_session", # 数学智能体会话ID
    bucket="agent-conversations", # 智能体对话存储桶
    prefix="math_sessions" # 数学会话前缀
)

math_agent = Agent(
    name="对话式数学智能体", # 对话式数学智能体
    session_manager=math_session_manager,
    tools=[calculate, remember_calculation],
    prompt="""
    您是一个对话式数学专家。
    - 记住我们对话中之前的计算
    - 在相关时引用之前的结果
    - 如果数学请求不清楚,请提出澄清问题
    - 在有帮助时提供分步解释
    """
)

# 使用 A2A 提供服务
server = A2AServer(agent=math_agent, port=9000)
server.serve()

3. 多轮对话示例
这是一个展示真正对话的完整示例:

import asyncio
from strands import Agent
from strands_tools.a2a_client import A2AClientToolProvider
from strands.session.file_session_manager import FileSessionManager

async def conversational_demo():
    # 设置对话式客户端
    session_manager = FileSessionManager(
        session_id="demo_conversation", # 演示会话ID
        base_dir="./conversation_sessions" # 会话存储目录
    )
    
    provider = A2AClientToolProvider(known_agent_urls=[
        "http://localhost:9000",  # 数学智能体
        "http://localhost:9001",  # 翻译智能体
        "http://localhost:9002"   # 天气智能体
    ])
    
    client_agent = Agent(
        name="对话助手", # 对话助手
        session_manager=session_manager,
        tools=provider.tools,
        prompt="""
        您是一个有用的对话助手,可以访问专业智能体。
        
        关键行为:
        - 维护对话上下文和记忆
        - 自然地引用之前的交互
        - 提出后续问题以更好地帮助用户
        - 在相关时组合来自多个专家的信息
        - 具有对话性和吸引力
        
        可用的专家智能体:
        - 数学计算和分析
        - 语言翻译服务
        - 天气信息和预报
        """
    )
    
    # 模拟多轮对话
    conversation = [
        "你好!你能帮我做一些计算吗?",
        "我需要计算 15 * 23",
        "太好了!现在你能计算那个结果的 20% 吗?",
        "完美。你能把 '结果是 69' 翻译成法语吗?",
        "谢谢!顺便问一下,巴黎今天的天气怎么样?",
        "有趣!那么根据我们之前关于预算和天气的对话,如果我计划去巴黎旅行,你会建议带伞吗?"
    ]
    
    print("=== 多轮对话演示 ===\n")
    
    for i, user_input in enumerate(conversation, 1):
        print(f"👤 用户 (第 {i} 轮): {user_input}")
        
        response = await client_agent.run_async(user_input)
        print(f"🤖 助手: {response}")
        print("-" * 60)
        
        # 短暂延迟以模拟自然对话节奏
        await asyncio.sleep(1)

# 运行演示
asyncio.run(conversational_demo())

4. 高级对话功能
添加更复杂的对话功能:

from strands import Agent, tool
from typing import Dict, List
import json
from datetime import datetime # 导入 datetime

class ConversationalA2AClient:
    def __init__(self, agent_urls: List[str], user_id: str = "default_user"):
        self.user_id = user_id
        self.conversation_history = []
        self.context_memory = {}
        
        # 具有用户特定会话的会话管理器
        self.session_manager = S3SessionManager(
            session_id=f"conversation_{user_id}", # 会话_{用户ID}
            bucket="user-conversations", # 用户对话存储桶
            prefix=f"users/{user_id}/sessions" # 用户/{用户ID}/会话 前缀
        )
        
        # A2A 提供者
        self.provider = A2AClientToolProvider(known_agent_urls=agent_urls)
        
        # 用于对话管理的增强工具
        self.conversation_tools = [
            self.remember_context,
            self.recall_context,
            self.summarize_conversation,
            self.ask_clarification
        ]
        
        # 创建对话式智能体
        self.agent = Agent(
            name=f"{user_id} 的个人助手", # {用户ID} 的个人助手
            session_manager=self.session_manager,
            tools=self.provider.tools + self.conversation_tools,
            prompt=self.get_conversational_prompt()
        )
    
    @tool
    def remember_context(self, key: str, value: str, category: str = "general") -> str:
        """记住对话中的重要上下文"""
        if category not in self.context_memory:
            self.context_memory[category] = {}
        
        self.context_memory[category][key] = {
            "value": value,
            "timestamp": datetime.utcnow().isoformat(),
            "conversation_turn": len(self.conversation_history)
        }
        
        return f"我会记住 {key}: {value} (类别: {category})"
    
    @tool
    def recall_context(self, key: str = None, category: str = None) -> str:
        """回忆先前存储的上下文"""
        if category and category in self.context_memory:
            if key and key in self.context_memory[category]:
                context = self.context_memory[category][key]
                return f"我记得 {key}: {context['value']} (来自第 {context['conversation_turn']} 轮)"
            else:
                items = list(self.context_memory[category].keys())
                return f"在 {category} 中,我记得: {', '.join(items)}"
        elif key:
            # 在所有类别中搜索
            for cat, items in self.context_memory.items():
                if key in items:
                    context = items[key]
                    return f"我记得 {key}: {context['value']} (类别: {cat})"
            return f"我不记得关于 {key} 的任何事情"
        else:
            # 返回所有上下文的摘要
            summary = {}
            for cat, items in self.context_memory.items():
                summary[cat] = list(items.keys())
            return f"我记得: {json.dumps(summary, indent=2)}"
    
    @tool
    def summarize_conversation(self, last_n_turns: int = 5) -> str:
        """总结最近的对话轮次"""
        recent_history = self.conversation_history[-last_n_turns:]
        
        summary = f"最近 {len(recent_history)} 轮的摘要:\n"
        for i, turn in enumerate(recent_history, 1):
            summary += f"{i}. 用户: {turn['user'][:50]}...\n"
            summary += f"   助手: {turn['assistant'][:50]}...\n"
        
        return summary
    
    @tool
    def ask_clarification(self, question: str, context: str = "") -> str:
        """向用户请求澄清"""
        clarification = f"我需要澄清: {question}"
        if context:
            clarification += f"\n上下文: {context}"
        
        return clarification
    
    def get_conversational_prompt(self) -> str:
        return f"""
        您是 {self.user_id} 的个人对话助手。
        
        您可以通过 A2A 协议访问专业智能体和对话管理工具。
        
        对话指南:
        1. 保持自然、吸引人的对话
        2. 使用 remember_context 工具记住重要细节
        3. 使用 recall_context 工具引用之前的对话
        4. 当请求不明确时请求澄清
        5. 智能地组合来自多个专家的信息
        6. 主动提供相关的帮助
        
        记忆类别:
        - preferences: 用户偏好和设置
        - calculations: 数学结果和公式
        - translations: 语言对和翻译
        - weather: 位置偏好和天气信息
        - tasks: 进行中的任务和项目
        
        始终努力做到有帮助、有上下文且具有对话性!
        """
    
    async def chat(self, message: str) -> str:
        """带有对话跟踪的主聊天接口"""
        
        # 添加到对话历史
        response = await self.agent.run_async(message)
        
        self.conversation_history.append({
            "user": message,
            "assistant": response,
            "timestamp": datetime.utcnow().isoformat()
        })
        
        return response

# 用法
async def advanced_dialogue_demo():
    client = ConversationalA2AClient(
        agent_urls=[
            "http://localhost:9000",  # 数学
            "http://localhost:9001",  # 翻译
            "http://localhost:9002"   # 天气
        ],
        user_id="john_doe" # 用户 john_doe
    )
    
    # 具有记忆和上下文的扩展对话
    conversation = [
        "你好!我计划下个月去巴黎旅行。",
        "你能帮我计算预算吗?我有 2000 美元可以花。",
        "如果我每天在住宿上花费 150 美元,我可以住多少天?",
        "太好了!你能把 '我想预订一个房间住 13 天' 翻译成法语吗?",
        "巴黎三月的天气通常怎么样?",
        "根据我们关于我的预算和天气的对话,我应该带什么?",
        "你能再提醒我一下我的总预算是多少吗?",
        "完美!你能总结一下我们目前的对话吗?"
    ]
    
    print("=== 高级对话式 A2A 演示 ===\n")
    
    for i, user_input in enumerate(conversation, 1):
        print(f"👤 用户 (第 {i} 轮): {user_input}")
        
        response = await client.chat(user_input)
        print(f"🤖 助手: {response}")
        print("-" * 80)
        
        await asyncio.sleep(1)

# 运行高级演示
asyncio.run(advanced_dialogue_demo())

启用对话的 A2A 方案的主要优势

  • 持久记忆: 跨交互记住对话

  • 上下文感知: 智能体可以引用之前的交流

  • 多智能体协调: 无缝组合多个专业智能体

  • 自然流程: 感觉像是在与一个智能助手交谈

  • 可扩展: 可以添加更多专业智能体而无需更改客户端代码

  • 用户特定: 每个用户都有自己的对话上下文

预期输出示例

👤 用户 (第 1 轮): 你好!你能帮我做一些计算吗?
🤖 助手: 您好!我很乐意帮您计算。我可以访问一个专业的数学智能体,它可以处理各种数学运算。您想计算什么?

👤 用户 (第 2 轮): 我需要计算 15 * 23
🤖 助手: 让我为您计算一下... 15 * 23 = 345。我会记住这个计算,以防您以后需要参考。您还想计算别的吗?

👤 用户 (第 3 轮): 太好了!现在你能计算那个结果的 20% 吗?
🤖 助手: 当然!取我们之前结果 (345) 的 20%:345 * 0.20 = 69。所以 345 的 20% 是 69。您想用这些数字执行任何其他计算吗?

是的,这个 A2A 方案绝对支持丰富的、有上下文的对话!关键是使用会话管理和对话感知提示(prompt)来在分布式智能体网络中维护上下文。


Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐