使用 A2A Python SDK 实现 CurrencyAgent
谷歌官方的a2a-python SDK最近频繁的更新,我们的教程也需要跟着更新,这篇文章,我们通过 a2a-python sdk的 0.2.3
版本,实现一个简单的CurrencyAgent。
https://a2aprotocol.ai/blog/a2a-sdk-currency-agent-tutorial-zh
目录
- 源码
- 准备
- 详细过程
- 创建项目
- 创建虚拟环境
- 添加依赖
- 配置环境变量
- 创建 Agent
- 核心功能
- 系统架构
- 系统提示词
- 主要方法
- 工作流程
- 响应格式
- 错误处理
- 测试 Agent
- 实现 AgentExecutor
- 实现 AgentServer
- AgentSkill
- AgentCard
- AgentServer
- 运行
- 运行 Server
- 运行 Client
源码
项目的源码在a2a-python-currency,欢迎 star 。
准备
- uv 0.7.2,用来进行项目管理
- Python 3.13+,一定要这个版本以上,a2a-python 的要求
- openai/openrouter 的 apiKey,baseURL,我使用的是 OpenRouter,有更多的模型可以选择。
详细过程
创建项目:
uv init a2a-python-currency
cd a2a-python-currency
创建虚拟环境
uv venv
source .venv/bin/activate
添加依赖
uv add a2a-sdk uvicorn dotenv click
配置环境变量
echo OPENROUTER_API_KEY=your_api_key >> .env
echo OPENROUTER_BASE_URL=your_base_url >> .env# example
OPENROUTER_API_KEY=你的OpenRouter API密钥
OPENROUTER_BASE_URL="https://openrouter.ai/api/v1"
创建 Agent
完整的代码如下:
import logging
import json
from typing import Any, Dict, List, Optional
import httpx
from os import getenv
from dotenv import load_dotenv
from collections.abc import AsyncIterableload_dotenv()logger = logging.getLogger(__name__)class CurrencyAgent:"""Currency Conversion Agent using OpenAI API."""SYSTEM_PROMPT = """You are a specialized assistant for currency conversions.
Your sole purpose is to use the 'get_exchange_rate' tool to answer questions about currency exchange rates.
If the user asks about anything other than currency conversion or exchange rates,
politely state that you cannot help with that topic and can only assist with currency-related queries.
Do not attempt to answer unrelated questions or use tools for other purposes.You have access to the following tool:
- get_exchange_rate: Get current exchange rate between two currenciesWhen using the tool, respond in the following JSON format:
{"status": "completed" | "input_required" | "error","message": "your response message"
}If you need to use the tool, respond with:
{"status": "tool_use","tool": "get_exchange_rate","parameters": {"currency_from": "USD","currency_to": "EUR","currency_date": "latest"}
}
Note: Return the response in the JSON format, only json is allowed.
"""def __init__(self):self.api_key = getenv("OPENROUTER_API_KEY")self.api_base = getenv("OPENROUTER_BASE_URL")self.model = "anthropic/claude-3.7-sonnet"self.conversation_history: List[Dict[str, str]] = []async def get_exchange_rate(self,currency_from: str = 'USD',currency_to: str = 'EUR',currency_date: str = 'latest',) -> Dict[str, Any]:"""Get current exchange rate between currencies."""try:response = httpx.get(f'https://api.frankfurter.app/{currency_date}',params={'from': currency_from, 'to': currency_to},)response.raise_for_status()data = response.json()if 'rates' not in data:logger.error(f'rates not found in response: {data}')return {'error': 'Invalid API response format.'}logger.info(f'API response: {data}')return dataexcept httpx.HTTPError as e:logger.error(f'API request failed: {e}')return {'error': f'API request failed: {e}'}except ValueError:logger.error('Invalid JSON response from API')return {'error': 'Invalid JSON response from API.'}async def _call_openai(self, messages: List[Dict[str, str]]) -> Dict[str, Any]:"""Call OpenAI API through OpenRouter."""async with httpx.AsyncClient() as client:response = await client.post(f"{self.api_base}/chat/completions",headers={"Authorization": f"Bearer {self.api_key}","Content-Type": "application/json",},json={"model": self.model,"messages": messages,"temperature": 0.7,"stream": False,},)response.raise_for_status()return response.json()async def stream(self, query: str, session_id: str) -> AsyncIterable[Dict[str, Any]]:"""Stream the response for a given query."""# Add user message to conversation historyself.conversation_history.append({"role": "user", "content": query})# Prepare messages for API callmessages = [{"role": "system", "content": self.SYSTEM_PROMPT}] + self.conversation_history# Get response from OpenAIresponse = await self._call_openai(messages)assistant_message = response["choices"][0]["message"]["content"]print(assistant_message)try:# Try to parse the response as JSONparsed_response = json.loads(assistant_message)# If it's a tool use requestif parsed_response.get("status") == "tool_use":tool_name = parsed_response["tool"]parameters = parsed_response["parameters"]# Yield tool usage statusyield {"is_task_complete": False,"require_user_input": False,"content": "Looking up the exchange rates..."}if tool_name == "get_exchange_rate":# Yield processing statusyield {"is_task_complete": False,"require_user_input": False,"content": "Processing the exchange rates..."}tool_result = await self.get_exchange_rate(**parameters)# Add tool result to conversation historyself.conversation_history.append({"role": "assistant","content": json.dumps({"tool_result": tool_result})})# Get final response after tool usefinal_response = await self._call_openai(messages)final_message = final_response["choices"][0]["message"]["content"]parsed_response = json.loads(final_message)# Add assistant response to conversation historyself.conversation_history.append({"role": "assistant",
相关文章:
使用 A2A Python SDK 实现 CurrencyAgent
谷歌官方的a2a-python SDK最近频繁的更新,我们的教程也需要跟着更新,这篇文章,我们通过 a2a-python sdk的 0.2.3 版本,实现一个简单的CurrencyAgent。 https://a2aprotocol.ai/blog/a2a-sdk-currency-agent-tutorial-zh 目录 源码准备详细过程 创建项目创建虚拟环境添加依…...
qt浏览文件支持惯性
#include <QApplication> #include <QListWidget> #include <QScroller> #include <QScrollerProperties>int main(int argc, char *argv[]) {QApplication app(argc, argv);// 创建列表控件并添加示例项QListWidget listWidget;for (int i 0; i <…...
Python类的力量:第六篇:设计模式——Python面向对象编程的“架构蓝图”
文章目录 前言:从“代码堆砌”到“模式复用”的思维跃迁 一、创建型模式:对象创建的“智能工厂”1. 单例模式(Singleton):全局唯一的“资源管家”2. 工厂模式(Factory):对象创建的“…...

