AI热点 5小时前 114 浏览次数 0 评论

保持终端的相关性:AI 智能体驱动的 CLIs 模式

InfoQ
InfoQ

发布了 116 文章

2019 年,AWS CLI 的第二个版本将默认分页器更改为 less 。这一变化为未来敲响了警钟,在 AI 智能体兴起的当下,破坏性变更变得愈发关键。就在那一天,成千上万的持续集成(CI)任务失败了,因为分页器变得具有交互性,在无头环境中等待着不会出现的键盘输入。是的,可以通过配置人为修复。但这一事件突出了 AI 智能体世界中的一个基本原则:命令行界面(CLI)必须可靠地运行,无需人工干预。

 

我观察到,从以人为中心的工作流程向代理式工作流程的转变在近年来急剧加速。像 GitHub Copilot CLI 和 Warp Agent Mode 这样的工具将自然语言转换为需要可靠执行的命令序列。今天,所有流行的 LLM 提供商都支持多步骤、链式代理式工作流程。这种转变是真实存在的。

 

在维护 CLI 近十年之后,我想深入探讨五个设计原则,这些原则将使 CLI 工具在 AI 时代取得成功。

 

人类便利性需要应急出口

AWS CLI 分页器事件说明了核心挑战。智能体无法回答问题,按键导航分页器,甚至无法解释输出中的颜色。它们运行的命令必须是确定性的,以便确定下一步的操作。

 

有效的模式提供了三种不同的解决路线。

 

显式标志

创建显式标志,如 --no-promp t 或 --no-interactive ,这些标志将禁用所有 CLI 命令从 stdin 读取。将不会有确认提示或分页器。这些是简单的更改,但人类可以通过 --help 发现它们,并在自动化中使用以实现确定性行为。

 

环境变量

环境变量允许进行一次性覆盖,但在运行任何命令之前就已确立全局上下文和控制。例如, NO_COLOR=true 可以去除所有 CLI 输出的颜色。为你的 CLI 工具名称保留自定义环境变量的前缀,如 MYCLI_PROFILE=dev 以启用工具上下文。这些特定于 CLI 的环境变量应该在 --help 文本的的“环境”部分中进行文档记录,以实现快速发现。建立一个清晰的优先级模型

explicit flags > env vars ,以促进确定性。

 

语义退出代码

退出代码传递关于命令执行的更深层次信息。成功时返回 0 ,用户定义的可纠正错误返回1-2 ,应用程序特定错误返回 3-125 。与环境变量一样,退出代码需要完整记录,并在次要版本中保持稳定。

 

但我在与 AI 智能体合作时了解到:智能体表现出与人类不同的行为使用模式。它们将命令快速串联在一起,其中一个命令的输出被管道传递到另一个命令的输入中。多个操作是并行启动的,而不是像人类那样顺序执行。它们甚至会根据解析结构化输出信息进行重试,并调整方向以达到最终目标。AI 智能体还寻找多种方式来确认它们的工作,例如在完成后运行后续命令,以检查成功而不是仅依赖退出代码。这种方法表明操作需要是幂等的,并且状态变化必须能够通过后续命令观察到。

 

这些模式不难实现,但需要关注一致性。创建一致的全局标志模式,以便在所有命令上实现结构化输出,如 --output json ,并确保你的 CLI 具有检查其拥有的资源状态的命令。

 

输出格式是一种 API 契约

这里有一个未被充分考虑的问题:每个输出结构化数据的 CLI 工具都在发布 API 契约。无论其输出是 JSON/YAML 或 TOML 格式,只要下游消费者依赖于输出字段名称、数据类型,无论是 stderr 还是 stdout ,都会受到影响。

 

让我们考虑两个例子,kubectl 和 terraform。

 

Kubernetes在v1.14中弃用了一个标志--export ),后来在 v1.18 中移除了它。该标志允许剥离集群特定的元数据,并将资源移动/导出到新集群。移除的原因是该功能存在多个缺陷,且无法覆盖其需要支持的所有服务。从命令行工具维护者的角度来看,这样的弃用是合理的。

 

然而,社区的反应却有所不同。使用 --export 生成模板的 Helm 图表无法正常工作。用于备份或将其检入版本控制的 CI/CD 管道也停止运行。即使在今天,在 GitHub 上搜索仍然能找到数千个对 kubectl get --export 的引用。

 

