系列第二篇。上一篇我做出了一个能读写自己博客的智能体。这一篇是它的下一个同事,一个专门看懂图片、画出图片的智能体。

先交代清楚:这篇是设计稿,不是完工报告。智能体还没写。我把设计想清楚、把名字起好、把施工单写好,然后交给我另一个 Agent 去落地。


一、为什么不是“给博客加两个工具”

上一篇末尾我说,写文章配头图时我又成了搬运工。当时第一个念头特别自然:那就在博客智能体里加两个画图工具呗。
我想了一晚上,决定单独做一个智能体。三个理由。
第一,这能力跟博客半毛钱关系都没有。画图识图这件事,跟我写不写博客毫无关系。产品做图、群里丢一张报表问“这数据什么问题”、把设计稿转成前端草图,都是同一个能力。塞进博客智能体,等于把图片能力私有化了,以后每遇到一个需要图片的场景都要重写一遍。
第二,它用的是另一批模型。博客智能体用文本模型就够了,识图要视觉模型,生图要图像生成模型。这三类模型的 API、参数、计费方式完全不同。混在一个智能体里,模型选择逻辑立马变成一团乱麻。

第三,我想给自己造点麻烦。我现在有两个智能体了,它们怎么配合、要不要互相调用、以后再加第三个怎么办,这些真实问题只有“真的有两个”才会浮出来。所以这个智能体是有意设计成通用图片能力的,而不是博客的一个配图工具。

二、起名字这件事

看我已有的成员,closedoff 是业务名(园区封闭化管理),blog 是功能直译。新成员想体现“看图加画图”这个双向能力,我试了几个候选。叫“画师”太窄,它还会看图;叫“眼睛”偏输入侧,漏了生成。最后定了“绘语”——“绘”是画,“语”是说、是理解,一进一出都占上了,读起来也像个角色名。
所以它的身份是:显示名“绘语(图片智能体)”,标识 huayu,分类“图片与视觉”,页面挂在 /agents/huayu,权限标识 huayu:access。文章标题也顺手定了:

AI Agent 多智能体开发 Vlog(二):我给博客智能体找了个会画图的同事
这里有个约束得记住:这个标识是全局唯一的,同时是授权标识、会话管理 key 和页面路径的来源。这三样必须由同一个地方推导,不许各处手写,否则迟早出现“授权了但页面进不去”这种玄学问题。

三、它会什么:工具怎么切

上一篇我学到最重要的一条是,工具不是越多越好,而是“模型在什么情况下会想起来用它”。所以我按使用场景切工具,不按 API 切。
看图的活儿我开了三个。huayu_describe 用来描述图里有什么,用户问“这张图是什么”的时候用。huayu_extract 从图里抽结构化信息,表格、发票、报表、截图文字都能抽。huayu_compare 对比多张图的差异,比如“这两版设计稿差在哪”。
画图的活儿开了三个。huayu_draw 是按文字描述生成图片,支持尺寸和风格参数。huayu_cover 专门生成文章头图,按标题和摘要自动组织提示词,尺寸固定横幅。huayu_illustrate 按段落生成配图,返回地址和建议插入的位置。
这里有个刻意的设计:后两个用 huayu_draw 其实都能实现,但我还是单独开出来了。理由是工具的“召回”。如果只有 huayu_draw,模型在“我这篇文章需要个头图”这个场景下,得自己推理出“头图等于一张横幅图加一段提示词”,中间容易走偏,尺寸不对、风格不搭、提示词写得太敷衍。而 huayu_cover 的说明直接写“用户需要文章头图或封面图时用它”,召回率立马上去了。
代价是工具变多、模型选择变难。所以我给自己定了条规矩:只有参数组合固定、场景明确时才开专用工具,否则一律用通用工具加参数。