[实战]用户系统-2-完善登录和校验以及VIP
这里写目录标题 完善登录和校验新建lib-auth创建配置引入配置和JWT完善登录基本登录单点登录多点登录校验和拦截编写守卫编写装饰器使用完善VIP修改mysql模型编写vip守卫代码进度完善登录和校验 之前我们模拟过用户的登录,本节将实现token的生成,校验,redis做黑名单。我们需…...
负载均衡笔记
并发数—同时服务的调用方的数量 吞吐量—单位时间内,能接受和返回的数据请求量 TPS。 Transaction事务 QPS。Query 请求/查询 优化点: 减少并发数—防止并非过高 低级—限流—可用的用户少了?! 多开几个口—分流 DNS 解析域…...

印度语言指令驱动的无人机导航!UAV-VLN:端到端视觉语言导航助力无人机自主飞行
作者:Pranav Saxena, Nishant Raghuvanshi and Neena Goveas单位:比尔拉理工学院(戈瓦校区)论文标题:UAV-VLN: End-to-End Vision Language guided Navigation for UAVs论文链接:https://arxiv.org/pdf/250…...

mysql都有哪些锁?
MySQL中的锁机制是确保数据库并发操作正确性和一致性的重要组成部分,根据锁的粒度、用途和特性,可以分为多种类型。以下是MySQL中常见的锁及其详细说明: 一、按锁的粒度划分 行级锁(Row-level Locks) 描述:…...
解锁未来AI:使用DACA模式和Agentic技术提高开发效率
学习Agentic AI:Dapr Agentic Cloud Ascent (DACA)设计模式的应用与演进 背景介绍 近年来,Agentic AI(代理型人工智能)的概念在学术界和产业界掀起了一阵热潮。Agentic AI指的是能够自主感知、决策和行动的智能体系统,它们不仅改变了我们与技术互动的方式,也为行业发展…...

