菜市场挨着河边。清早,卖菜的人已经把摊子摆开。青菜上还带着露水,萝卜和白菜整齐地码在竹筐里。卖鱼的把木桶放在脚边,水面时不时晃动一下。有人挑着担子从桥上走过,也有人停下来讨价还价。河边种着几棵柳树,树荫落在石阶上。卖早点的铺子飘出热气,包子一笼一笼地揭开盖子。太阳升高以后,人渐渐多起来,叫卖声、说话声混在一起。这样的早晨天天都有,却并不让人觉得重复。
引子
在这部分,我将以层层递进的逻辑方式,为大家讲解一下如何写一个类似 Claude Code 那样的 CLI。本文章尽量会以通俗易懂的方式为大家讲解,教给大家一些设计思路和架构设计中需要注意的点。本文章适用于个人开发者,小型初创团队和想学习 Agent CLI相关知识的初学者。文章将会以当前开源的一些优秀项目为例子讲述设计方法和思维。
一、什么是 CLI?
首先我们要了解什么是 CLI?CLI 中文名称叫命令行界面,它是一种交互方式。与之对应的叫GUI,中文名称叫图形界面,我们经常使用的微信,浏览器界面这些都是 GUI。
作为初学者,大家这里面可能会混淆,Windows PowerShell 是不是 CLI 呢?严格来说,PowerShell是实现 CLI 交互的工具。更具体一点,当我们在 terminal(终端)中使用 git commit、git status、git push 的时候就是在使用 CLI。如果大家有提交项目的经验,或者在 GitHub 上面提交过项目的话,对这些命令行应该是比较熟悉的。
到这里你会发现一个问题,我写了一个产品,这个产品运行的很多功能都需要用到函数指令。用户要执行各种操作,那么让用户记住这些指令显然是不现实的,所以GUI(图形界面)就出现在了大众视野中。GUI 未必执行的是 CLI 命令,但是其核心逻辑和 CLI 差不多,都是在一种交互方式。GUI 是用户点击按钮,CLI 是输入命令行。
随着 AI 技术的发展,工程师逐渐想到了一个方法,能不能通过调用 LLM 的方式,让 LLM执行各种命令行,做出 Agent CLI 来操作我们的电脑,帮助我们干更多的事情呢?于是,Agent CLI 便诞生了。在 Agent CLI 中 Agent 可以通过命令行,来读取和操作你电脑本地的文件。
因此很多初学者会存在一个误区,在看到 Agent 操作你的文件的时候会非常震惊,认为这个模型能力很强,能够操作你的电脑,其实模型并不能操作你的电脑,模型只是借助了命令行工具进行的操作。
二、Agent CLI 设计需要注意哪些维度?
了解完 CLI,接下来我们进入正题,在设计 Agent CLI的时候该注意哪些呢?我将分成下面这几大类为大家讲起:
1. 工具
2. 上下文
3. workflow
4. 数据库
5. prompt
6. runtime
7. CLI 界面
8. 兜底(专业讲就是边界设计)与安全
三、工具(工具集)
我们先从工具(专业一点也可以叫工具集)讲起。Agent 工具集的设计非常重要。在 Agent 设计下,工具集并不是简单的工具,它往往决定了 Agent 的能力边界(这里面排除一些特别因素,比如模型的种类)。你提供给模型的工具集,决定了 Agent 行动空间以及 Token 成本。如果设计得当,那么 Agent 将会成为你的得力助手,如果做不好,那么 Agent 将会选择错误的工具,进行胡乱操作。
以 Claude Code 为例。在 Claude Code中工具并不是分散写到不同目录中的,所有的工具集中在同一个根目录里。Claude Code 将这些工具统一注册和管理,建立了一个工具池。在这个工具池中一共设计了 50 个工具。
这点就和 Anthropic 官方出的技术博客中有差异,他们说自己只为 Claude Code 设计了 20 多种工具,而且他们认为并不是工具越多越好,主张工具的质量 > 工具量。从这点看,Anthropic 公司也存在水分,但是其表明的工具质量 > 工具量,我是十分认同的。
文献引用来源:
"Claude Code currently has ~20 tools, and our team frequently revisits if we need all of them for Claude to be most effective. The bar to add a new tool is high, because this gives the model one more option to think about."
—— Seeing like an Agent,claude.com/blog/seeing-like-an-agent
(章节:"Progressive disclosure: the Claude Code Guide agent")
3.1 系统工具 vs Agent 工具
所以,对于工具设计,你需要根据你的业务需求,为你的 Agent 设计对应的工具。工具的数量根据 Agent 系统复杂程度和业务需求制定。在工具设计上如果从工具使用对象的角度去思考的话,可以分为系统工具和 Agent 工具。
Agent 工具可以分为外部 MCP 工具和内部工具(需要工程师去设计的工具)细分为这 5 种:
1. 文件读写工具
2. Agent 结构化输出工具(例如 todowrite 工具)
3. shell 与系统操作工具
4. Agent 编排工具
5. 搜索工具与 MCP 所连接的资源(网站,外部工具等等)
当然,如果你希望你的 CLI 能够自动回复你,具备主动性,那么还需要加一个触发工具。
系统工具主要有 skill 加载,上下文工具(需要我们注意的是,现在的 Agent 架构下,Agent可以自己选择上下文的获取,但是上下文的裁剪还是需要由系统执行的。总结来讲,上下文获取属于Agent 工具,上下文裁剪属于系统工具)、MCP 资源工具负责读取和列出 MCP 资源、系统监控工具、系统等待、发送文件、推送消息、发送消息等工具。
讲到这里,大家可能对于 Agent 系统中工具是否属于系统工具和 Agent工具的划分不清楚。我这里面有一个方法叫给大家:我们去分析这个工具是否需要 prompt 来区分这个工具是否属于系统工具还是 Agent 工具。如果这个工具不需要Prompt,那么它就是系统工具。如果需要,则是 Agent 工具。
知其然必知其所以然,为什么这么划分呢?因为在当前,我们需要一个 prompt 去告诉 LLM 这个工具是什么、何时使用、边界情况是什么(不能拿它干什么)、以及这个工具的调用指令(Tool_Call)等内容。
3.2 以工具为起点,连带看其他组件
我们先从 Agent 内部工具讲起,如果您之前读过我写的文章,您应该知道,一个优秀的工程思维不能仅仅考虑这个组件的设计。我们应该连带着去看。我们分析项目组件不能仅仅分析这个组件本身。我将会以工具为起点,连带着去分析其余的部分。让大家感受一下工程化思维。
3.2.1 文件读写工具
文件读写工具将赋予模型读写文件的能力,是较为基础,也是非常重要的工具。最常见的工具为FileReadTool、FileEditTool、FileWriteTool,这些工具可以帮助模型进行文件的阅读和改写。
这里面需要大家要注意的是,不要单独地为 word、PDF等等的文档专门写一个工具,我们可以将这些处理逻辑内置在 FileReadTool。并且在 PDF 的处理上,我们可以采用多模态模型直接将 PDF
里面的内容截图,让模型进行分析(这里需要了解每个模型的图片处理上限,一般来说,将 5-10 页 PDF 直接 Base64 编码作为文档传递给模型,如果超越了页数限制,把每页渲染成图片,然后给到多模态模型进行图片分析。具体的情况还需要根据模型能力来设置)。
3.2.2 Agent 结构化输出工具
Agent 结构化输出工具主要负责让 Agent 将自己的规划,需要的执行步骤写下来。如果使用过一些 AI 产品的朋友们肯定都会遇到一个情况,当你给 Agent 提交一个任务的时候,界面上会弹出一个 todolist 或者 plan 边框,这个边框里面的内容就使用到了结构化输出的工具。
最为常见的结构化输出工具有 ToDoWrite、TaskCreate、TaskOutput 工具。流程为:
• Agent 根据当前的任务进行分析,为自己设立任务(写下来)
• Agent 继续分析任务需要几个步骤完成?这些步骤大致该怎么做?(写下来)
当然 Agent 写下来之后,肯定不能直接发送给用户,为什么呢?因为还没有进行排版,这就还需要系统再去调用一个发送消息的工具,将这些内容进行编排,前端进行渲染,然后呈现在用户面前。
这就是你看到一个 ToDoList 边框的完整过程(更为企业级的做法会有更多的边界处理,比如前端渲染重试机制,用户网络波动的重新推送等等)。
聪明的你可能会发出疑惑,这个 Agent结构化输出工具跟系统工具中的发送消息工具有些类似。确实有类似的地方,但是 Agent结构化输出工具更针对于 Agent 输出的前期处理,而系统工具中的发送消息工具负责后期处理,且覆盖范围更大。比如有时候你的简单问题不需要调用 Agent 结构化输出工具,那么这时候 Agent 的输出会直接交给发送消息工具去处理。
3.2.3 Shell 与操作系统工具
Shell 与操作系统工具主要负责跑 git、npm(Node Package Manager 是 Node.js 的管理包器,你在用 AI 开发网站时用到的 Vue、React 都用到了 npm 进行的安装)、系统环境,验证等。总的来说,Shell 与操作系统工具主要负责把 Agent 的决策落在真实的 OS 进程中,让 Agent 在你的本地进行验证执行,和依赖的下载。你在使用 Agent产品时经常会看到弹出一些边框,里面有各种 bash 和 PowerShell命令行、下载请求、验证请求等等,这些就是 Shell 与操作系统工具负责的内容。
Shell 与操作系统工具主要有 BashTool、PowerShellTool。这两个工具都属于 Shell 执行器。
作为执行器,我们需要让其处于沙盒环境中使得 Agent 在执行真实操作的时候更加安全(比如,做到不会删除用户的重要文件)。这里需要额外讲解一下,作为沙盒,需要考虑:
• 进程的管理
• 周期的管理 • 状态的管理(休眠还是活跃)
• 权限管理(沙盒内部需要设置哪些白名单?拦截哪些 Agent 失误造成的错误指令?针对哪些语法做安全性检查?)
为了做到上述沙盒中的功能,我们需要更多的子工具去负责这些。这些子工具其实可以作为一个系统工具去定义(我上面讲到过,是否属于系统工具可以通过该工具是否拥有 Prompt 来定义)。
以 Claude Code 为例子,该项目中有休眠工具(用于静默等待)、注册定时任务的工具、捕获/接管终端输出工具、系统监控工具,以及一个将 shell 执行器工具沙盒产出的上下文以 REPL 模式(Read读取、Eval 求值、Print 打印结果、Loop 循环,其特点是交互式的,逐条执行,立刻看结果。Python 中的 >>> 提示符就属于 REPL)进行隐藏的工具。
当然,我个人认为 Claude Code的工程设计不是很好甚至说有些混乱,比如这里面其实有些工具是属于上下文类型的工具,但是Claude Code 并没有将其写到上下文工具目录下,并且如果你详细分析其目录,工程师在目录设计上并没有刻意的按照系统工具和 Agent 工具进行分类,更多的是根据功能进行的分类(虽然这块设计得也不是很好)。
那么我认为一个好的架构设计其每个组件务必是职责清晰,遵循职责分离原则的。对于 Shell Tool 这块,要写一个沙盒是必须的,将这个沙盒抽象成一种工具也可以(毕竟其内核作为一个执行器)。那么其中的系统工具应该写在 system_tools目录下,类似这种执行器其内部机制比较复杂,我们可以写在 tool_orchestrator目录下,这里面专门写一些管理工具来管理这些执行器的周期、进程、处理边界情况等。
3.2.4 工程化思维展开
既然上面说到工程设计,并且文章面向初学者和开发者,我们稍微展开讲解一下工程设计中的一些要点和一些思维。以 Agent CLI 为例子,当你要设计它的时候,你需要清楚的了解,这里面大致有哪些模块?你如何将这些模块进行分类?模块和模块之间你打算如何设计它们的功能和联系?
举个例子,模块 A 负责上下文,那么上下文包括裁剪模块,加载模块,存储模块;B 负责 memory,那么 memory 包括长中短期模块,memory 驱动加载模块。这就是你需要先了解大致模块有哪些。
如果作为一个清晰的项目目录设计,我建议大家把这些非常庞大的功能建立一个项目目录(比如例子中提到的上下文作为一个项目目录,把 memory 作为一个项目目录)。我认为一个目录的设计是工程框架设计的基石,能够体现你个人的工程化思维。更为重要的是,面对一个企业级的项目,你必须要考虑到边界情况和安全情况。当面对高并发调用时,系统有没有什么机制进行处理,分担服务器的压力?哪些内容作为本地缓存保证用户的隐私?总结来讲工程化思维的核心便是由点到面进行展开思考,最后再收敛到这个点上。
(如果大家对这部分感兴趣,我后面可以单独出一篇文章进行单独的讲解)
3.3 Agent 编排工具
下面我们回归正题,继续分析 Agent 编排工具。当前很多 Agent 系统采用的是多 Agent系统。一个系统中会有很多 Agent(比如 ruflo 这个项目,他在官方的 README 中说明了项目中有 100 多个 Agent 集群)。
参考引用:https://github.com/ruvnet/ruflo.git
"Agent = Model + Harness. ... Ruflo is the harness — the execution layer around Claude Code and
Codex that adds 100+ specialized agents, coordinated swarms, self-learning memory, federated comms across machines, and enterprise security guardrails."
这里建议大家根据业务逻辑去制定项目中 Agent数量。并不是越多越好,真正好的工程设计也需要考虑成本因素。那么对于 Agent CLI 来说,通常 10 个左右的 Agent 数量能够满足其功能。
Agent 编排从狭义角度去思考其实就是广为讨论的 workflow,Agent 编排工具就是 workflow编排工具。比较火的编排工具有 langchain、langgraph 这些组件,包括有零代码工作流程编排平台如 dify、n8n(这里面演变成了一句话帮你生成一个完整的 Agent workflow,比如 Relay APP)。
3.3.1 OpenAI 提出的子 Agent 抽象
OpenAI 在《Orchestrating Agents: Routines and Handoffs》提出两个基本抽象:Routines + Handoffs。
• 作者:Ilan Bigio(OpenAI 工程师)
• 发布日期:2024 年 10 月 10 日(Oct 10, 2024)
• URL:https://cookbook.openai.com/examples/orchestrating_agents
文章摘取:
"What if instead [of returning a string], we return an Agent object to indicate which agent we want to transfer to?"
文章里 Ilan Bigio 对这个 trick 的评价是:
"A simple, but surprisingly effective way to do this is by giving them a transfer_to_XXX function, where XXX is some agent. The model is smart enough to know to call this function when it makes sense to make a handoff!"
2024-10-11(也就是文章发出来第二天),OpenAI 把这个思想打包成了一个最小可运行框架Swarm。由此子 Agent 作为工具被调用的设计被提出并且被实现。Swarm 的 README 直接说:
• GitHub:https://github.com/openai/swarm
• PyPI:openai-swarm 0.1.1(Released: Oct 17, 2024)
• License:MIT
• 作者:OpenAI Solutions(维护者 wirthual)
"The primary goal of Swarm is to showcase the handoff & routines patterns explored in the Orchestrating Agents: Handoffs & Routines cookbook. It is not meant as a standalone library, and is primarily for educational purposes."
这个思想后来成为了行业的范式。
3.3.2 Anthropic 的工程化
不过在 2026-01-23 Anthropic Blog(Cara Phillips)中工程化了这个思想。文章中指出的核心思想是,子代理可以解决一些真正的限制,例如:
• 上下文限制
• 专业化限制
• 并行执行的限制
Agent 子代理的编排取决于具体的情景,而非问题类型。设定明确的验证点,子代理无需了解全部上下文(这其实和第一条呼应上了,解决上下文的限制问题)。
总结一下:在 Agent 编排工具上不仅仅是传统意义上的工具,工程界已经把 Agent 作为工具并且广泛使用。在设计上,我们需要根据任务场景设定你的子 Agent(比如任务情景为检索、编码、整合)。子代理的存在是为了专业化地解决业务场景,不能为了设计子代理而设计子代理(这也是 Anthropic 公司在上面的技术报告中提出的当前大部分 Agent 工程师在设计中存在的问题)。毕竟多一个子代理,就会多一份 Token,如果这个业务在自动化脚本下就能够稳定高质量的完成,那么我们在设计的时候就不需要多花费这笔 Token 成本。
3.4 搜索工具
搜索工具可以分为系统搜索工具和外部搜索工具。
对于系统搜索工具,主要负责:
• 搜索系统中的工具(这个工具主要是为 Agent 设计,让 Agent 调用这个工具,迅速的能够知道当前能够调用哪些工具)
• 列出 MCP server 中的资源等
对于外部搜索工具,主要负责一些外部的信息:
• 比如搜索工具(如果想免费使用的话可以下载 duckduckgo库,调用这个工具可以实现搜索,但是需要你自己负责外部信息上下文的裁剪)
• 现在市面上有非常多的开源爬虫工具,比如maxun、firecrawl(个人感觉这个非常好用)、Tavily search 等等
• 如果你爬虫技术不好,又不想自己负责搜索信息的裁剪,那么你完全可以使用这些开源工具
3.5 MCP
最后 MCP。MCP Server 分为本地的,你自己部署到服务器上的和托管付费的:
• 第一种完全免费
• 第二种需要你支付服务部署的费用
• 第三种则是付费点,需要付费给云厂商对于 MCP 的设计,整个链路是:
AI → MCP Client → MCP Server → 外部资源
你需要自己写一个 MCP Client 来连接外部服务提供的 MCP Server。
大家可以这样理解 MCP:你有一个 U 盘(你自己的业务),电脑上有文件需要下载到 U 盘(外部服务),但是这个电脑只能接受一种插口,这时候,转接插口出现了,你只需要让转接头知道你的 U 盘插口型号就能够轻松的下载电脑上的文件。
你需要在你的 MCP 中设计以下要点:
1. 管理多个 MCP Server
2. 建立 stdio 或 HTTP 连接
3. 获取工具列表
4. 获取资源
5. 获取 Prompt 调用工具
6. 将工具结果返回给 LLM
其中 3 和 4 可以写在系统搜索工具中。
楼主 · 历史 (2)