让 AI 编程助手调用另一个 AI:一次跨工具问答同步的工程复盘

引子

起因是一个很具体的场景:日常在 AI 编程 IDE(Trae)里干活,但手上的 ZCode 账号还有额度没用完,于是很想"在 Trae 里问 ZCode"。

听起来只是"转发一条问题",但真正动手拆解之后,约束有三条:

  1. 提问必须真正走 ZCode 的通道,消耗它的账号额度,而不是在本地拼一个请求;
  2. ZCode 桌面端的历史记录里要能看到这次问答,方便回头翻;
  3. 回答要回到 Trae 当前对话里,后续还能被上下文和记忆引用。

第三条天然满足,麻烦的是前两条------尤其第二条,它把"简单转发"变成了"跨两个工具做数据同步"。这篇记录完整的排查与实现过程。

一、先搞清机制:CLI 和桌面端根本是两套存储

第一反应是"CLI 问完,桌面端自然就有记录"。实际验证后发现不成立,原因在存储分层:

  • CLI 侧 有一套自己的本地会话库,按工作目录维度记录会话;
  • 桌面端 的历史列表读的是另一套任务索引库,只认特定 provider 且有 CLI 创建时间戳的记录;
  • 两者不共用同一份数据,也没有"扫描 CLI 会话库并自动导入"的逻辑。

测试里还发现一个关键细节:CLI 创建的会话,只有当它的工作目录在桌面端已被登记为项目时,才会进入桌面端的索引范围。在临时目录里跑的会话,桌面端就是看不到。

把这几条串起来,结论很清晰:

CLI 到桌面端是单向的(桌面端把任务交接给 CLI 时会写索引),终端直接发起的 CLI 会话不会自动出现在桌面端历史里。

所以"让历史里有记录"这件事,不能等,得自己把索引补上。

二、为什么最后做成 Skill,而不是 MCP

动手之前有个绕不开的选型问题:这个能力该做成 MCP,还是做成 Skill?

我的判断标准只有一个------这个能力到底是什么形状:

维度 MCP Skill(本地脚本 + 说明)
本质 标准化的工具协议,服务端暴露一组能力 一段固定的本地流程编排
适合 多客户端复用、需要被动态发现的工具集 单机、依赖本地 CLI 与本地数据库的流程
成本 要起服务、定义 schema、维护传输 一个脚本,加一份使用说明
本例匹配度 低:能力只有一个,且强依赖本机的 CLI 与 SQLite 高:调用 CLI → 写索引 → 回传文本,三步固定

这个能力没有"被多个客户端发现"的需求,本质上就是本机的一段流程。用 MCP 等于为了一个动作起一个服务,属于过度设计。

最终形态:一个 Skill 目录,包含三件东西------

  • 说明文件(告诉模型什么时候用、怎么用、有哪些参数);
  • 主脚本(负责调用 CLI、注入索引、返回结果);
  • 一个小的同步脚本(负责写本地索引库)。

三、实现的三个步骤

1. 调用:走 CLI 的单次问答模式

CLI 支持"给一个问题、拿一段回答"的单次模式,这是消费账号额度的正路。调用完成后,会话会在本地会话库里留下一条记录,并带有一个会话 id------这个 id 是后面同步的钥匙。

2. 注入:把会话 id 写进桌面端索引

关键点只有一个:桌面端索引里的 task_id,必须与 CLI 会话 id 完全一致。有了这个一致性,桌面端读索引时就能把它当成一条正常的历史任务。

索引记录只需要满足桌面端"能读出来"的最小字段集合,大致是:

ini 复制代码
task_id        = CLI 会话 id
provider       = 该 CLI 对应的 provider 标识
cli_created_at = 本次创建时间(非空,否则不会被纳入列表)
title / 摘要   = 由问题首行截取

写成脚本就是一次 INSERT:

python 复制代码
import sqlite3, time

def sync_session(session_id, provider, question):
    conn = sqlite3.connect(INDEX_DB)
    conn.execute(
        "INSERT INTO tasks (task_id, provider, title, cli_created_at) VALUES (?, ?, ?, ?)",
        (session_id, provider, question[:60], int(time.time())),
    )
    conn.commit()
    conn.close()

这里有个容易忽略的点:顺序不能反。必须先拿到 CLI 的 session id,再写索引;反过来(自己生成一个 id 再去调 CLI)会导致两边 id 不一致,桌面端点开就是空会话。

3. 回传:把回答原样交回对话