由于弃用操作有详细的文档记录,所以这并非单纯的沟通失误。问题在于没有认识到 CLI 的输出格式是契约,而契约是有依赖关系的。在日常使用中,人类可以适应并找到创造性的解决办法来应对这类问题。但在这种情况下,自动化系统会灾难性地崩溃,且没有简单的恢复方法。

 

Terraform 采取了不同的方式。每个 Terraform 状态文件都明确包含版本信息。这种包含方式在优先考虑向后兼容性的同时,提供了更安全的模式演进。

 

{  "terraform_version": "1.5.0",  "serial": 1,  "lineage": "3c77e9e7-0d23-9db4-4b42-4e12d0d531b4",  "version": 4}
复制代码

 

Terraform 状态文件是一个实时的工件,贯穿初始化、首次写入以及后续通过 Terraform CLI 进行的更新。通常,较新的 Terraform CLI 版本可以透明地升级较旧的状态。如果运行时遇到较旧的 JSON 模式编码版本或较旧的 Terraform CLI 版本,则会明确报错,防止数据损坏。最后,血统甚至会跟踪远程状态与本地状态,防止意外覆盖。

 

正如上面所证明的,这里的解决方案需要将 CLI 输出视为“版本化”的 API 表面积。对于所有产生结构化输出的命令,使用 JSON 模式或 CUE 明确定义模式会非常有益。更好的做法是将其纳入 CI 基础设施,以便在问题出现在生产环境之前就检测到破坏。

 

name: ci-checkon: [pull_request]jobs:  validate:    steps:      - make install #安装mycli      - make generate-schema # generate schema.cue      - run: mycli show --output json > show-output.json      - run: cue vet schema.cue show-output.json # 检测破坏性变更
复制代码

 

总之,像对待 API 一样对待 CLI 输出,并遵循类似的演变模式。增加性变更总是安全的,例如增加新的、可选的字段或新的命令。然而,破坏性变更要求进行主要版本更新。依靠语义化的版本控制,但如果变更是不可避免的,确保迁移路径被内置到工具本身中,以减轻过渡。更好的做法是,设计你的 CLI 架构,使得破坏性变更不会影响自动化工作流,因为任何由 CLI 创建的状态都可以在客户端进行版本控制。

 

通过 MCP 暴露 CLI 能力

 

模型上下文协议代表了 LLM 驱动的 AI 智能体与自定义 CLI 集成的最重要方式之一。现在,与基于训练数据了解工具的智能体不同,它们可以通过受限且版本化的模式动态发现功能并执行 CLI。

 

重要的是,如果没有 MCP,通过智能体调用 CLI 的整个过程可能会变得脆弱,因为输出格式可能会改变,相应的链式命令会在没有通知的情况下中断。这适用于我们之前讨论的所有内容,例如标志被弃用。

 

MCP 允许工具通过离散的、结构化的模式向智能体描述自己。

 

{  "name": "deploy",  "description": "Deploy the application to a chosen environment",  "inputSchema": {    "type": "object",    "properties": {      "environment": {        "type": "string",        "enum": ["staging", "production"],        "description": "Target environment"      },      "force": {        "type": "boolean",        "default": false,        "description": "Skip safety checks"      }    },    "required": ["environment"]  }}
复制代码

 

以上是智能体在运行时发现的部署工具的能力展示智能体可以在执行前清楚地验证输入,并轻松理解整体契约。此外,每个支持 MCP 的 CLI 现在可以立即提供给所有支持 MCP 的智能体,无需进一步定制集成工作。

 

MCP 工具描述可以直接从 CLI 的现有命令定义中派生。然而,至关重要的是,在构建 MCP 服务器之前,你的 CLI 要具备回归测试套件,使用像bats-core这样的工具,以在其版本中保持逃生舱口和输出格式。通过像fastMCP这样的框架来实现 MCP 协议会更容易,这些框架使得启动 MCP 服务器变得简单。根据你的 CLI 管理的内容,MCP 服务器可以配置为无状态包装器,使用临时的内存存储运行,或者作为具有持久存储支持的服务运行。

 

一旦你的 MCP 服务器设置好,复杂的智能体行为就成为来常态,例如并行编排多个工具,实现将不同工具串联起来的工作流,甚至随着通过 MCP 向智能体提供更多工具而不断演进这些工作流。

 

紧密的反馈循环

