基于Claude API的AI应用开发:claude-toolshed框架实战指南
1. 项目概述与核心价值最近在折腾AI应用开发特别是围绕Claude API构建一些自动化工具时发现了一个挺有意思的开源项目——aksh-3141/claude-toolshed。这名字直译过来是“Claude的工具棚”听起来就挺接地气的。简单来说它不是一个独立的AI应用而是一个专门为Claude API设计的“工具集”或“工具箱”框架。如果你用过Claude的API特别是它的“工具调用”Tool Calling功能就会知道这玩意儿功能强大但用起来有点繁琐。你需要自己定义工具、处理JSON、管理会话状态代码写起来容易变得又长又乱。claude-toolshed的出现就是为了把这些脏活累活都包了让你能像搭积木一样快速、优雅地把各种功能“挂载”到Claude对话中。它的核心价值在于“提效”和“降本”。对于个人开发者或小团队它能让你在几小时内就搭建出一个功能相对完善的AI助手原型而不用花几天时间去处理底层的通信协议和状态管理。对于有经验的开发者它提供了一套清晰、可扩展的架构让你能把精力集中在业务逻辑和工具功能的实现上而不是重复造轮子。这个项目特别适合那些想基于Claude API构建复杂对话应用、智能客服、数据分析助手或者自动化工作流的人。即使你对Python和异步编程不是特别熟跟着它的文档和例子也能很快上手。2. 核心架构与设计哲学拆解2.1 什么是“工具调用”与为什么需要框架要理解claude-toolshed得先搞懂Claude API的“工具调用”机制。这其实是当前大模型应用的一个主流模式大模型本身不直接执行具体操作比如查数据库、发邮件、调用第三方API它只负责“思考”和“决策”。当用户提出一个需要具体操作才能回答的问题时比如“帮我查一下上个月的销售额”模型会“决定”需要调用哪个工具并生成一个结构化的调用请求一个JSON对象。然后你的应用程序负责接收这个请求找到对应的函数去执行拿到结果后再把结果塞回给模型由模型组织成自然语言回复给用户。这个过程听起来简单但实现起来坑不少。首先你需要严格按照Anthropic的格式定义每个工具名称、描述、参数schema。其次你要维护一个“工具注册表”把定义好的工具函数映射上去。然后在每次对话循环中你都要检查模型的返回里是否包含了工具调用请求如果有就得解析、分发、执行再把执行结果拼装好连同历史对话一起作为下一次请求的上下文发回去。状态管理、错误处理、异步执行……这些细节堆在一起代码很快就变得难以维护。claude-toolshed的设计哲学就是“约定大于配置”和“关注点分离”。它帮你把工具定义、注册、调用分发、会话管理这些通用逻辑全部封装好了。作为开发者你只需要做两件事1. 用Python函数和简单的装饰器来定义你的工具2. 告诉框架怎么连接Claude API。剩下的框架全包了。这种设计让代码结构非常清晰工具就是纯粹的业务逻辑函数而框架负责所有与AI模型交互的胶水代码。2.2 项目核心组件与工作流拆开来看claude-toolshed主要由以下几个核心组件构成它们共同协作完成一次完整的工具调用对话Tool工具这是最基本的单元。每一个工具对应一个Python函数。你需要用tool装饰器来标记它并在装饰器里提供工具的名称和描述。函数的参数和返回值类型会被框架自动用来生成符合Claude API要求的JSON Schema。比如一个查询天气的工具函数签名可能是def get_weather(city: str) - str:框架就知道这个工具需要一个字符串类型的city参数并返回一个字符串。ToolRegistry工具注册表这是一个中心化的仓库负责收集和管理所有用tool装饰过的函数。你不需要手动注册框架会在启动时自动发现并加载它们。这保证了工具定义的声明式和去中心化你可以在项目的任何地方定义工具只要它们能被导入框架就能找到。Agent/Toolset代理/工具集这是与Claude模型对话的核心执行器。你创建一个Agent实例并把你需要的工具注册表传递给它。Agent内部封装了与Claude API的通信逻辑。它的run方法是主要的入口你传入用户消息它就会自动处理整个“模型思考-调用工具-返回结果-模型回复”的循环直到模型认为不需要再调用工具给出最终答案为止。Conversation会话Agent内部维护着一个会话对象它保存了完整的对话历史包括用户消息、模型回复、工具调用和工具执行结果。这个状态是自动管理的确保了多轮对话中上下文的连贯性。整个工作流可以概括为用户输入 -Agent.run()- 框架将对话历史和可用工具列表发送给Claude - Claude返回消息或工具调用请求 - 框架解析工具调用执行对应的Python函数 - 将函数结果作为新的上下文消息发送给Claude - Claude生成最终回复 - 框架输出回复给用户。这个过程对开发者是完全透明的。3. 从零开始环境搭建与基础工具创建3.1 安装与初始配置上手的第一步是安装。claude-toolshed是一个Python库所以前提是你得有Python环境建议3.8以上。安装非常简单用pip一键搞定pip install claude-toolshed安装完成后最关键的一步是配置Claude API密钥。框架需要这个密钥来与Anthropic的服务器通信。绝对不要把密钥硬编码在代码里更不要上传到GitHub等公开平台。最安全、最规范的做法是使用环境变量。在终端里设置环境变量Linux/macOSexport ANTHROPIC_API_KEY你的实际API密钥或者在代码中通过os.environ设置仅用于临时测试生产环境不推荐import os os.environ[ANTHROPIC_API_KEY] 你的实际API密钥对于Windows用户可以在PowerShell中使用$env:ANTHROPIC_API_KEY你的实际API密钥实操心得我强烈建议使用.env文件配合python-dotenv库来管理环境变量。在项目根目录创建一个.env文件里面写上ANTHROPIC_API_KEYsk-xxx然后在代码开头加两行from dotenv import load_dotenv; load_dotenv()。这样既安全.env文件通常被.gitignore忽略又方便在不同环境开发、测试、生产切换时只需替换.env文件即可。3.2 创建你的第一个工具让我们从一个最简单的“Hello World”式工具开始感受一下框架的便捷。假设我们想创建一个工具让Claude能给我们讲个笑话。首先创建一个Python文件比如my_first_agent.py。import asyncio from claude_toolshed import tool from claude_toolshed.agent import Agent # 1. 使用装饰器定义一个工具 tool(nametell_joke, descriptionTell a random joke.) def get_random_joke() - str: 这个函数被tool装饰后就成为了一个Claude可调用的工具。 函数名本身不重要装饰器里的name才是工具在Claude眼中的标识。 description至关重要Claude根据它来决定什么时候调用这个工具。 # 这里只是一个硬编码的例子实际可以连接笑话API jokes [ 为什么程序员分不清万圣节和圣诞节因为 Oct 31 Dec 25。, 我写代码的速度取决于咖啡因的浓度和死线的距离。, 调试代码就像在雷区里找一只变色的猫而那只猫可能根本不存在。 ] import random return random.choice(jokes) # 2. 创建Agent并运行 async def main(): # 初始化Agent。默认使用最新的Claude模型。 agent Agent(tools[get_random_joke]) # 将工具函数传入 # 开始对话 response await agent.run(给我讲个笑话吧要程序员相关的。) print(Claude:, response) if __name__ __main__: asyncio.run(main())运行这个脚本你会看到Claude调用了tell_joke工具并把工具返回的笑话组织成一段友好的话术回复给你。整个过程你只需要定义函数和一句话启动对话框架自动完成了工具描述生成、API调用、结果注入的所有中间步骤。注意事项tool装饰器中的description字段是灵魂。Claude模型完全依赖这个描述来理解工具的功能。描述要清晰、具体最好说明工具的用途、输入和输出。模糊的描述会导致模型错误调用或根本不调用。例如“处理数据”就太模糊“根据城市名称查询该城市当前的天气情况和温度”就明确得多。3.3 处理带参数的复杂工具现实中的工具很少像讲笑话这么简单。大部分工具都需要输入参数。claude-toolshed利用Python的类型注解来自动生成参数schema非常智能。让我们创建一个稍微复杂点的工具一个简易的计算器能进行加减乘除。from claude_toolshed import tool from typing import Literal tool( namecalculator, descriptionPerform a basic arithmetic operation. Choose from addition (), subtraction (-), multiplication (*), or division (/). ) def calculate(a: float, b: float, operation: Literal[, -, *, /]) - float: 执行基础算术运算。 Args: a: 第一个运算数 b: 第二个运算数 operation: 运算符支持 , -, *, / Returns: 运算结果 if operation : return a b elif operation -: return a - b elif operation *: return a * b elif operation /: if b 0: return float(inf) # 简单处理除零错误实际项目应更严谨 return a / b else: raise ValueError(fUnsupported operation: {operation}) # 在Agent中使用 async def main(): agent Agent(tools[calculate]) # 你可以问“计算一下3.14乘以2.5等于多少” response await agent.run(请帮我计算 (15 7) * 3 的值。) print(response)这里有几个关键点类型注解即Schema函数参数a: float, b: float明确告诉框架这两个参数是数字类型。Claude API会据此生成{type: number}的schema。复杂类型支持operation: Literal[, -, *, /]使用了typing.Literal。这会被框架翻译成枚举类型{enum: [, -, *, /]}强制Claude必须从这几个选项里选一个避免了模型胡编乱造一个不支持的运算符。错误处理在工具函数内部进行基本的错误检查如除零并返回一个合理的值或抛出异常。框架能捕获异常并将其信息传递给Claude让模型可以向用户解释错误。运行这段代码Claude会理解你的问题自动调用calculator工具并传入正确的参数a15, b7, operation‘‘得到结果22后再调用一次a22, b3, operation‘*‘最终计算出66并组织语言回复你。这一切都是自动的、链式的。4. 构建实战一个多功能个人助理Agent理解了基础工具后我们来组装一个更有用的东西一个能查天气、记笔记、管理待办事项的个人文字助理。这个例子将涵盖更接近真实世界的场景。4.1 工具一智能天气查询我们使用一个免费的公开天气API例如Open-Meteo来获取真实数据。这涉及到网络请求所以工具函数必须是异步的async def。import aiohttp from claude_toolshed import tool from datetime import date tool(nameget_weather, descriptionGet the current weather and forecast for a given city.) async def fetch_weather(city_name: str, country_code: str CN) - str: 根据城市名和国家代码查询天气。 使用Open-Meteo API无需密钥。 # 1. 地理编码将城市名转换为经纬度 geo_url fhttps://geocoding-api.open-meteo.com/v1/search?name{city_name}country{country_code}count1 async with aiohttp.ClientSession() as session: async with session.get(geo_url) as resp: if resp.status ! 200: return f无法找到城市 {city_name} 的地理信息。 geo_data await resp.json() if not geo_data.get(results): return f未找到城市 {city_name}。请检查拼写。 location geo_data[results][0] lat, lon location[latitude], location[longitude] city_full_name location.get(name, city_name) # 2. 获取天气数据 weather_url ( fhttps://api.open-meteo.com/v1/forecast? flatitude{lat}longitude{lon} fcurrenttemperature_2m,weathercodedailyweathercode,temperature_2m_max,temperature_2m_min ftimezoneauto ) async with session.get(weather_url) as resp: if resp.status ! 200: return f获取{city_full_name}的天气数据失败。 weather_data await resp.json() # 3. 解析并格式化结果 current weather_data[current] daily weather_data[daily] # 简单映射天气代码到文字实际应用可用更全的映射表 wmo_code_map {0: 晴, 1: 少云, 2: 多云, 3: 阴天, 45: 雾, 61: 小雨, 80: 阵雨} current_weather wmo_code_map.get(current[weathercode], 未知) today daily[time][0] today_weather wmo_code_map.get(daily[weathercode][0], 未知) result f {city_full_name} 当前天气 - 温度{current[temperature_2m]}°C - 状况{current_weather} 今日({today})预报 - 最高温{daily[temperature_2m_max][0]}°C - 最低温{daily[temperature_2m_min][0]}°C - 天气{today_weather} return result实操心得对于涉及网络I/O的工具务必使用异步函数async def和像aiohttp这样的异步HTTP客户端。这能保证你的Agent在等待一个工具如网络请求返回时不会阻塞整个事件循环从而保持高响应性。同步的requests库在异步环境里会出问题。4.2 工具二简易笔记与待办管理为了简化我们用内存中的字典来模拟数据存储。在实际项目中你会连接到数据库如SQLite、PostgreSQL或云服务。from claude_toolshed import tool from typing import Optional, List # 模拟内存存储 notes_store {} todos_store [] tool(namecreate_note, descriptionCreate a new note with a title and content.) def add_note(title: str, content: str) - str: 创建一条新笔记。 if title in notes_store: return f笔记 {title} 已存在请使用更新功能或换一个标题。 notes_store[title] content return f笔记 {title} 创建成功。 tool(nameget_note, descriptionRetrieve the content of a note by its title.) def retrieve_note(title: str) - str: 根据标题获取笔记内容。 content notes_store.get(title) if content is None: return f未找到标题为 {title} 的笔记。 return f笔记 {title} 的内容\n{content} tool(nameadd_todo, descriptionAdd a new todo item.) def add_todo_item(task: str, priority: Literal[low, medium, high] medium) - str: 添加一条待办事项。 import uuid todo_id str(uuid.uuid4())[:8] new_item {id: todo_id, task: task, priority: priority, done: False} todos_store.append(new_item) return f待办事项已添加 (ID: {todo_id})。任务{task}优先级{priority}。 tool(namelist_todos, descriptionList all pending todo items, optionally filtered by priority.) def list_pending_todos(priority_filter: Optional[str] None) - str: 列出所有未完成的待办事项。 filtered [t for t in todos_store if not t[done]] if priority_filter and priority_filter in [low, medium, high]: filtered [t for t in filtered if t[priority] priority_filter] if not filtered: return 当前没有待办的事项。 if not priority_filter else f没有优先级为 {priority_filter} 的待办事项。 result 待办事项列表\n for item in filtered: result f- [{item[id]}] {item[task]} (优先级: {item[priority]})\n return result这个工具集展示了几个重要模式工具分组将相关的操作笔记的增查、待办的增列定义在同一个模块里逻辑清晰。可选参数priority_filter: Optional[str] None表示这个参数可以省略。Claude在调用时如果用户没提优先级就不会传这个参数。状态持久化目前数据存在内存里程序重启就没了。这是为了演示的简化。生产环境必须使用外部持久化存储并在工具函数中实现读写。4.3 组装并运行多功能Agent现在我们把所有工具组装起来创建一个真正的个人助理。import asyncio from claude_toolshed.agent import Agent # 假设上面的工具定义都在同一个文件或已被导入 from my_weather_tool import fetch_weather from my_note_tools import add_note, retrieve_note, add_todo_item, list_pending_todos async def main(): # 创建Agent传入所有工具 agent Agent( tools[fetch_weather, add_note, retrieve_note, add_todo_item, list_pending_todos], modelclaude-3-5-sonnet-20241022, # 可以指定模型版本 max_tokens1024, ) # 模拟一个多轮对话场景 conversation [ 今天北京天气怎么样, 把‘项目会议要点’记下来内容是‘讨论claude-toolshed集成方案负责人张三下周交付原型’。, 我还有哪些高优先级的待办事项, 帮我计算一下(1200 - 450) / 30 等于多少, # 我们没加计算器工具看Claude如何处理 ] print( 个人助理对话开始 ) for user_msg in conversation: print(f\n[用户]: {user_msg}) response await agent.run(user_msg) print(f[助理]: {response}) print( 对话结束 ) if __name__ __main__: asyncio.run(main())运行这个脚本你会看到一个连贯的对话。Claude会根据你的问题智能地选择调用get_weather、create_note或list_todos工具。当你问到一个它没有对应工具的问题如计算时它会老实地回答“我无法执行计算”或者尝试用推理给出一个近似答案取决于模型。这展示了Agent的能力边界。5. 高级特性与生产级考量当你想把基于claude-toolshed的原型变成真正可用的服务时有几个高级特性和工程化问题必须考虑。5.1 会话记忆与上下文管理默认情况下Agent对象会维护一个会话记住之前的所有对话和工具调用结果。这对于多轮对话至关重要。但有时你需要更精细的控制新建会话每次调用agent.run()默认是延续上次会话。如果想开始一个全新话题可以创建新的Agent实例或者使用agent.new_session()方法如果框架提供。上下文长度与总结Claude模型有上下文窗口限制如200K tokens。超长的对话历史会被截断可能导致遗忘早期信息。对于超长对话一个高级策略是定期让模型自己总结之前的对话要点然后将总结作为新的“系统提示”或压缩后的历史再继续后续对话。claude-toolshed本身可能不直接提供此功能但你可以通过拦截或包装agent.run的输入输出来实现。会话持久化如果你想实现“用户下次登录还能看到上次对话”的功能就需要把agent.conversation或其中的消息列表序列化如转成JSON保存到数据库。下次初始化Agent时再反序列化加载进去。5.2 错误处理与工具鲁棒性工具函数在执行时可能出错网络超时、API限流、无效输入等。框架通常能捕获异常并将其传递给Claude模型模型会尝试向用户解释错误。但我们可以做得更好from claude_toolshed import tool import aiohttp from aiohttp import ClientError, ClientTimeout tool(namerobust_weather, descriptionA more robust weather query tool.) async def get_weather_safe(city: str) - str: try: # ... 之前的天气查询逻辑 ... async with aiohttp.ClientSession(timeoutClientTimeout(total10)) as session: # ... 发起请求 ... pass except ClientError as e: # 网络相关错误 return f查询天气时网络出现错误{str(e)}。请稍后重试。 except TimeoutError: return 天气查询请求超时请检查网络或稍后再试。 except KeyError as e: # API返回数据格式不符合预期 return f处理天气数据时遇到意外格式错误信息{str(e)}。 except Exception as e: # 捕获所有其他未预见的错误 # 生产环境应记录日志如logging.error(e)而不是直接返回给用户 return 系统内部处理天气请求时发生未知错误。核心原则工具函数应该尽可能内部消化错误并返回一个对用户友好的字符串信息。避免让未处理的异常直接抛出导致整个Agent会话崩溃。同时一定要记录详细的错误日志使用logging模块方便后台排查。5.3 性能优化与超时控制工具执行超时如果一个工具执行时间过长比如一个复杂的数据库查询或慢速的第三方API会拖累整个对话响应。可以为工具函数设置超时机制。Python的asyncio.wait_for可以派上用场。import asyncio from functools import wraps def tool_with_timeout(timeout_seconds30): def decorator(func): wraps(func) async def wrapper(*args, **kwargs): try: return await asyncio.wait_for(func(*args, **kwargs), timeouttimeout_seconds) except asyncio.TimeoutError: return f工具 {func.__name__} 执行超时{timeout_seconds}秒请重试或简化请求。 return wrapper return decorator tool(nameslow_query) tool_with_timeout(10) # 自定义超时装饰器要放在tool里面 async def potentially_slow_operation(): await asyncio.sleep(15) # 模拟慢操作 return Done异步并发如果多个工具之间没有依赖关系且框架支持可以考虑让它们并发执行。不过标准的Claude工具调用模式是顺序的模型思考-调用一个工具-得到结果-再思考所以通常不需要。5.4 安全性与权限控制这是企业级应用无法回避的问题。你不能让用户通过Claude调用任何工具。工具级权限最简单的办法是根据用户身份动态构建不同的工具列表。例如普通用户只能使用查询天气和创建笔记而管理员则多一个系统管理工具。在创建Agent时根据当前登录用户传入不同的tools列表即可。参数校验与净化工具函数必须对输入参数进行严格的校验。即使Claude模型已经根据schema生成了参数也要防范潜在的注入攻击或非法值。例如一个删除文件工具必须校验文件路径是否在允许的目录内。tool(nameread_file) def read_allowed_file(filepath: str) - str: import os # 限制只能读取特定安全目录下的文件 SAFE_BASE_DIR /var/www/safe_data/ full_path os.path.abspath(os.path.join(SAFE_BASE_DIR, filepath)) # 防止目录遍历攻击 if not full_path.startswith(os.path.abspath(SAFE_BASE_DIR)): return 错误无权访问该路径。 if not os.path.exists(full_path): return 文件不存在。 # ... 读取文件 ...访问令牌Token管理如果你的工具需要调用需要认证的外部API如公司内部系统千万不要把API密钥硬编码在工具函数里。应该从安全的配置服务或当前用户的会话信息中获取。6. 常见问题、调试技巧与避坑指南在实际开发和集成claude-toolshed的过程中你肯定会遇到各种问题。下面是我踩过的一些坑和总结的排查思路。6.1 工具不被调用检查描述和对话历史问题你明明定义了一个工具但Claude在对话中从来不调用它。排查步骤检查工具描述这是最常见的原因。描述必须清晰、无歧义准确反映工具的功能和适用场景。对比一下差描述“处理数据”好描述“根据给定的股票代码查询该股票最近一天的收盘价和涨跌幅。”用后者当用户问“苹果股价怎么样”时模型更容易匹配到。检查工具参数Schema在Agent初始化后可以打印出工具列表的schema看看。agent Agent(tools[my_tool]) for t in agent.tools: print(t.name, t.schema) # 查看生成的JSON Schema是否符合预期确保参数类型string, number, boolean等定义正确。 3.检查对话历史/系统提示有时之前的对话历史会把模型“带偏”。或者如果你设置了很强的系统提示如“你是一个只负责翻译的助手”模型可能会自我限制不去调用其他功能的工具。尝试开启一个新的会话新建Agent测试。 4.模型能力确认你使用的Claude模型版本支持工具调用。目前claude-3-opus、claude-3-sonnet和claude-3-haiku都支持但不同版本在工具调用的准确性和主动性上可能有细微差别。6.2 工具调用参数错误强化类型提示和描述问题Claude调用了工具但传入的参数值类型不对或格式错误导致工具函数执行失败。解决方案使用更精确的类型除了基本的str,int,float,bool多用typing模块。List[str],Dict[str, int],Literal[“yes“, “no“]都能生成更精确的schema约束模型的输出。在描述中明确格式如果参数有特定格式如日期“YYYY-MM-DD”邮箱地址一定要在工具描述或参数描述中写明。例如tool(description“查询日历。date参数格式必须为YYYY-MM-DD。”)工具函数内部做防御性校验这是最后一道防线。即使参数不对也要优雅处理。tool(namesend_email) def send_email(to: str, subject: str, body: str) - str: import re # 简单的邮箱格式校验 if not re.match(r[^][^]\.[^], to): return f错误邮箱地址‘{to}’格式无效。 # ... 发送逻辑 ...6.3 异步工具函数卡住或报错确保正确的异步上下文问题在运行异步工具时程序卡住、报错Event loop is closed或Task was destroyed but it is pending。根本原因异步事件循环管理不当。claude-toolshed内部是异步的你的异步工具函数也必须在正确的事件循环中运行。解决与避坑入口点使用asyncio.run()这是最安全的方式如我们所有例子所示。避免在同步函数中调用异步Agent如果你在Flask、Django非异步视图这样的同步Web框架中集成不能直接await agent.run()。你需要使用asyncio.run()在一个新的事件循环中运行或者使用asyncio.create_task并在一个已运行的事件循环中管理。更推荐使用支持异步的Web框架如FastAPI、Sanic、Quart。管理好HTTP会话对于aiohttp不要在每次工具调用时都创建新的ClientSession这很耗资源且可能导致端口耗尽。最好在工具函数外部创建并复用session或者使用框架提供的上下文管理。6.4 如何调试复杂的工具调用逻辑当对话逻辑复杂工具调用链很长时看清内部发生了什么很有必要。开启详细日志claude-toolshed可能内置了日志功能。查看其文档看如何设置日志级别如logging.basicConfig(levellogging.DEBUG)来打印模型请求、响应和工具调用的详细信息。手动打印中间状态你可以在工具函数内部和agent.run前后打印信息。async def main(): agent Agent(tools[...]) user_input “复杂问题...” print(f“用户输入: {user_input}”) # 你可以先看看Agent准备发送给Claude的消息和工具列表 # 这需要查看Agent内部属性具体取决于框架暴露的接口 response await agent.run(user_input) print(f“模型最终回复: {response}”) # 查看完整的对话历史 for msg in agent.conversation.messages: # 假设属性名是这个 print(f“{msg[‘role’]}: {msg[‘content’]}”)使用Claude API Playground或Console有时直接把Agent构建的请求包括系统提示、历史消息、工具定义复制到Anthropic的官方控制台里手动发送能更直观地看到模型的“思考过程”和原始响应有助于调试工具选择或参数生成的问题。6.5 成本控制与Token使用优化Claude API是按Token收费的。复杂的工具调用和长对话历史会快速消耗Token。监控Token用量API的响应头或响应体里通常会包含本次请求消耗的输入/输出Token数。定期统计做到心中有数。精简工具描述在保证清晰的前提下工具描述不要太啰嗦。每个Token都要花钱。定期清理对话历史对于长时间运行的会话定期让模型总结一下然后重置历史只保留总结作为新的系统消息。这能有效控制上下文长度。设置max_tokens参数在创建Agent时合理设置max_tokens防止模型生成过于冗长的回复。最后再分享一个我个人的小技巧在项目初期可以先用一个简单的、硬编码返回值的工具来测试整个流程是否跑通然后再去实现复杂的、依赖外部服务的真实逻辑。这能帮你快速隔离问题确定是工具定义的问题、模型调用的问题还是外部API集成的问题。claude-toolshed这个框架把复杂的AI交互抽象得非常干净让你能专注于创造有价值的工具本身而不是陷在协议和状态管理的泥潭里。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2610359.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!