脚本最后一步只做一件事:把 CLI 返回的正文打印到标准输出。这样调用方(Trae)拿到的就是纯文本,可以直接进入当前对话,被后续的上下文和记忆机制正常引用。

整体流程串起来就是:

bash 复制代码
问题 → 调 CLI(消耗额度、产生 session) → 用 session id 写桌面端索引 → 回传回答文本

这套实现已经整理成开源仓库,包含 Skill 说明、CLI 入口脚本和索引同步脚本三部分:github.com/zlw1125/zco...。想直接用的可以按 README 里的步骤安装,想自己改造的,重点看 _sync.py 里那段字段映射。

四、三个必须提前知道的限制

限制 1:CLI 通道的模型可能是锁死的

验证时发现一个反直觉的现象:桌面端已经在用更轻量的 Flash 模型,但 CLI 通道仍然固定用完整版模型------因为 CLI 用的是 OAuth 登录拿到的 account provider,而这个 provider 的默认模型由服务端下发,单次问答模式没有切换入口。

尝试过改配置文件、设环境变量、改数据库里的会话配置,全部无效;能生效的只有"桌面端里用 API Key 类型的 provider"这一条路。

这提醒我们:在封装别人的 CLI 之前,先确认哪些东西是你控制不了的,否则使用者提的第一个诉求就是"换个模型",而你无能为力。

限制 2:桌面端列表有缓存

索引写进去了,桌面端不重启也可能看不到------列表是缓存渲染的,需要重启或刷新索引才会重新读取。

这一点必须写进使用说明,否则使用者会认为"同步失败"。判断方法很简单:查一下索引库,记录在,就说明写入成功,只是展示层还没刷新。

限制 3:工作目录的登记状态会影响可见性

如果希望会话以一个"项目"的形态出现在桌面端,CLI 的工作目录必须是桌面端已登记过的项目路径;在临时目录里跑,索引可能写了但归属不清。

五、验证清单

这类"跨工具同步"最容易出现"看起来成了、其实是假的",所以验证要分三层:

  1. 额度层:确认这次调用确实走了目标账号(额度会变动),而不是本地伪造的回答;
  2. 存储层 :直接查索引库,task_id 与 CLI 会话 id 是否一致、cli_created_at 是否非空;
  3. 展示层:重启桌面端后,历史列表里能否看到这条记录,点开后内容是否完整。

我至少跑了两轮真实会话做交叉验证,两轮都能在索引里查到对应记录------这比"脚本没报错"可靠得多。

结语

这件事本身不复杂,复杂的是"两个工具各自为政"的现实:CLI 有自己的会话库,桌面端有自己的索引库,中间没有桥。

真正有价值的三个判断是:

  • 先验证机制,再写代码------"应该会自动同步"是最贵的假设;
  • 选形态看形状------一个本地流程用 Skill,一组要被发现的工具才用 MCP;
  • 同步靠一致性------两个系统只要约定好一个稳定的 id,就能低成本打通。

如果你的工作流里也有"A 工具干活、B 工具记账"的情况,这套"调用 → 用同一 id 写索引 → 回传结果"的套路,基本可以直接搬。完整代码在这里:github.com/zlw1125/zco...。

相关推荐
qinglongcn20 分钟前
“完成”是什么意思——Plan 步骤状态机的七个 Bug
agent·ai编程
柯南466833 分钟前
【AI工程师精讲】32:Text2SQL:让 AI 查数据库,难点八成不在生成 SQL 上
人工智能·ai编程
艺杯羹2 小时前
MCP本地服务集成避坑:从Stdio管道僵死到双向JSON-RPC稳健通信
人工智能·python·ai·系统架构·大语言模型·ai编程·mcp
西安小哥6 小时前
百万上下文真的来了,我反而把提示词写短了
ai编程
西安小哥6 小时前
大模型开始自己排班:LLM 路由落地时我踩到的三个坑
ai编程
frcoder6 小时前
【Harness编程】构建 AI 编程工作流:设计原则与实施指南
ai编程·harness编程·tackharness
前端双越老师7 小时前
程序员 1v1 访谈系列第十二期:普通人没有核心竞争力
前端·ai编程·全栈
柳杉7 小时前
没有写一行代码:我用 Codex 制作 了一个 3D 智慧展厅可视化大屏
前端·ai编程·three.js
小lu飞17 小时前
2026小红书小工具怎么制作:纯前端 ZIP 打包、沙箱限制与笔记挂载流程
前端·笔记·ai·ai编程