拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Dora:基于Bash的轻量级AI Agent,让LLM安全执行系统命令

如果你最近在关注 AI Agent 领域可能会发现一个有趣的现象很多项目都在追求“大而全”。它们集成了复杂的工具链、庞大的知识库、精密的规划器甚至需要专门的框架来管理状态。这当然很强大但对于只想快速验证一个想法或者让 LLM 帮你自动化处理一些本地文件、执行几个系统命令的开发者来说这种“重武器”反而成了一种负担。Dora的出现正是对这种“过度工程化”趋势的一次优雅反击。它的核心主张极其简单一个真正可用的 LLM Agent其核心能力可能并不需要复杂的框架而仅仅是一个能够安全、可控地执行 Bash 命令的接口。今天要介绍的 Dora就是一个践行这一理念的微型项目。它没有复杂的依赖没有臃肿的架构其全部“工具”能力就建立在 Bash 这个最古老、最通用的系统 Shell 之上。通过这篇文章你将彻底理解 Dora 的设计哲学并亲手搭建一个属于你自己的、能理解自然语言并执行系统任务的 AI 助手。更重要的是你会明白为什么有时候“少即是多”以及如何在实际项目中安全地运用这种能力。1. Dora 要解决的核心问题从“玩具”到“工具”的最后一公里在深入代码之前我们必须先回答一个问题为什么是 Bash以及 Dora 究竟想解决什么痛点当前很多 AI Agent 演示令人惊艳它们能联网搜索、写邮件、生成图表。但当你真正想把它接入自己的开发环境让它帮你重命名一批文件、清理日志、或者执行一个本地的构建脚本时往往会遇到障碍环境隔离过强很多框架为了安全将 Agent 限制在沙箱中无法直接操作宿主机的文件系统或调用本地命令。工具定义繁琐你需要为每一个想执行的操作比如grep、find、curl编写专门的“工具”函数并注册到框架中过程冗长。依赖复杂动辄需要安装 Python 虚拟环境、Node.js 生态的包甚至 Docker只为运行一个简单的自动化任务。认知负担重你需要先学习框架的特定概念如 Planning、Memory、Skill才能开始使用。Dora 的答案直击要害将 Bash Shell 本身作为一个超级工具Meta-Tool暴露给 LLM。这意味着只要 LLM 能生成正确的 Bash 命令它就能完成几乎所有在终端里可以做的事情。这极大地降低了“工具化”的门槛。Dora 的核心价值判断是对于大量本地化、系统级的自动化任务一个具备基础 Bash 命令生成与安全执行能力的轻量级 Agent其实用价值远高于一个功能全面但难以集成和定制的重型框架。它瞄准的正是“从想法到自动化”的最后一公里让开发者能用最少的配置快速获得一个能理解“帮我把当前目录下所有.log文件移动到backup/文件夹”这类指令的智能助手。2. 核心概念与工作原理当 LLM 遇见 Shell要理解 Dora需要厘清几个关键概念以及它们是如何协同工作的。2.1 LLM Agent 的简化模型一个典型的 LLM Agent 工作流可以简化为以下循环感知Perception接收用户输入自然语言。规划PlanningLLM 思考需要做什么分解为步骤。执行Execution调用一个或多个工具Tools来执行具体步骤。观察Observation获取工具执行的结果。循环根据观察结果决定下一步是继续执行、重新规划还是返回最终答案给用户。2.2 Dora 的极简架构Dora 对这个模型做了极致简化规划与执行合一LLM 的主要任务就是根据用户请求直接生成单条、可执行的 Bash 命令。唯一工具Bash Shell。Dora 不管理多种工具它只提供一个安全的接口来运行 Bash 命令。状态管理极简。通常只维护当前工作目录和上一次命令的执行结果。2.3 安全执行机制核心中的核心这是 Dora 与一个“简单粗暴”的os.system调用最大的区别。允许 LLM 直接执行 Bash 命令是极其危险的想象一下rm -rf /或下载恶意脚本。因此Dora 必须包含一个安全层Safety Layer通常包括命令过滤阻止执行明确危险的命令如rm、dd、mkfs、wget到可疑地址等。权限限制以非特权用户身份运行命令。交互确认可选对于高风险或修改性操作先向用户确认再执行。工作目录隔离将 Agent 限制在特定的沙箱目录内操作。Dora 的精妙之处在于它在提供强大灵活性的同时通过设计来约束风险而不是通过限制功能来逃避风险。3. 环境准备与前置条件由于 Dora 是一个微型项目其环境准备非常简单。我们将以最典型的 Python 实现为例进行说明。基础环境要求操作系统Linux 或 macOSWindows 需要 Git Bash 或 WSL 来获得完整的 Bash 环境。Python版本 3.8 及以上。这是运行 LLM 客户端和 Dora 逻辑的主语言。Bash标准的 Shell 环境。LLM API 密钥你需要一个能访问大模型 API 的密钥。我们将使用OpenAI 的 GPT 系列如 gpt-3.5-turbo作为示例因为它最通用。你也可以替换为 Claude、DeepSeek 或本地部署的模型。安装步骤创建并进入项目目录mkdir dora-agent cd dora-agent创建虚拟环境强烈推荐python3 -m venv venv source venv/bin/activate # Linux/macOS # 在 Windows 上: venv\Scripts\activate安装核心依赖Dora 的核心依赖通常只有 OpenAI Python 库。pip install openai如果你打算使用其他模型比如通过litellm来统一接口可以安装pip install litellm关键配置设置你的 OpenAI API 密钥。永远不要将密钥硬编码在代码中# 在终端中设置环境变量临时 export OPENAI_API_KEYyour-api-key-here # 或者更持久的方法写入 ~/.bashrc 或 ~/.zshrc 文件末尾 echo export OPENAI_API_KEYyour-api-key-here ~/.zshrc source ~/.zshrc在代码中我们将通过os.environ来读取这个密钥。4. Dora 核心流程拆解与实现现在我们来一步步构建 Dora 的核心。我们将创建一个名为dora.py的文件。4.1 第一步导入依赖与基础设置# dora.py import os import subprocess import sys from typing import Optional, Tuple import openai # 从环境变量读取 API 密钥 client openai.OpenAI(api_keyos.environ.get(OPENAI_API_KEY)) # 定义模型可以根据需要更换 MODEL gpt-3.5-turbo # MODEL gpt-4 # 如果使用 DeepSeek 等需调整 base_url 和 model name # client openai.OpenAI(api_keyos.environ.get(DEEPSEEK_API_KEY), base_urlhttps://api.deepseek.com) # MODEL deepseek-chat4.2 第二步构建安全命令执行器这是 Dora 的“心脏”。我们需要一个函数它能执行命令但会先进行安全检查。def execute_command_safely(command: str, cwd: str None) - Tuple[str, str, int]: 安全地执行 Bash 命令。 返回: (stdout, stderr, return_code) # 1. 基础安全检查黑名单机制 dangerous_patterns [ rm -rf /, rm -rf /*, mkfs, dd if, chmod -R 777 /, /dev/sda, :(){:|:};:, wget http://, curl -O http:// # 可以更精细地控制网络访问 ] for pattern in dangerous_patterns: if pattern in command: return , fSecurity Alert: Command blocked due to dangerous pattern {pattern}., 1 # 2. 可选交互式确认对于某些写操作 # 这里我们简化仅对包含 rm 的命令进行提示示例 # 在实际项目中可以设计更复杂的规则或用户交互。 if rm in command and -f in command: print(f警告即将执行删除命令: {command}) confirm input(确认执行(y/N): ) if confirm.lower() ! y: return , Command cancelled by user., 0 # 3. 执行命令 try: # 使用 subprocess.run可以更好地控制超时、工作目录等 result subprocess.run( command, shellTrue, capture_outputTrue, textTrue, cwdcwd, # 可以限制工作目录 timeout30, # 防止命令长时间运行 executable/bin/bash # 明确指定使用 bash ) return result.stdout, result.stderr, result.returncode except subprocess.TimeoutExpired: return , Command timed out after 30 seconds., 1 except Exception as e: return , fCommand execution failed: {str(e)}, 1关键点解析黑名单Blacklist我们阻止了明显危险的命令模式。这是一种基础但必要的防护。更高级的方案可以使用白名单只允许特定命令但会牺牲灵活性。用户确认对于强制删除 (rm -f) 这类操作增加一次人工确认是防止 LLM“手滑”的有效手段。subprocess.run参数shellTrue允许使用 Bash 语法管道|、重定向等。capture_outputTrue和textTrue方便我们获取字符串格式的输出。cwd可以将 Agent 限制在某个子目录下运行实现工作空间隔离。timeout防止命令无限期运行。executable指定 Bash确保环境一致性。4.3 第三步构建 LLM 提示词工程LLM 需要被明确地教导如何扮演一个“Bash 助手”。提示词Prompt的质量直接决定了命令生成的准确性和安全性。def build_system_prompt() - str: return 你是一个专业的系统管理员助手专门将用户的需求转化为安全、准确、高效的 Bash 命令。 你的核心规则 1. 你只能输出一个有效的 Bash 命令。不要输出任何解释、Markdown 代码块标记或额外文本。 2. 命令必须尽可能简单、直接优先使用常用工具如 ls, find, grep, awk, sed, cp, mv, cat, echo。 3. 绝对禁止生成任何危险命令包括但不限于直接删除根目录、格式化磁盘、下载并执行未知脚本、修改关键系统文件权限。 4. 如果用户请求模糊或无法用单个命令完成请生成一个能获取更多信息的命令例如 ls 来查看目录内容。 5. 当前工作目录是用户的主目录~但命令应具有通用性。 用户请求这个系统提示词做了几件重要的事明确角色和边界让 LLM 聚焦于“命令生成器”。强制输出格式“只能输出一个有效的 Bash 命令”是关键指令简化了后续的解析。灌输安全理念反复强调禁止危险操作。提供降级策略当请求不明确时引导 LLM 生成探索性命令如ls而不是胡乱猜测。4.4 第四步整合 Agent 主循环现在我们将 LLM 调用、命令生成、安全执行和结果观察串联起来。def dora_agent_loop(): Dora Agent 的主交互循环。 print(Dora Agent 已启动。输入您的请求或输入 quit/exit 退出。) print(当前工作目录:, os.getcwd()) print(- * 50) system_prompt build_system_prompt() conversation_history [{role: system, content: system_prompt}] while True: user_input input(\n您: ).strip() if user_input.lower() in [quit, exit, q]: print(再见) break if not user_input: continue # 1. 将用户输入加入历史并调用 LLM conversation_history.append({role: user, content: user_input}) try: response client.chat.completions.create( modelMODEL, messagesconversation_history, temperature0.1, # 低温度让输出更确定、更偏向命令 max_tokens150 ) # 2. 提取 LLM 生成的命令 assistant_reply response.choices[0].message.content.strip() # 清理可能的 markdown 代码块标记 if assistant_reply.startswith(bash): assistant_reply assistant_reply[7:] if assistant_reply.startswith(): assistant_reply assistant_reply[3:] if assistant_reply.endswith(): assistant_reply assistant_reply[:-3] command assistant_reply.strip() print(f生成命令: {command}) except Exception as e: print(f调用 LLM 时出错: {e}) continue # 3. 安全执行命令 stdout, stderr, return_code execute_command_safely(command) # 4. 处理并展示结果 print(f\n[执行结果]) if stdout: print(f标准输出:\n{stdout}) if stderr: print(f标准错误:\n{stderr}) print(f返回码: {return_code}) print(- * 30) # 5. 将执行结果作为观察反馈给 LLM更新历史可选用于多轮复杂任务 # 这里我们简化处理每次都是新的独立对话。若要支持多轮规划需将结果加入 history。 # observation f命令 {command} 执行完毕。返回码: {return_code}。输出: {stdout[:500]} # conversation_history.append({role: assistant, content: command}) # conversation_history.append({role: user, content: observation}) # 为简化我们重置历史只保留 system prompt开始新一轮。 conversation_history [{role: system, content: system_prompt}] if __name__ __main__: dora_agent_loop()5. 完整示例运行你的第一个 Dora Agent现在让我们把所有的代码整合起来并运行它。文件结构dora-agent/ ├── venv/ # Python 虚拟环境执行 source venv/bin/activate 后生成 ├── dora.py # 我们的主程序文件 └── .env (可选) # 用于存储 API 密钥需安装 python-dotenv运行步骤确保你已在项目目录下并且虚拟环境已激活。确保OPENAI_API_KEY环境变量已设置。运行程序python dora.py你将看到提示符然后可以开始与你的 Dora Agent 对话。交互示例Dora Agent 已启动。输入您的请求或输入 quit/exit 退出。 当前工作目录: /home/user/dora-agent -------------------------------------------------- 您: 列出当前目录下所有的 Python 文件 生成命令: find . -name *.py -type f [执行结果] 标准输出: ./dora.py 返回码: 0 ------------------------------ 您: 统计 dora.py 文件有多少行 生成命令: wc -l dora.py [执行结果] 标准输出: 120 dora.py 返回码: 0 ------------------------------ 您: 帮我在当前目录创建一个叫 test_project 的文件夹并在里面放一个 README.md 文件 生成命令: mkdir -p test_project echo # Test Project test_project/README.md [执行结果] 标准输出: 返回码: 0 ------------------------------ 您: 看看刚才创建的 README 文件内容 生成命令: cat test_project/README.md [执行结果] 标准输出: # Test Project 返回码: 0 ------------------------------看到这里你应该已经感受到了 Dora 的魅力。它就像一个坐在你终端里的、能理解你模糊意图的助手将你的自然语言指令转化为精准的 Bash 命令并执行。6. 效果验证与能力边界测试一个合格的 Agent 不仅要能完成简单任务还要能处理复杂、模糊的请求并且在危险边缘及时刹车。让我们对上面的实现进行一些测试。测试用例 1模糊请求的处理您: 我这里有点乱清理一下 生成命令: ls -la分析LLM 没有去猜测“清理”的具体含义是删除文件还是整理而是生成了一个探索性命令ls -la让用户先看到当前状态。这符合我们提示词中“获取更多信息”的策略是安全且合理的。测试用例 2多步操作的整合您: 找出所有昨天修改过的日志文件并把它们的名字存到一个列表里 生成命令: find . -name *.log -mtime -1 -type f modified_logs_yesterday.txt分析LLM 成功将“找出”和“存到列表”合并为一个命令使用了find的-mtime参数和输出重定向。这展示了其理解和组合能力。测试用例 3安全机制的触发您: 删除所有东西 生成命令: echo This command is too dangerous to execute. Please specify a directory or file pattern.分析这是一个理想情况LLM 直接拒绝生成危险命令。但依赖于 LLM 的“自觉”并不完全可靠。更可靠的是我们execute_command_safely函数中的黑名单。如果 LLM 生成了rm -rf /*也会被我们的安全层拦截。测试用例 4错误处理与反馈您: 把不存在的文件 important.txt 复制到 backup 文件夹 生成命令: cp important.txt backup/ 2/dev/null || echo File important.txt not found or backup/ directory does not exist.分析生成的命令包含了错误处理2/dev/null和|| echo ...。这非常出色LLM 预见到了可能的错误并生成了更健壮的命令。执行后你会看到“File not found”的提示而不是一个晦涩的 Bash 错误。通过这些测试我们可以验证 Dora 的基本能力是有效的同时安全机制也在起作用。它的边界在于处理需要多轮交互、复杂状态维护或图形界面的任务。7. 常见问题与排查思路在实际运行中你可能会遇到以下问题问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named openai未安装openai库或不在正确的虚拟环境中。在终端输入pip list | grep openai。激活虚拟环境 (source venv/bin/activate) 并执行pip install openai。openai.AuthenticationErrorAPI 密钥无效或未设置。检查echo $OPENAI_API_KEY是否输出正确密钥。重新设置环境变量并确保 Python 进程能读取到它。重启终端或 IDE。LLM 生成的命令总是失败提示词不够清晰或模型温度 (temperature) 太高导致输出不稳定。查看生成的原始命令内容是否包含多余文本。1. 优化系统提示词强调“只输出命令”。2. 将temperature参数降至 0.1 或 0。命令执行被安全层误拦截黑名单规则过于严格拦截了无害命令。检查被拦截的命令和匹配到的危险模式。调整dangerous_patterns列表使其更精确。考虑使用白名单模式。subprocess.TimeoutExpired执行的命令运行时间过长超过30秒。确认该命令是否确实需要长时间运行如编译。1. 对于已知的长任务在用户请求中明确说明。2. 适当增加timeout参数值。Agent 无法理解复杂请求请求本身过于复杂或模糊超出单轮命令生成的能力。观察 LLM 生成的命令是否偏离预期。1. 简化你的请求分步进行。2. 考虑实现多轮对话历史功能让 Agent 能基于上一步结果进行规划。在 Windows 上 Bash 命令无效环境是原生 CMD 或 PowerShell而非 Bash。在终端输入bash --version。1. 安装 Git for Windows使用 Git Bash。2. 启用 WSL (Windows Subsystem for Linux)。3. 修改代码适配 PowerShell 命令工作量较大。8. 进阶优化与工程实践建议基础的 Dora 已经能工作但要用于更严肃的场景还需要考虑以下优化点8.1 增强安全性白名单机制对于生产环境或高安全要求场景黑名单永远有漏网之鱼。可以转而使用白名单只允许执行预定义的、安全的命令集如ls,cat,grep,find(不带-delete),wc等。文件系统沙箱使用chroot、容器Docker或专用用户权限将 Agent 严格限制在某个目录下使其无法访问系统关键路径。网络访问控制默认禁止curl、wget等网络命令或只允许访问特定的内部地址。8.2 提升可用性会话历史与状态管理当前的实现每次都是新对话。要实现真正的多步任务如“找到错误日志” - “提取时间戳” - “统计数量”需要将命令执行结果作为上下文反馈给 LLM。修改conversation_history的维护逻辑即可。工具增强虽然核心是 Bash但可以包装一些常用操作为“高级工具”。例如一个“搜索文件内容”工具内部可能调用grep -r “pattern” . --include”*.py”但对用户暴露为更简单的指令。输出格式化对于ls、find等命令原始输出可能很乱。可以让 LLM 在生成命令时就加上格式化参数如ls -lh或者事后对输出进行整理。8.3 代码结构优化将项目模块化例如dora-agent/ ├── core/ │ ├── __init__.py │ ├── safety.py # 安全执行模块 │ ├── llm_client.py # LLM 交互模块 │ └── prompt.py # 提示词管理模块 ├── tools/ # 可插拔的工具集未来扩展 ├── config.yaml # 配置文件 ├── main.py # 主入口 └── requirements.txt8.4 配置化管理将模型类型、API 密钥、温度、超时时间、安全规则等提取到配置文件如config.yaml或.env文件中。# config.yaml llm: provider: openai model: gpt-3.5-turbo api_key_env_var: OPENAI_API_KEY temperature: 0.1 safety: enabled: true mode: blacklist # 或 whitelist blacklist_patterns: - rm -rf - mkfs - chmod 777 timeout_seconds: 30 workspace: base_path: /tmp/dora_workspace # 沙箱目录8.5 日志与审计任何自动化系统尤其是能执行命令的都必须有完整的日志。import logging logging.basicConfig(filenamedora_agent.log, levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) def execute_command_safely(command, cwd): logging.info(fAttempting to execute: {command} from {cwd}) # ... 执行逻辑 ... if return_code ! 0: logging.warning(fCommand failed: {command}. stderr: {stderr}) else: logging.info(fCommand succeeded: {command}) return stdout, stderr, return_code日志应记录时间戳、用户输入、生成的命令、执行结果返回码、错误信息。这对于问题回溯和安全审计至关重要。9. 总结从 Dora 看轻量级 Agent 的设计哲学通过从头构建一个 Dora我们揭示了一个核心思想AI Agent 的实用化不一定始于构建一个庞大的工具生态而可以始于赋予它安全使用现有最强工具Bash的能力。Dora 的极简设计带来了几个显著优势近乎零学习成本任何熟悉 Bash 的开发者都能立刻理解其能力边界和扩展方式。惊人的灵活性理论上所有能用命令行完成的任务Dora 都能尝试。极低的部署开销不需要额外的服务、数据库或复杂依赖。当然它的局限性也同样明显安全性高度依赖防护层、缺乏长期记忆、处理复杂多轮任务能力有限。因此Dora 更适合作为个人效率助手、自动化脚本的智能前端或是学习 Agent 概念的绝佳入门项目。给你的实践建议从本地、非关键任务开始用 Dora 帮你整理下载文件夹、批量重命名照片、搜索代码库。逐步构建自己的“工具库”当你发现某些复杂命令组合经常使用时可以将其封装成 Dora 的一个“技能”Skill例如一个clean_old_logs技能内部对应find /var/log -name *.log -mtime 7 -delete。永远把安全放在第一位在将其连接到任何存有重要数据的系统之前反复测试你的安全规则。考虑在白名单模式下运行。Dora 就像一把瑞士军刀中最基础的那片刀它简单但足以解决大量日常问题。在追求更智能、更强大的 Agent 框架之前不妨先用好这把“刀”它可能会为你打开一扇通往实用 AI 自动化的大门。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门