ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WorkBuddy开放平台实战:从零搭建每日AI资讯简报Agent

WorkBuddy开放平台实战:从零搭建每日AI资讯简报Agent 上周我把一个每天早上要花十五分钟人工完成的活儿——整理 AI 行业资讯并写成简报发给团队——变成了 WorkBuddy 开放平台上跑的 Agent 定时任务。从注册开发者账号到最终上线整个过程两天就打通了。这篇文章就是把这条完整路径拆开讲一遍从 WorkBuddy 开放平台的能力边界到模型接入、Skill 工具调用、记忆管理、最后部署成带触发器 Agent 应用的每一步。如果你是一个个人开发者之前只调过大模型 API还没系统接触过 Agent 开发这篇文章应该能帮你省掉我去翻文档、试错的那两天。1. 先别急着写代码WorkBuddy 开放平台到底开放了什么很多人在接触一个开放平台时第一反应是去看 API 文档、找 SDK然后直接开始写代码。其实对于 Agent 这种偏应用层的产品最值钱的不是那几行调用代码而是平台帮你封装好的运行时能力。WorkBuddy 开放平台给我的第一感觉就是它不像普通 API 平台那样只给你一堆数据接口而是把开发一个 Agent 应用这件事本身做成了可配置、可编程的流程。1.1 平台能力地图Agent 运行时、Skill 协议、触发链路我接入之后把 WorkBuddy 开放平台的能力大致分成四层这样理解起来比较清晰Agent 运行时这层负责把大模型 API、会话管理、工具调用循环、错误处理这些底层的脏活累活接住。你不需要自己维护模型返回 tool_call 之后怎么把结果回传这个循环平台会在内部完成多轮推理。Skill 协议这是个人开发者最需要花精力设计的部分。Skill 本质上是一个可以被模型动态调用的外部函数平台会把你的函数定义转换成模型能理解的 JSON Schema模型在推理过程中决定是否需要调用它。触发链路支持手动触发、定时 Cron 触发、Webhook 入站触发。这意味着 Agent 不只能你问我答还能主动按时干活。可观测性每次运行的输入输出、工具调用记录、Token 消耗、耗时都在控制台里有记录方便排查问题。理解这四层之后你会发现 WorkBuddy 开放平台解决的核心问题不是怎么调大模型而是怎么把大模型放进去做一个真正能干活的自动化系统。个人开发者自己从零实现这些能力不是不行要写的东西很多而且很容易在小细节上翻车。1.2 为什么个人开发者值得选它我的判断标准很简单这个平台能不能让我把精力花在业务逻辑而不是基础设施上。对比自建方案如果我要自己做一个具备记忆和工具调用能力的 Agent需要处理模型 API 接入、工具调用循环、上下文管理、任务队列、定时调度还要考虑并发和失败重试。每一块都是可以深挖的坑。WorkBuddy 开放平台把这些整合成了配置项和 API让我可以把注意力集中在三件事上模型选型、Skill 设计、指令设计。另一个让我选择它的理由是成本可控。平台本身提供的是应用托管和编排能力模型推理费用按实际调用量计费。个人开发者可以先从低成本的模型服务商开始跑通流程之后再根据效果决定要不要换更强的模型。这种低门槛开始、按需升级的思路对个人项目非常友好。1.3 一个贯穿全文的目标每日行业简报 Agent为了让整篇文章不是空谈概念我给自己定了一个具体目标实现一个每日行业简报 Agent。它的工作流程是这样的每天早上 8 点平台通过定时触发器唤醒 Agent。Agent 调用我编写的 Skill 去获取指定领域的公开资讯然后按照我设定的指令格式生成一份简报最后把结果推送到团队群机器人。如果某个步骤失败Agent 会自动重试并把错误记录到日志。这个目标虽然听起来简单但完整覆盖了 Agent 开发的全部关键环节模型接入、Skill 编写、自定义指令、记忆管理、触发调度和稳定性处理。后面的内容全部围绕这个目标展开你可以直接照着做然后把领域换成自己关心的方向。2. 接入前最容易卡住的三个环节我自己在正式调用第一个接口之前其实已经浪费了小半天时间。原因不是功能有多复杂而是几个边缘环节没搞清楚。这里把它们单独拎出来讲因为这些坑基本每个人都会遇到。2.1 开发者账号与 API Key 的申请逻辑WorkBuddy 开放平台的开发者账号申请流程比较常规注册账号、实名认证、进入开发者后台创建应用。创建应用之后会拿到一组 App ID 和 API Key。有一点需要注意API Key 的权限范围可以在后台配置。比如你可以限制这个 Key 只能调用某个 Agent、不能修改应用配置。个人开发阶段我建议权限给得保守一点不要让一个 Key 同时拥有管理和调用权限省得代码仓库泄露之后被拿去改你的配置。密钥的处理方式也要养成好习惯。不要把它硬编码在代码里更不要提交到 Git 仓库。我本地用的是.env文件配合python-dotenv加载。.gitignore里把.env加进去这个动作虽小能避免很多不必要的麻烦。2.2 配额、频率与成本边界要先问清楚这一步是我第一天浪费时间的重灾区。我刚开始只关注了接口文档没有仔细看配额说明结果第一轮压测就把单日请求上限打满了导致后面真实验证时接口返回 429。接入之前一定要确认三个数字每分钟 API 请求次数上限单次任务的运行时长上限计费维度按 Token 数还是按调用次数个人开发者做 Agent 应用很容易忽略成本问题。模型输出 1000 个 Token 和输出 5000 个 Token成本能差出几倍。WorkBuddy 开放平台的 Agent 配置里可以对单次输出的 Token 数做限制比如把max_output_tokens设置成 800既能控制成本也能防止模型在某些异常场景下无限生成。这个配置我建议在第一个 Agent 创建时就设置好别等月底对账才发现超了。2.3 开发环境准备一个干净的 Python 虚拟环境就够WorkBuddy 开放平台提供的 API 风格很通用一个 Python 3.10 环境加requests库就能跑通全部流程。如果你要开发自定义 Skill 并通过 SDK 注册需要安装官方 SDK但我建议刚开始先用纯 HTTP 方式调通一次再引入 SDK这样遇到问题更容易定位。我本地的环境准备是这样mkdir workbuddy-agent-demo cd workbuddy-agent-demo python3 -m venv venv source venv/bin/activate pip install requests python-dotenv touch .env.env里面放两类密钥WorkBuddy 开放平台的 API Key 和模型服务商的 API Key。两类密钥分开存放、分开加载清晰一点。环境准备这部分没有太多技术含量但值得认真做因为后面所有的调试和运行都依赖这个基础。3. 打通第一行调用模型接入与 Agent 最小运行闭环环境准备好之后下一步不是直接写 Skill而是把模型接入这个地基打好。WorkBuddy 开放平台允许你自己配置模型供应商这相当于给了你选择权。如果你只用平台内置的模型也能跑通但自定义供应商的好处是可以接入你自己已有的模型账号成本更可控模型版本选择也更自由。3.1 在 WorkBuddy 中注册模型供应商我选择的模型服务商是 DeepSeek 开放平台核心原因是它的 API 兼容 OpenAI 的调用格式而且成本低适合个人开发者频繁调试。注册模型供应商时需要填三类信息供应商名称、API 地址和模型名称列表。curl -X POST https://openapi.workbuddy.example.com/v1/model-providers \ -H Authorization: Bearer $WORKBUDDY_API_KEY \ -H Content-Type: application/json \ -d { name: deepseek, type: openai_compatible, base_url: https://api.deepseek.com/v1, api_key_env: DEEPSEEK_API_KEY, models: [deepseek-chat, deepseek-reasoner] }这里有一个细节值得注意api_key_env字段是用来指定模型服务商密钥的环境变量名的。WorkBuddy 平台服务端会从它自己的环境变量里读取这个值也就是说你的模型服务商密钥并不需要出现在本地方便地存储。这个设计可以避免在客户端请求里传输模型供应商密钥安全性更好。我最初在这里踩过一个认知上的坑以为需要在每一次 Agent 调用请求里都带上模型服务商的 Key。实际上模型供应商的配置是一次性的配置完成之后调用 Agent 时只需要带 WorkBuddy 开放平台签发的 API Key 就可以了。3.2 最小 Agent 请求的报文结构与返回解析注册完模型供应商之后下一步是创建自己的 Agent。在 WorkBuddy 开放平台后台创建 Agent 时会要求选择一个模型我选的是deepseek-chat日常处理资讯整理足够。创建完成后可以用一个非常小的请求来验证整条链路是否通import os import requests from dotenv import load_dotenv load_dotenv() WB_API_KEY os.getenv(WORKBUDDY_API_KEY) resp requests.post( https://openapi.workbuddy.example.com/v1/agent/run, headers{Authorization: fBearer {WB_API_KEY}}, json{ agent_id: daily_briefing, session_id: test-001, messages: [ {role: user, content: 今天人工智能领域有什么值得关注的消息} ], config: { max_output_tokens: 800 } }, timeout60 ) print(resp.status_code) print(resp.json())返回的 JSON 结构大致是三层外层是状态信息中间是output_text和usage特殊情况下还会出现tool_calls字段。output_text是最终展示给用户的内容usage里包含本次调用消耗的 Token 数tool_calls只有模型决定调用 Skill 时才会出现。这个最小请求跑通意味着平台侧的模型接入、Agent 运行时、基础会话管理都是正常的。后面的所有开发都建立在这个基础之上。3.3 把对话循环跑起来从调一次 API到多轮会话最小请求跑通之后很多人会直接进入 Skill 开发但我建议先做一轮完整对话循环的验证。因为 Agent 和普通 API 一个很大的不同在于它的执行过程不是一个请求-响应那么简单而是模型推理-调用工具-返回结果-再次推理的循环。在 WorkBuddy 开放平台的请求参数里有个字段叫mode可以设置成auto。在auto模式下平台会自动完成工具调用循环遇到需要 Skill 的情况会自己调用不需要开发者手动干预。我把这个模式称为傻瓜模式适合前期验证和日常低频场景。还有一种manual模式平台会把模型选择好的工具调用返回给开发者由开发者来执行并回传结果。这个模式适合调试因为你可以在每一步插入日志看清楚模型到底选择了什么工具、为什么选择。个人开发阶段我建议两种模式都试用一下先manual理解流程再切到auto浏览体验。理解对话循环之后你会意识到一个问题每一次循环都会消耗 Token而成本主要花在来回。比如模型第一次推理判断需要调用获取资讯的 Skill消耗一批 Token拿到 Skill 返回结果后再推理生成简报又消耗一批 Token。后面在做指令设计时要尽量避免让模型折腾太多轮才能给出结果。4. 给 Agent 装上手和眼Skill 与工具调用落地一个只有对话能力的 Agent 只是个聊天机器人真正让它有生产力的是工具调用能力。在 WorkBuddy 开放平台里这个能力通过 Skill 机制实现。这一章我讲清楚 Skill 的编写方式以及我实际开发中总结的几条铁律。4.1 Skill 的本质是可被模型触发的外部函数从概念上理解Skill 就是一系列函数的集合。每个函数有名字、描述、参数定义。模型在推理过程中会根据用户请求和函数描述来决定是否调用某个函数。打个比方Agent 是大脑Skill 是手。大脑决定要不要看新闻手就去执行获取新闻的动作。这里关键点在于手不会主动做任何事它只能被大脑点名后执行。Skill 的粒度设计值得花心思。粒度过粗比如一个 Skill 干十件事模型很难准确传达意图粒度过细比如一个 Skill 只做一次加法运算模型又会频繁陷入工具调用的漩涡浪费 Token。我的经验是一个 Skill 对应一个不可分割的原子能力比如获取指定领域资讯是一个 Skill把资讯格式化就不是一个好 Skill因为格式化应该由模型在生成回复时自然完成。4.2 一个完整的 Skill 定义获取资讯 生成摘要回到我的每日行业简报目标这里需要两个 Skill 配合一个负责获取资讯原文一个负责生成摘要。资讯获取这个动作具有明确的外部性适合做成 Skill。平台注册 Skill 的方式支持两种在网页后台手动填写或者用 SDK 在代码里声明。我用的是 SDK 声明方式因为代码即文档变更记录也更清楚。from workbuddy import skill skill.register( nameget_topic_news, description获取指定领域的公开资讯列表返回标题、来源和时间。当用户要求整理行业动态、新闻简报时使用。, parameters{ type: object, properties: { topic: { type: string, description: 资讯主题例如人工智能、开源、金融 }, limit: { type: integer, description: 返回条数默认5条, minimum: 1, maximum: 10 } }, required: [topic] } ) def get_topic_news(topic: str, limit: int 5): # 这里换成你自己的公开数据源例如 RSS 解析或搜索聚合 items fetch_news_from_source(topic, limit) return {items: items}注意description这段文字模型能不能识别出什么时候该调用这个 Skill完全看它。写得太泛模型会在不需要时也调用写得太窄模型又会忽略它。我还特意加了一个当用户要求整理行业动态、新闻简报时使用这个场景提示明显降低了误调用率。Skill 的返回值建议统一包装成 JSON 结构。模型拿到结构化返回之后生成简报时会更容易把控格式。如果返回的是自由文本模型容易丢失结构信息输出质量不稳定。4.3 function calling 的匹配原理与参数约束Skill 注册到平台后平台会把函数签名转换成语义描述发送给模型。模型的内部推理会生成一个 JSON里面包含name和arguments字段分别表示它想调用的函数名和参数。这里有一个容易忽略的细节参数约束如果写得不够明确模型传参时会凭感觉。比如limit这个参数如果不写minimum和maximum模型可能传一个很离谱的数字。我在调试时见过模型给limit传了 100导致外部接口压力过大、响应超时。后来在参数定义里明确限制 1 到 10问题就没再出现过。还有一点Skill 内部一定要做输入的兜底校验。比如topic如果是空字符串就直接返回空列表而不是去请求外部接口。模型虽然能力强但它的输出仍然有随机性不能假设它每次都精确传参。5. 让 Agent 记住该记住的上下文、记忆与自定义指令Agent 开发进行到这里已经能跑通用户问-模型调工具-输出结果的闭环了。但要把它变成真正持续可用的应用还必须解决记忆问题。一个不带记忆的 Agent每次对话都像失忆了一样这在业务场景里很难接受。5.1 上下文窗口与持久化记忆的边界首先要分清两种记忆会话内上下文和持久化记忆。会话内上下文指的是多轮对话之间携带的消息列表。WorkBuddy 开放平台通过session_id维护同一个会话的历史记录。你在请求里带上同一个session_id平台会把之前的消息一起发给模型这样就实现了多轮对话连续。但上下文携带是有成本的。每轮请求都会把历史消息重新计算一次 Token随着对话变长成本会线性上升。我实测下来一个包含 20 轮历史的会话历史消息消耗的 Token 往往大于单次回复的 Token。这时候就要考虑持久化记忆。持久化记忆是把 Agent 需要长期保存的信息存到外部存储里比如用户的偏好、固定项目的状态。它和上下文是互补关系上下文负责短期连续对话持久化记忆负责跨会话的长期信息。在设计时不要试图把持久化记忆全量塞进上下文而是让 Skill 在需要时读取相关片段。5.2 自定义指令的推荐结构自定义指令在 WorkBuddy 开放平台里对应的是 Agent 的 System Prompt。这个位置是控制 Agent 行为最直接的手段但很多人不知道怎么写才有效。我在多次调参后总结了一套比较稳定的指令结构角色: 简报编辑 任务: 将工具返回的原始内容整理为简报 约束: - 每条摘要不超过80字 - 按影响力排序而非时间排序 - 必须附来源链接 - 不要输出表格 输出格式: markdown 列表这个结构的好处是角色定义了说话风格任务明确了核心目标约束画出了行为红线输出格式降低了不确定性。特别是约束部分每一条都要可被程序化校验不要写要有深度这种模糊要求。另一个经验是约束条数不要贪多。我试过一口气写十条约束模型的执行效果反而变差因为它要同时满足的条件太多容易顾此失彼。现在基本稳定在三到五条按优先级排序最重要的放最前面。5.3 实测下来的记忆策略我的每日行业简报 Agent 最终采用的是会话记忆 少量持久化记忆的组合方案。会话记忆用平台自带的session_id机制每次运行都会生成一个新的时间戳作为session_id这样每次触发都是一次干净的任务执行。持久化记忆则用在了上次简报的发布时间这个场景上。Agent 不希望把一模一样的资讯重复推送所以需要一个 Skill 来记录和查询最近处理过的资讯标题。这个 Skill 后面接了一个 SQLite 数据库逻辑很简单写入时去重查询时过滤掉已处理的标题。代码大致是这样skill.register( namemark_news_processed, description记录已经处理过的资讯标题避免下次重复推送。, parameters{ type: object, properties: { titles: {type: array, items: {type: string}} }, required: [titles] } ) def mark_news_processed(titles): for t in titles: table.insert({title: t, processed_at: now()}) return {processed: len(titles)}记忆策略的关键是不要贪多。这个 Agent 需要记忆的只有什么信息已经处理过一个简单的去重表就够了。把更多的状态塞给 Agent反而会因为信息过载影响判断。6. 从脚本升级成应用部署、触发与稳定性设计本地代码跑通是一回事让它每天按时运行、出错能自愈又是另一回事。这一章讲部署和稳定性设计也是个人开发者和成熟工程实践差距最大的地方。6.1 用平台触发器替代手动运行WorkBuddy 开放平台的一个实用功能是可以在云端保存 Agent 配置和 Skill然后通过触发器让它主动运行。支持三种触发方式定时触发用 Cron 表达式定义执行计划Webhook 触发收到外部请求时运行控制台手动触发调试阶段用我的简报 Agent 用的是定时触发配置如下trigger: type: schedule cron: 0 8 * * * timezone: Asia/Shanghai这里有一个需要留意的坑Cron 表达式默认时区。如果不显式指定timezone平台统一按 UTC 时间执行结果就是每天早上八点的说法在不同时区下会差出 8 个小时等你发现的时候可能已经误跑好几天了。我第一次配置时忘了写时区Agent 在下午四点才跑我还以为是平台故障。6.2 失败重试与超时设计Agent 真正上线之后你会发现外部接口的抖动是常态。Skill 里调用的接口可能在某个早上突然响应慢或者返回 5xx。这时候如果没有失败处理整条链路的输出质量就会受影响。我设计了两级重试策略。第一级在 Skill 函数内部调用外部接口设置 10 秒超时失败之后分别按 30 秒、60 秒的间隔重试两次最多三次。如果三次都失败返回结构化错误{error: source_timeout, message: 尝试3次均超时}第二级在平台任务配置里设置任务级重试次数为 2。这样即使某个 Skill 连续失败整个 Agent 任务还能有机会重新开始。重试间隔需要合理设置。太短会导致外部接口压力叠加太长又会让任务整体时间超出预期。个人场景 30 到 60 秒的退避间隔比较合理。6.3 观测日志、成本、效果三板斧上线之后最怕的就是黑盒运行。WorkBuddy 开放平台的控制台提供三类数据我习惯叫它们观测三板斧运行日志记录每次任务的输入、输出、Skill 调用详情和报错Token 统计按模型、按任务维度统计消耗量效果分析看每次输出是否符合预期是否出现模型死活不调用 Skill的情况我自己每周会花 10 分钟过一遍运行日志重点看两个指标Skill 调用成功率以及每轮任务的 Token 消耗是否异常。如果某个 Skill 突然被频繁调用但调用结果相同很可能说明指令引导出了问题模型在执行循环。成本控制还有一个技巧给触发器任务设置最大运行次数或最大 Token 消耗。WorkBuddy 开放平台支持对单个任务设置预算上限超过自动终止。我设置的是单次运行输出不超过 1000 Token这样即使模型陷入死循环也不会产生高额费用。7. 我踩过的坑和现在仍在用的接入习惯最后分享一些实际接入和运行过程中的问题以及我现在固定下来的工作习惯。这些内容不涉及高深技术但对排查效率影响很大希望对你有用。7.1 三个让我浪费过时间的坑第一个坑是模型供应商的base_url填错。DeepSeek 开放平台的接口地址是带/v1路径的但我在注册供应商时习惯性地把它当成普通域名填结果平台拼接出的请求路径变成了https://api.deepseek.com/v1/v1/chat/completions。排查这个问题的线索是运行日志里的 404 错误看 URL 就一目了然。第二个坑是 Skill 的description写得太宽泛。我最初写的是获取新闻结果用户说随便聊点什么时模型居然也调用了这个 Skill白白浪费一次外部请求和一次工具调用循环。后来我把描述改成获取指定领域的公开资讯列表当用户要求整理行业动态、新闻简报时使用误调用率明显下降。模型判断工具是否该调用很大程度依赖这个描述里的触发场景提示。第三个坑是自定义指令里的输出格式和推送渠道不兼容。我在指令里让 Agent 生成 Markdown 表格结果推送消息时表格渲染混乱整个简报变得很难看。后来我把指令里的输出格式改成无序列表并在 Skill 返回数据时就做好文本整理才彻底解决。建议在写指令之前先想清楚最终消费这份内容的方式是什么。7.2 我现在接新 Agent 的标准流程踩过这些坑之后我总结出了一条固定的接入流程现在每个新 Agent 都按这个顺序推进先明确这个 Agent 最终产出的东西是什么把这个写成一个一句话的验收标准用最少配置创建一个 Agent接好模型供应商跑通一次纯对话调用列出所有需要的 Skill每个 Skill 先用假数据返回跑通工具调用链路把假数据替换成真实数据观察输出质量和稳定性最后才配置触发器和部署上线这套流程的关键在于先跑通链路、再追求真实效果。假数据阶段可以把平台配置问题和业务逻辑问题分开排查。如果跳过这个阶段外部接口一抖动你会分不清到底是平台有问题、Skill 写错了还是外部数据源不稳定。我实际体验下来这样走看起来好像绕远其实是最快的一条路。最后分享一个我个人的小习惯也是觉得最值得留存的每次调整 Agent 的指令或 Skill我都把这一版的关键信息和实际输出截图或复制到本地留存命名带上日期和版本号。这个习惯帮我在迭代几轮之后还能快速定位到底是哪个改动导致效果变好或者变差也方便随时回滚到之前表现不错的版本。Agent 开发本身迭代很快能稳定复现结果比频繁尝试新花样更重要。
返回列表