另外还加了两个素材侧的工具。huayu_library 用来翻我之前生成过的图,huayu_upload 把用户传的图登记进素材库。第一个是我特意加的,生图要花钱,用户经常说“上次那张再给我来张差不多的”,能翻出来就别重画。

四、图片在系统里怎么流动

这是整个设计里我花时间最多的地方。结论先放这儿:图片永远不当作“内容”进对话上下文,只当作引用流动。

4.1 输入侧

用户在页面选一张图,先上传并登记,拿到 attachmentId、归属人、大小、类型;发消息时带上这个引用,模型看到的是一个图片内容块;真需要识图时,由工具去取真实图片数据,再调视觉模型。
关键在中间那一步的分离:消息里带的是引用,真实图片数据只在调模型那一刻才被取出来。不直接塞进去,是因为会话会重放:刷新页面、恢复历史、分支对话,都要重读一遍会话日志。要是消息体里存着几百 KB 的图片数据,这些操作会又慢又贵,数据库还会飞速膨胀。

4.2 输出侧

模型调 huayu_cover 之后,先调图像生成模型拿到图片数据(可能是 base64),然后立刻存进图床换回一个 URL,最后只把 URL 交给对话。模型看到的是“图已生成,地址是 https://...”,页面看到的是一个 img 标签。
第二步不能省:base64 绝不能留在对话上下文里,它会被反复读、反复计费,还会把上下文撑爆。图片一生成就落盘,对话里只留地址。
这个思路和上一篇讲的“工具结果分两路”是同一个原则:凡是又大又重复的数据,都别让它跟着对话走。

4.3 存哪

分三层。图床存图片文件本身,复用博客已有的图床能力。业务库存图片元数据——谁生成的、什么提示词、哪个模型、尺寸、时间、花了多少钱,这些要能查、能复用、能算账。会话日志里只留地址引用,保证重放时不重复搬运图片数据。

五、模型怎么选

绘语要跨三类模型,比博客智能体复杂。识图必须支持图片输入,也就是要视觉模型;生图是另一个类别,跟对话模型完全不是一回事;对话和组织用普通文本模型就行。
这里省了我不少事:模型可以随时换。我只要说“给我一个支持图片输入的模型”,剩下的路由、调用、流式都不用操心,换模型也不用改业务代码。哪天出了更强的视觉型号,我改的是配置,不是代码。
我定了三条规矩。第一,按“这一轮要干什么”选模型,不是按智能体选。不能简单写“绘语用 X 模型”,因为同一轮里识图和生图要用不同的模型,所以模型选择发生在每一次模型调用的层面,而不是会话创建时一次性定死。
第二,有视觉要求的调用,必须先校验模型真的支持。我吃过这个亏:界面上选了个模型,结果它不支持图片输入,请求发出去才报错,用户看到的是“系统错误”四个大字。正确做法是调用前就知道这个模型支不支持,不支持就明确提示“当前模型无法识别图片,请切换到支持视觉的模型”。
第三,缺配置要明确拒绝,不能静默降级。要是生图模型的密钥没配,工具应该直接返回“图片生成未配置”,而不是悄悄降级成“我帮你写段提示词,你自己去画吧”。后者会让用户以为功能坏了,却不知道坏在哪。

顺便说个设计时发现的现状:我的群组配置里其实预留了模型白名单字段,但代码里还没实现。所以设计稿里我把它标成“预留但未生效”。绘语正好是第一个真实需求方,它要用比较贵的生图模型,必须能限制。

六、跟博客智能体的关系(这节的结论会被第三篇推翻)