HarmonyOS NEXT 使用 relationalStore 实现数据库操作
大家好,我是V哥。在 HarmonyOS NEXT 开发中,如何操作数据库,V 哥在测试中总结了以下学习代码,分享给你,如何想要系统学习鸿蒙开发,可以了解一下 V 哥最近刚刚上架出版的 《HarmonyOS 鸿蒙开发之路 卷2 从入…...

R语言学习--Day04--数据分析技巧
在清洗完数据,在对数据分析前,我们要懂得先梳理一下我们的逻辑,即数据是什么形式的,要进行哪种分析,有可能呈现什么特点,进而再想怎么处理数据去画图可以最大程度地凸显我们要的特点。 一般来讲࿰…...

SRS流媒体服务器之RTC播放环境搭建
环境概述 srs版本 commit 44f0c36b61bc7c3a1d51cb60be0ec184c840f09d Author: winlin <winlinvip.126.com> Date: Wed Aug 2 10:34:41 2023 0800Release v4.0-r5, 4.0 release5, v4.0.271, 145574 lines. rtc.conf # WebRTC streaming config for SRS. # see full.…...

Android 性能优化入门(三)—— ANR 问题分析
需要清楚 ANR 的概念、类型、如何产生以及如何定位分析。 1、概述 1.1 ANR 的概念 ANR(Application Not Responding)应用程序无响应。如果你应用程序在主线程被阻塞太长时间,就会出现 ANR,通常出现 ANR,系统会弹出一…...
用HTML5实现实时ASCII艺术摄像头
用HTML5实现实时ASCII艺术摄像头 项目简介 这是一个将摄像头画面实时转换为ASCII字符艺术的Web应用,基于HTML5和原生JavaScript实现。通过本项目可以学习到: 浏览器摄像头API的使用Canvas图像处理技术实时视频流处理复杂DOM操作性能优化技巧 功能亮点…...

鸿蒙Flutter实战:22-混合开发详解-2-Har包模式引入
以 Har 包的方式加载到 HarmonyOS 工程 创建工作 创建一个根目录 mkdir ohos_flutter_module_demo这个目录用于存放 flutter 项目和鸿蒙项目。 创建 Flutter 模块 首先创建一个 Flutter 模块,我们选择与 ohos_app 项目同级目录 flutter create --templatemodu…...

游戏引擎学习第302天:使用精灵边界进行排序
在 game_render_group.cpp 中:正确计算 GetBoundFor() 里的 SpriteBound 值 我们正在进行游戏的排序问题调试。虽然这是一个二维游戏,但包含一些三维元素,因此排序变得比较复杂和棘手。混合二维和三维元素时,需要依赖一些比较主观…...

SpringBoot+MyBatis
切换数据库连接词 引入数据库连接词的依赖,配置数据库连接池的类型; 编写测试类: package org.example.threelayerdecouplingdomeapplication2;import org.example.threelayerdecouplingdomeapplication2.mapper.UserMapper; import org.ex…...

wireshark: Display Filter Reference
https://www.wireshark.org/docs/dfref/// 这个里面的扩展功能还是很强大,可以帮着问题分析。支持大量的自定义化的字段读取功能,支持很多的协议。 https://www.wireshark.org/docs/dfref///f/frame.html frame.time_delta Time delta from previous ca…...

Java基础 Day19
一、泛型(JDK5引入) 1、基本概念 在编译阶段约束操作的数据类型,并进行检查 好处:统一数据类型,将运行期的错误提升到了编译期 泛型的默认类型是 Object 2、泛型类 在创建类的时候写上泛型 在创建具体对象的时候…...

VMware+Windows 11 跳过安装阶段微软账号登录
OOBE 阶段 来到这里 断开网络适配器 VMware右下角,点击网络适配器,断开连接 同时按下 Shift 和 F10 ,打开命令提示符(cmd.exe) 输入 oobe\BypassNRO.cmd 并回车 接下来正常进行即可...