AI 智能体的运作方式与人类截然不同。认知货币也不同。人类可以耐心等待,思考下一步行动或重新思考,而不会打乱工作流程,但 AI 智能体完成相同任务时会消耗计算资源,例如占用 token、填满上下文窗口,甚至面临超时限制。

 

解决方案不仅仅是速度,而是要在正确的时间提供正确的反馈。Agent-CLI 交互需要以下模式,每种模式都服务于不同的目的。

 

早期验证

在你的 CLI 中,加入一些命令,以便在智能体朝着正确方向前进时提供早期信号,尤其是在执行诸如部署之类的潜在破坏性操作时。

 

ansible-playbook nginx.yml --syntax-checkansible-playbook nginx.yml --check --diff
复制代码

 

在上述代码片段中, --syntax-check 解析 Ansible 剧本并解析变量/角色,以确保没有语法错误。带有--check--diff 标志的命令是一个试运行操作,如果有任何变化,它会精确展示将要进行的更改,并附带相应的语义退出代码。这为执行操作的智能体提供了一个清晰的信号,以判断是否可以安全地继续进行。

 

进度报告

由智能体启动的长时间运行的任务需要一种报告进度的方式,否则它们看起来就像是挂起了。一个例子是来自 AWS CloudFormation 的事件流。智能体可以读取输出,及早检测失败,甚至可以根据部署的进展估计何时中断自己。此外,CLI 写入的流保持一致性很重要,因为 AI 智能体经常在后台启动任务,并将输出重定向到它们稍后可以检查的文件中。

 

aws cloudformation describe-stack-events --stack-name app --output json
复制代码

 

优雅终止

所有 CLI 工具都应采用最佳实践来妥善处理操作中断,同时保持状态一致。本质上,它们应该能够优雅地处理 SIGTERM ,并采取适当的清理措施。智能体应该能够依赖工具的一致性工作,否则 AI 智能体的整体效率会降低。在这种情况下,工具的质量确实很重要。过去那种“拙匠怨工具”的说法对 AI 智能体并不适用。我们的任务是提供具有内置正确行为的正确工具。

 

应用这些模式会产生显著的复合效应。更快的反馈意味着更多的迭代,智能体能更有效地利用 token,从而在整体上提高任务完成的可靠性。

 

不要猜测,依赖遥测数据

传统的 CLI 分析试图在生命周期管理中找到模式,然后转向自动化。智能体表现出完全不同的使用模式,它们不会逐渐发现功能。它们会一次性全部采用,并且可能不会阅读 --help 页面。然而,它们会执行一致的标志组合,并在快速连续中遵循高度重复的链式命令。遥测将比以往任何时候都更重要。除了人类和自动化的使用模式,我们还需要跟踪 AI 智能体的使用。收集的遥测数据应该是明确的,并得到用户的同意。在 CLI 的首次运行中,应该披露所收集的确切信息(例如,操作系统版本、基础命令、标志、延迟、匿名安装 ID、会话 ID 和时间戳),并提供一种简单的退出方式,例如设置环境变量 MYCLI_NO_TELEMETRY=1

 

export MYCLI_NO_TELEMETRY=1mycli config set telemetry false

# 显示当前状态mycli telemetry status# 遥测:已禁用(MYCLI_NO_TELEMETRY=1)
复制代码

 

遥测应用于通过发现使用模式来确定优化优先级。CI/CD 系统的错误率应该推动对结构化输出的投资。中断或超时应该推动性能改进。识别一致的模式应该建议更好的默认值。

 

数据驱动的方法比以往任何时候都更加核心。得出的洞察将能更好提高智能体的可靠性,同时仍然能让用户控制和了解用于遥测的数据。

 

面向多受众的未来:人类、自动化以及如今的 AI 智能体

命令行工具正日益成为人类与代理式 AO 协作的通用 API 层。这种协作标志着软件开发领域的一次重大转变,不容小觑。那些认识到这一变化的工具将在这一现实环境中蓬勃发展。传统上,命令行工具注重简单、可组合的界面,使用户能够完成复杂的任务。如今,这些工具需要进化,以便能够与 AI 智能体协同工作。问题不在于 CLI 是否需要与 AI 智能体配合,而在于它们现在是否已经做好了准备?

 

原文链接:

https://www.infoq.com/articles/ai-agent-cli/

InfoQ

InfoQ

116 文章 16039 浏览次数 0 粉丝

评论 (0)

睡觉动画