写设计稿时,我最初的想法特别自然:博客智能体写完稿,需要头图,就调绘语生成一张。我甚至把调用方式都想好了。
但我在末尾加了一节“待验证的问题”,写着写着发现这条路有坑。
第一个问题是谁依赖谁。博客直接调绘语,博客就依赖绘语。以后我加个排版智能体,它也要图,那它也得认识绘语。再加个数据月报智能体要配图表,还得认识绘语。智能体会连成一张网,每加一个成员就要改一批已有代码。
第二个是鉴权。用户是在博客页面操作的,博客去调绘语时用谁的身份证?借用户身份的话,绘语的权限校验怎么做?用内部身份的话,用户对图片的权限边界又在哪?
第三个是出错。绘语生成失败,博客该说什么?它不知道绘语失败的细节,只能笼统说句“配图失败了”,用户看不到真实原因。
第四个是状态。“这文章配了哪张图”记在博客那边,“这张图谁生成的、花多少钱”记在绘语那边。两边各记一半,对不上时没法查。
所以我在设计稿末尾写了一句:绘语先按“独立智能体加独立页面”做出来,先能自己用;跟博客的协作方式暂不直连,等第三个成员出现时再看统一方案。

这句话就是第三篇的开头。

七、给下游 Agent 的施工单

下面这份是写给另一个 Agent 的任务卡,同时也当成这份设计的验收标准。
目标是:在现有群组里新增成员 huayu,提供图片理解与生成能力,接入群组既有的会话、工具、授权体系。
要交付的东西有七项:在群组的 Agent 清单里加一条,分类为“图片与视觉”;把装载链路五件套补齐;写一份完整的声明,包括人设、工具注册、结果投影、思考投影;至少实现 huayu_describehuayu_drawhuayu_cover 三个工具;业务存储要有图片元数据表和迁移脚本,口径跟本项目其他成员一致,只核验不建表;页面 /agents/huayu 要能用,可以先复用现有结构;最后是就绪探针,缺配置时装载成功但报未就绪,并说清缺什么、怎么配。
这里重点说装载链路,因为新增一个成员,代码要走五个地方,任何一个漏掉都不会报错,只会表现为“工具不见了”或“页面打不开”。第一处是 Agent 清单数组,漏掉就完全不被装载。第二处是装载函数的 switch 分支,漏掉会装载失败但不影响其他成员。第三处是错误处理映射,漏掉会把业务错误当成 500。第四处是子包适配层,漏掉可能页面路径和权限对不上。第五处是 mount 函数的返回值,必须如实返回全部已注册工具和协作入口。
最后一条最阴。mount 要返回“本次注册了哪些工具”,群组根据它算“这个智能体能用哪些工具”。这里返回空数组的话,结果是该智能体所有工具全部不可见,而界面上完全看不出来。
验收的时候我会逐条看:页面能不能打开、权限受不受 huayu:access 控制;缺配置时就绪探针有没有返回 503 并说明配置方法;已注册的工具是不是全部出现在 mount 返回值里;传一张图问“这张图里有什么”能不能正确描述;说“给我生成一张 XX 的图”能不能返回可访问的地址;生成的图片刷新页面后还在不在(这一条证明存的是地址不是内容);缺生图密钥时是不是返回明确的未配置错误而不是静默降级;以及群组里其他成员有没有受影响。

交付时我还要求说明三件事:实际用了哪些模型,识图、生图、对话分别是哪个;图床用的哪一套、保留策略是什么;哪些地方是故意没做的,比如暂不支持视频、暂不做图片编辑。最后一条尤其重要,我在这个项目里最怕的不是“没做”,是“看起来做了但其实没接线”。所以请把“故意留白”和“还没做”分开写清楚。

八、这篇留下的问题

绘语做完之后,我会有两个能干的智能体,外加三个待解的问题。博客配图这件事到底该谁发起?以后第三个、第四个成员进来,怎么避免两两对接的网状依赖?用户在哪个入口跟这些智能体打交道,难道每个智能体一个页面,让他自己判断该找谁?
下一篇就是这三个问题的答案,也是这个系列真正的重点:多智能体协作。我会讲清一个完整的智能体执行链路,从用户说一句话开始,到结果交回去,中间到底发生了什么。

最后修改:2026 年 09 月 22 日
如果觉得我的文章对你有用,请点个赞吧!