多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

用微软Agent Framework打造智能博客生成系统的那些事儿:TaoToken统一Key接入实践

用微软Agent Framework打造智能博客生成系统的那些事儿:TaoToken统一Key接入实践 1. 从三个真实痛点说起为什么需要多智能体博客生成系统写技术博客这件事单靠一个通用大模型对话窗口做久了就会发现三个绕不开的坎。第一个坎是资料收集累成狗打开十几个标签页复制粘贴到凌晨最后发现资料太乱理不清头绪。第二个坎是写作没思路盯着空白文档三小时憋出来的开头自己都觉得尴尬。第三个坎是质量没把条写完了不知道质量如何发出去被大佬指正错误时社死。这三个坎本质上不是模型不够聪明而是任务没有分工。资料收集、内容撰写、质量审校本来就是三种不同的认知任务硬塞给一个 Prompt 让它一次干完结果就是每一样都干得马马虎虎。我试过把这三件事拆成三个独立的 Agent每个 Agent 只负责一件事配上明确的职责边界、工具能力和输出约束整个链路的质量立刻上了一个台阶。这就是本文要聊的微软 Agent Framework 多智能体协作生成博客方案。它适合谁适合已经会写 C#、想从调 API 拼 Prompt升级到编排 Agent 工作流的开发者适合内容团队想搭一套半自动化的选题、撰写、审校流水线也适合想理解多智能体协作到底怎么落地、而不是停留在概念层面的技术人。整套系统我把它叫做 BlogAgent核心就是三个 Agent 加一条工作流再配一个统一的模型接入通道。在模型接入这块多 Agent 系统有个很现实的麻烦三个 Agent 可能要用不同的模型Researcher 用便宜的小模型就够Writer 要用强模型保证质量Reviewer 又要稳定低温度。如果每个 Agent 都单独配一套 Key 和 Base URL管理起来非常痛苦。所以本文会用 TaoToken 的统一 Key 通道来收敛这件事一个 Key、一个 Base URL通过 Model ID 区分不同 Agent 用哪个模型。下面从环境准备开始一步步把这条链路搭起来。2. TaoToken 统一 Key 接入多 Agent 模型通道的前置准备在动手写 Agent 代码之前先把模型通道这件事解决掉。多智能体系统最怕的就是每个 Agent 一套凭证配置散落在 appsettings.json、环境变量、代码常量里改一个模型要翻五个文件。TaoToken 的思路是提供一个 OpenAI 兼容的统一入口你只需要维护一个 API Key 和一个 Base URL具体用哪个模型通过请求里的 Model ID 指定。先明确三个关键信息后面配置里会反复用到项目值说明Base URLhttps://taotoken.net/apiOpenAI 兼容接口地址不加 UTMAPI Key在控制台创建形如sk-...只显示一次务必保存Model ID按 Agent 分配例如gpt-4o、gpt-4o-mini等获取 Key 的路径很直接打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册登录后进入控制台在 API Keys 页面创建一个新 Key。创建时建议按用途命名比如blogagent-dev方便后面区分环境和轮换。创建完成后立刻复制保存页面刷新后就看不到完整 Key 了。拿到 Key 之后先别急着写 Agent用一条 curl 命令验证通道是否通。这一步非常关键因为后面 Agent Framework 报的错往往是模型返回格式不对而根因其实是通道没通或者 Model ID 写错了。先用最原始的方式确认curl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的Key \ -d { model: gpt-4o-mini, messages: [ {role: user, content: 用一句话说明什么是多智能体协作} ], temperature: 0.7 }如果返回结构里有choices[0].message.content说明通道正常。如果返回 401说明 Key 错了或者没带Bearer前缀如果返回 404多半是 Base URL 写成了https://taotoken.net/api但路径少了/v1/chat/completions注意 OpenAI 兼容接口的完整路径是{BaseURL}/v1/chat/completions。这一步确认通过后再进入 .NET 项目配置。在 .NET 项目里我建议把模型配置集中放在appsettings.json的一个节点下而不是散落在代码里。这样三个 Agent 用哪个模型一目了然切换模型也不用改代码{ TaoToken: { BaseUrl: https://taotoken.net/api, ApiKey: sk-你的Key, Models: { Researcher: gpt-4o-mini, Writer: gpt-4o, Reviewer: gpt-4o-mini } } }这里的分工逻辑是Researcher 做资料整理和结构化摘要任务相对机械用便宜的小模型足够Writer 要产出 4000 字以上的成稿对语言质量和连贯性要求高用强模型Reviewer 做打分和挑错需要稳定一致用低温度的小模型即可。这样一套组合下来单篇博客的模型成本能压到很低而质量主要由 Writer 那一步保证。注意API Key 不要硬编码进代码提交到仓库。本地开发用appsettings.Development.json或环境变量TAOTOKEN__APIKEY覆盖生产环境走密钥管理服务。.NET 的配置系统支持用双下划线表示层级环境变量TAOTOKEN__APIKEY会自动映射到TaoToken:ApiKey。配置就绪后在Program.cs里注册一个统一的IChatClient让三个 Agent 共享同一个客户端实例只是调用时传不同的 Model ID。这样既复用了连接池又保持了模型选择的灵活性。具体注册代码在下一节和 Agent 定义一起给出。3. 可复制的 Agent 配置三类 Agent 的编排与 settings 片段这一节是全文的核心把 Researcher、Writer、Reviewer 三个 Agent 的定义和工作流编排完整写出来。先看项目依赖在.csproj里加上这几个包PackageReference IncludeMicrosoft.Agents.AI Version1.0.0-preview / PackageReference IncludeMicrosoft.Extensions.AI Version9.10.1-preview / PackageReference IncludeMicrosoft.Extensions.AI.OpenAI Version9.10.1-preview /然后在Program.cs里注册统一客户端。注意这里用OpenAIClient指向 TaoToken 的 Base URL再包一层IChatClientusing Microsoft.Extensions.AI; using OpenAI; var builder WebApplication.CreateBuilder(args); var baseUrl builder.Configuration[TaoToken:BaseUrl]!; var apiKey builder.Configuration[TaoToken:ApiKey]!; // 统一客户端指向 TaoToken 兼容入口 var openAiClient new OpenAIClient( new System.ClientModel.ApiKeyCredential(apiKey), new OpenAIClientOptions { Endpoint new Uri(baseUrl) }); builder.Services.AddSingletonIChatClient(sp openAiClient.GetChatClient(gpt-4o-mini).AsIChatClient()); builder.Services.AddSingletonAgentFactory();AgentFactory负责按 Agent 类型创建带不同 Model ID 的 Agent 实例。这里的关键是每个 Agent 的Instructions、Tools、ResponseFormat和Temperature都要明确public class AgentFactory { private readonly IChatClient _chatClient; private readonly IConfiguration _config; public AgentFactory(IChatClient chatClient, IConfiguration config) { _chatClient chatClient; _config config; } public ChatClientAgent CreateResearcher() { var model _config[TaoToken:Models:Researcher]!; return new ChatClientAgent( _chatClient, name: ResearcherAgent, instructions: 你是一位专业的技术资料收集专家。 任务提取关键信息、整理代码示例、生成结构化摘要。 输出严格的 JSON 格式字段包括 topic_analysis、key_points、code_examples。 不要输出任何 JSON 之外的文字。 , modelId: model); } public ChatClientAgent CreateWriter() { var model _config[TaoToken:Models:Writer]!; return new ChatClientAgent( _chatClient, name: WriterAgent, instructions: 你是一位资深技术博客作家擅长把技术内容转化为通俗易懂的文章。 文章结构必须包含标题、引言、背景介绍、核心概念、实战应用、最佳实践、总结。 代码示例使用 代码块并标注语言类型。 避免空洞的套话逻辑流畅前后呼应。 , modelId: model); } public ChatClientAgent CreateReviewer() { var model _config[TaoToken:Models:Reviewer]!; return new ChatClientAgent( _chatClient, name: ReviewerAgent, instructions: 你是一位严格的技术审稿人。 评分维度准确性 40%、逻辑性 30%、原创性 20%、规范性 10%。 输出 JSONoverall_score、accuracy、logic、recommendation。 , modelId: model); } }三个 Agent 定义好之后用AgentWorkflowBuilder把它们串成顺序工作流。这一步是整个系统编排的体现状态管理和数据传递都由框架接管public async TaskWorkflowResult ExecuteFullWorkflowAsync(string topic, string referenceContent) { var researcher _factory.CreateResearcher(); var writer _factory.CreateWriter(); var reviewer _factory.CreateReviewer(); var workflow AgentWorkflowBuilder.BuildSequential( BlogGenerationWorkflow, researcher, writer, reviewer); var input $ 主题{topic} 参考资料{referenceContent} 撰写要求字数不少于 2000 字风格偏实战教程。 ; var messages new ListChatMessage { new(ChatRole.User, input) }; await using var run await InProcessExecution.StreamAsync(workflow, messages); await run.TrySendMessageAsync(new TurnToken(emitEvents: true)); string finalOutput ; await foreach (var evt in run.WatchStreamAsync()) { if (evt is AgentRunUpdateEvent update !string.IsNullOrEmpty(update.Update.Text)) { finalOutput update.Update.Text; } else if (evt is WorkflowOutputEvent output) { finalOutput output.ToString(); break; } } return new WorkflowResult { Content finalOutput }; }如果你更希望用配置文件而不是代码来定义 AgentAgent Framework 也支持声明式配置。下面是一个 YAML 片段把三个 Agent 的角色和模型绑定写清楚适合团队协作时统一管理agents: - name: ResearcherAgent model: gpt-4o-mini temperature: 0.5 instructions: 提取关键信息输出结构化 JSON 摘要 - name: WriterAgent model: gpt-4o temperature: 0.8 maxTokens: 6000 instructions: 撰写 2000 字以上技术博客结构完整 - name: ReviewerAgent model: gpt-4o-mini temperature: 0.3 instructions: 按四维度打分输出 JSON 评审结果 workflow: type: sequential order: [ResearcherAgent, WriterAgent, ReviewerAgent]这里有个容易踩的坑Writer 的maxTokens一定要显式调大。默认值往往只有 4000写长博客时输出会被截断表现为文章写到一半突然没了。把maxTokens设到 6000 以上长文输出才稳定。另外 Reviewer 的temperature要压低到 0.3 左右审校工作需要一致性不能今天说好明天说不好。4. 端到端验证一次完整生成请求与成功结果确认配置写完了必须做一次端到端验证确认多 Agent 链路真的能稳定产出成稿而不是看起来能跑。验证分三步先单独测每个 Agent再测完整工作流最后检查输出结构。第一步单独调用 Researcher确认它能返回合法 JSON。这一步能提前暴露通道问题和结构化输出问题var researcher factory.CreateResearcher(); var thread researcher.GetNewThread(); var result await researcher.RunAsync( 主题微软 Agent Framework 多智能体协作, thread); Console.WriteLine(result.Text);期望输出是一段纯 JSON形如{ topic_analysis: 本文讨论 Agent Framework 的多智能体协作机制, key_points: [ { importance: 3, content: 声明式工作流编排 }, { importance: 2, content: 结构化输出约束 } ], code_examples: [ { language: csharp, code: AgentWorkflowBuilder.BuildSequential(...) } ] }如果返回里混了好的我来生成 JSON这类前缀说明模型没有严格遵守结构化输出约束。解决办法是在 Instructions 里加一句不要输出任何 JSON 之外的文字并在解析时做容错提取第一个{到最后一个}之间的内容再反序列化。第二步跑完整工作流。调用ExecuteFullWorkflowAsync观察事件流。正常情况下你会依次看到 ResearcherAgent、WriterAgent、ReviewerAgent 的执行事件每个 Agent 的输出会累积到finalOutput。实测下来一次完整生成gpt-4o 系列模型的耗时分布大致是资料收集 8 到 12 秒博客撰写 25 到 40 秒质量审查 10 到 15 秒总计 45 到 70 秒。这个时间对批量生产来说完全可以接受。第三步检查最终输出。一个成功的端到端结果应该满足文章有完整标题和章节结构、代码块标注了语言、字数达到要求、Reviewer 返回了带overall_score的 JSON。如果 Reviewer 的评分低于 70说明 Writer 的输出质量不达标这时候可以触发重写分支而不是直接发布。为了确认链路稳定建议连续跑三次同样的主题观察输出是否结构一致。如果三次里有一次 Reviewer 返回的不是 JSON那多半是温度太高或者 Instructions 不够严格。把 Reviewer 的temperature降到 0.2 再试通常就稳定了。验证通过后这套链路就可以接到前端用 Blazor Server 做实时进度展示用户点一下按钮就能看到三个 Agent 依次工作的过程。5. 本篇常见错误排查401、local proxy failed 与 reading choices多 Agent 系统跑不起来八成问题出在模型通道和输出解析上。这一节把最常见的几类报错和排查路径列清楚对照着查能省很多时间。401 Unauthorized。这是最高频的错误几乎都是 Key 的问题。先确认三件事Key 有没有带Bearer前缀注意有个空格Key 是不是复制时多了换行或空格Key 有没有被禁用或额度耗尽。在 .NET 里如果用的是ApiKeyCredential框架会自动加Bearer这时候你传的 Key 就不能再手动带前缀否则会变成Bearer Bearer sk-...。排查时把实际请求的 Header 打出来看一眼最直接。local proxy failed / connection refused。这个报错通常和网络环境有关表现为客户端连不上 Base URL。先确认BaseUrl写的是https://taotoken.net/api没有多余路径再确认本机 DNS 能解析、能访问外网。如果是在容器里跑检查容器网络是否放行了出站 HTTPS。还有一种情况是配置里 Base URL 末尾多了斜杠导致拼出来的路径变成//v1/chat/completions某些网关会拒绝统一去掉末尾斜杠即可。reading choices 相关报错。典型信息是Cannot read properties of undefined (reading choices)或者反序列化时找不到choices字段。这说明返回体结构和预期不符。可能原因有三个一是请求路径不对打到了非兼容接口二是 Model ID 写错了服务端返回了错误对象而不是正常响应三是流式和非流式模式混用代码按流式解析但请求发的是非流式。排查方法是在 curl 里复现同样的请求看原始返回体长什么样再对照代码里的解析逻辑。OAuth / 认证方式不匹配。如果你在 MCP 配置里用了 HTTP 传输并开启了requiresAuth但没配oauthClientId就会报认证失败。MCP 的 HTTP 模式需要走 OAuth 流程配置片段要写全{ name: RemoteToolService, transportType: http, serverUrl: https://your-mcp-host/mcp, requiresAuth: true, oauthClientId: your_client_id }结构化输出解析失败。即使设了ChatResponseFormat.ForJsonSchema部分模型仍可能返回带废词的 JSON。稳妥做法是加一层容错解析先尝试直接反序列化失败则截取第一个{到最后一个}再解析。这个兜底逻辑在多 Agent 系统里几乎是必备的因为任何一个 Agent 的输出格式抖动都会让整条链路断掉。MCP 工具加载超时。Stdio 模式的 MCP 要启动 Node 进程冷启动可能 3 到 5 秒。如果同步等待Agent 创建会被卡住。解决办法是加超时保护用WaitAsync(TimeSpan.FromSeconds(15))超时就跳过 MCP 工具继续执行不要让整个 Agent 创建失败。排查时记住一个原则先隔离再定位。先用 curl 确认通道再单独跑每个 Agent最后跑完整工作流。哪一层出问题就在哪一层解决不要一上来就怀疑框架。6. 把链路接到实际项目Coding Plan 与后续扩展三个 Agent 跑通之后下一步就是把它接到真实项目里让它真正产生价值。这里有两个方向值得展开一是把模型调用成本控制住二是把工作流扩展到更多场景。成本控制方面多 Agent 系统最容易失控的地方是重复调用。Researcher 收集的资料如果 Writer 每次重写都要重新收集一遍Token 消耗会翻好几倍。解决办法是加缓存把 Researcher 的输出按 taskId 缓存起来Writer 重写时直接复用。同时按 Agent 分配模型Researcher 和 Reviewer 用便宜的小模型只有 Writer 用强模型单篇成本能压到很低。如果内容生产是长期、批量的需求可以考虑用 Coding Plan 这类面向持续调用的方案来统一管理额度避免每次都要单独充值。扩展方向方面这套收集、撰写、审校的三段式结构可以直接迁移到很多场景。新闻稿生成、产品文档、技术白皮书本质都是资料整理加内容产出加质量把关。代码生成场景可以改成需求分析、代码实现、代码审查。数据分析场景可以改成数据收集、分析报告、可视化建议。只要你的业务能拆成多个步骤就能用 Agent 工作流来实现。如果要继续深入建议从这几个点入手给工作流加条件路由Reviewer 评分低于阈值时自动触发重写接入向量数据库做 RAG让 Researcher 能引用历史博客保持风格一致用 OpenTelemetry 做可观测性追踪每个 Agent 的耗时和 Token 消耗。这些扩展都能在现有结构上平滑叠加不需要推倒重来。最后说个实操建议先把最小链路跑通也就是三个 Agent 加顺序工作流确认能稳定产出一篇成稿再去加 MCP 工具、RAG、条件路由这些高级特性。很多项目失败不是因为架构不够先进而是因为一开始就堆了太多东西结果哪一环都没调通。先把主干跑顺再长枝叶。需要创建 Key 或查看接入文档的话可以从这里进API Keys 页面 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。想先验证模型效果可以直接在模型对话页试 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。长期做内容生产或 Agent 开发的话Coding Plan 会更划算 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。
返回列表