HarmonyOS开发-应用间跳转
1. HarmonyOS开发-应用间跳转 在鸿蒙中,我们再开发过程当中或多或少都会遇见想要从一个App的页面跳转至另一个App的页面,这个时候我们要怎么进行跳转呢,其实在HarmonyOS开发者文档中只需要用到Want对象和startAbility()方法进行跳转就可以了。 1.1. 实现 (1)我们要先准备两个…...
网工每日一练
2025/5/22.每日一练(单选题) 路由器在查找路由表时存在最长匹配原则,这里的长度指的是以下哪个参数? A. NextHopIP地址的大小 B. 路由协议的优先级 C. Cost D. 掩码的长度 路由器在查找路由表时遵循的最长匹配原则中,“…...
使用 Navicat 17 for PostgreSQL 时,请问哪个版本支持 PostgreSQL 的 20150623 版本?还是每个版本都支持?
🧑💻 PostgreSQL 用户 使用 Navicat 17 for PostgreSQL 时,请问哪个版本支持 PostgreSQL 的 20150623 版本?还是每个版本都支持? 🧑🔧 官方技术中心 Navicat Premium 17 和 Navicat for P…...

校园二手交易系统
该交易平台分为两部分,前台和后台。用户在前台进行商品选购以及交易;管理员登录后台可以对商品进行维护,主要功能包含: 后台系统的主要功能模块如下: 登录功能、注册功能、后台首页 系统设置: 菜单管理、…...

基于pycharm,python,flask,sklearn,orm,mysql,在线深度学习sql语句检测系统
详细视频:【基于pycharm,python,flask,sklearn,orm,mysql,在线深度学习sql语句检测系统-哔哩哔哩】 https://b23.tv/JLQDwNn...
LangChain02-Agent与Memory模块
Agent与Memory模块深度解析 1. Agent模块原理 1.1 ReAct框架的实现机制 Agent是LangChain中最具智能化的组件,其核心思想基于 ReAct框架(Reasoning Acting),即通过 思维(Thought) 和 行动(Ac…...

upload-labs通关笔记-第17关文件上传之二次渲染gif格式
系列目录 upload-labs通关笔记-第1关 文件上传之前端绕过(3种渗透方法) upload-labs通关笔记-第2关 文件上传之MIME绕过-CSDN博客 upload-labs通关笔记-第3关 文件上传之黑名单绕过-CSDN博客 upload-labs通关笔记-第4关 文件上传之.htacess绕过-CSDN…...
计算机网络学习20250525
应用层协议原理 创建一个网络应用,编写应用程序,这些应用程序运行在不同的端系统上,通过网络彼此通信 不需要在网络核心设备(路由器,交换机)上写应用程序网络应用程序工作在网络层以下将应用程序限制在端系统上促进应用程序迅速研发和部署,将复杂问题放到网络边缘网络应…...

STM32中的SPI通信协议
IIC和SPI的对比 IIC是半双工的通信,无法同时收发信息;SPI是全双工通讯,可以同时收发信息;IIC的通讯协议较复杂,而SPI通讯协议较简单;IIC需要通过地址选择从机,而SPI只主要一个引脚即可选中从机…...

从版本控制到协同开发:深度解析 Git、SVN 及现代工具链
前言:在当今软件开发的浪潮中,版本控制与协同开发无疑扮演着举足轻重的角色。从最初的单兵作战到如今大规模团队的高效协作,一套成熟且得力的版本控制系统以及围绕其构建的现代工具链,已然成为推动软件项目稳步前行的关键引擎。今…...
redis Pub/Sub 简介 -16 (PUBLISH、SUBSCRIBE、PSUBSCRIBE)
Redis Pub/Sub 简介:PUBLISH、SUBSCRIBE、PSUBSCRIBE Redis Pub/Sub 是一种强大的消息传递范例,可在应用程序的不同部分之间实现实时通信。它是构建可扩展和响应式系统的基石,允许组件在没有直接依赖的情况下进行交互。本章将全面介绍 Redis…...