从零实现 GeekAgent —— Day3 Bash 工具

💡 原文中文,约6900字,阅读约需17分钟。
📝

内容提要

本文介绍从零实现GeekAgent的第三天:为模型添加Bash工具,使其能执行本地shell命令。实现包含超时(10秒)、输出截断(2000字符)和执行前确认三道安全护栏,确认逻辑可替换以便未来升级权限模型。通过新增run_shell工具,模型可主动调用命令并获取结果,为后续读写文件等能力奠定基础。

🔎

延伸解读

安全护栏的必要性

文章强调,让模型直接执行shell命令存在风险,因此必须设置超时、输出截断和执行前确认三道护栏。超时防止命令挂起阻塞循环,截断避免输出撑爆上下文,确认则防止危险命令如rm -rf被误执行。这些护栏是Agent安全运行的基础,缺一不可。

确认逻辑的可替换设计

Day3将确认逻辑抽象为可注入的confirm函数,通过setConfirmFn替换实现。这样后续升级权限模型时,只需替换确认函数,无需改动工具调用循环。这种设计提高了代码的可维护性和扩展性,是Agent权限管理的关键一步。

Bash工具的能力边界

文章指出,Bash工具几乎能覆盖所有文件操作,但直接使用存在安全风险。Day3通过run_shell工具封装了bash命令,并加上护栏,但明确未实现权限模型、目录隔离和流式输出。这些限制为后续开发指明了方向,如Day4将拆出只读工具和写工具。

Q&A

GeekAgent Day3 中,run_shell 工具的作用是什么?

run_shell 工具允许模型在本地执行 shell 命令,并将标准输出和标准错误合并后返回给模型,使模型能够主动操作真实环境。

GeekAgent 的 Bash 工具设置了哪些安全护栏?

设置了三个安全护栏:超时(10秒)、输出截断(2000字符)和执行前确认(y/N)。

为什么 shell 不能直接裸跑?

因为模型可能产生幻觉,直接执行任意命令可能导致永久阻塞、上下文撑爆或危险操作(如 rm -rf),所以需要超时、截断和确认等护栏。

GeekAgent Day3 中,确认逻辑是如何设计的?

确认逻辑被封装在 run_shell 工具内部,通过 confirm 函数实现,该函数可通过 setConfirmFn 注入,默认未注入时拒绝执行。这样后续可以替换为权限模型,而不影响循环。

GeekAgent Day3 中,输出截断是如何实现的?

使用 truncate 函数,当输出超过 2000 字符时,截断并附上原长度提示。

GeekAgent Day3 中,超时是如何实现的?

使用 Node.js 的 exec 内置 timeout 选项,设置为 10 秒,超时后自动杀掉子进程并返回失败信息。

GeekAgent Day3 中,执行前确认的默认行为是什么?

默认行为是拒绝执行,因为 confirm 函数未注入时返回 false,只有通过 installCliConfirm 注入后才会弹出 y/N 提示。

GeekAgent Day3 中,如何将确认逻辑接入主程序?

在 index.ts 中调用 installCliConfirm(rl) 一行代码,将主 REPL 的 readline 接口注入为确认实现。

GeekAgent Day3 中,终端着色是如何处理的?

复用 Day 1 的 color.ts,将工具调用进度行和执行前确认提示染成黄色,与模型正文的绿色区分。

GeekAgent Day3 中,明确没有实现哪些功能?

没有实现权限模型(仅每次询问)、目录隔离(可访问任意路径)、流式输出(命令执行完才一次性返回)。

🏷️

标签

➡️

继续阅读