搭建一个轻量 Agent Harness——让 AI Agent 安全地执行命令、读写文件

搭建一个轻量 Agent Harness------让 AI Agent 安全地执行命令、读写文件、调用 API

Agent 不只是调用 LLM,还需要执行命令、读写文件、调 API。但让 AI 直接操作你的电脑是有风险的。Agent Harness 就是解决这个问题的------给 Agent 一个受限的"沙箱"。

Harness 做什么

复制代码
Agent 想做什么 → Harness 检查和审批 → 执行 → 返回结果

核心能力:
├─ 🛡️ 沙箱执行:限制 Agent 只能操作指定目录
├─ 📋 命令白名单:只允许安全的命令
└─ ✅ 人工审批:危险操作需要确认

核心代码

python 复制代码
# harness.py
import subprocess, os, shlex
from pathlib import Path

class AgentHarness:
    """Agent 安全执行环境。"""

    ALLOWED_COMMANDS = {"ls", "cat", "head", "tail", "grep", "wc",
                        "find", "echo", "date", "python", "pip", "git"}

    def __init__(self, workspace="./agent_workspace", require_confirm=True):
        self.workspace = Path(workspace).resolve()
        self.workspace.mkdir(parents=True, exist_ok=True)
        self.require_confirm = require_confirm
        self.history = []

    def execute(self, command: str) -> dict:
        """在沙箱中执行命令。"""
        cmd_parts = shlex.split(command)
        if not cmd_parts:
            return {"error": "Empty command"}

        # 安全检查
        base_cmd = cmd_parts[0]
        if base_cmd not in self.ALLOWED_COMMANDS:
            return {"error": f"命令 {base_cmd} 不在白名单中"}

        # 危险操作需要确认
        dangerous = any(k in command for k in ["rm ", "delete", "DROP", ">", ">>"])
        if dangerous and self.require_confirm:
            print(f"\n⚠️ 危险操作:{command}")
            ok = input("确认执行?[y/N] ").strip().lower()
            if ok != "y":
                return {"error": "用户取消"}

        try:
            result = subprocess.run(
                command, shell=True, capture_output=True, text=True,
                timeout=30, cwd=str(self.workspace),
            )
            output = result.stdout.strip()
            if result.returncode != 0:
                output = result.stderr.strip() or output

            self.history.append({"command": command, "output": output[:500]})
            return {"output": output[:2000], "code": result.returncode}
        except subprocess.TimeoutExpired:
            return {"error": "命令执行超时(30s)"}
        except Exception as e:
            return {"error": str(e)}

    def read_file(self, path: str) -> dict:
        """安全读取文件。"""
        full_path = (self.workspace / path).resolve()
        if not str(full_path).startswith(str(self.workspace)):
            return {"error": "不能读取工作目录以外的文件"}

        try:
            content = full_path.read_text(encoding="utf-8", errors="ignore")
            return {"content": content[:5000]}
        except Exception as e:
            return {"error": str(e)}

    def write_file(self, path: str, content: str) -> dict:
        """安全写入文件。"""
        full_path = (self.workspace / path).resolve()
        if not str(full_path).startswith(str(self.workspace)):
            return {"error": "不能写入工作目录以外的文件"}

        if self.require_confirm:
            print(f"\n📝 即将写入:{path}({len(content)} 字符)")
            ok = input("确认写入?[y/N] ").strip().lower()
            if ok != "y":
                return {"error": "用户取消"}

        try:
            full_path.parent.mkdir(parents=True, exist_ok=True)
            full_path.write_text(content, encoding="utf-8")
            return {"status": "ok", "path": str(full_path.relative_to(self.workspace))}
        except Exception as e:
            return {"error": str(e)}

Agent + Harness 组合使用

python 复制代码
# agent_with_harness.py
from openai import OpenAI
from harness import AgentHarness
import os, json
from dotenv import load_dotenv
load_dotenv()

client = OpenAI(api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com/v1")
harness = AgentHarness("./workspace")

TOOLS = [
    {"type": "function", "function": {
        "name": "execute_command", "description": "在沙箱中执行命令。可用命令:ls, cat, grep, find, python, git",
        "parameters": {"type": "object", "properties": {"command": {"type": "string"}}, "required": ["command"]}
    }},
    {"type": "function", "function": {
        "name": "read_file", "description": "读取工作目录中的文件",
        "parameters": {"type": "object", "properties": {"path": {"type": "string"}}, "required": ["path"]}
    }}
]

def run_agent(task):
    messages = [{"role": "system", "content": f"你是一个编程助手。工作目录:{harness.workspace}"}]
    messages.append({"role": "user", "content": task})

    while True:
        resp = client.chat.completions.create(
            model="deepseek-chat", messages=messages, tools=TOOLS, tool_choice="auto"
        )
        msg = resp.choices[0].message

        if not msg.tool_calls:
            return msg.content

        for tc in msg.tool_calls:
            name = tc.function.name
            args = json.loads(tc.function.arguments)

            if name == "execute_command":
                result = harness.execute(args["command"])
            elif name == "read_file":
                result = harness.read_file(args["path"])
            else:
                result = {"error": "Unknown tool"}

            messages.append(msg)
            messages.append({"role": "tool", "tool_call_id": tc.id, "content": json.dumps(result)})

# 使用
result = run_agent("在当前目录创建一个 hello.py,内容为打印 Hello World,然后运行它")
print(result)

总结

一个轻量的 Agent Harness,三个核心能力:

  1. 命令白名单:限制 Agent 只能执行安全命令
  2. 目录隔离:Agent 只能操作工作目录内的文件
  3. 危险操作确认:删除、覆盖等需要人工审批

几十行代码实现,让你的 Agent 既强大又安全。

本文由 Zyentor(智元界)原创发布


本文发布于 Zyentor(智元界) ------ AI 开发者社区 原文链接:www.zyentor.com/news/4324

相关推荐
for_ever_love__15 分钟前
Map-Reduce 式全文问答:当文档超出上下文时的分而治之
人工智能·map·汇总·分块·rag·reduce·长文
海宇数据21 分钟前
零信任架构实战:基于海宇入职背调报告构建自动化即时配送与网约车众包运力准入鉴权网关
运维·人工智能·架构·自动化
2601_9622035123 分钟前
2026企业级AI智能体办公平台对比:KuWork vs bit-Agent、安捷AI、Team Claw等6款,文档、报告、PPT与策划方案怎么选?
人工智能
墨子夕25 分钟前
创新的潮汐——从科学发现到资本周期的百年规律(第二卷)
大数据·数据库·人工智能
console.log('npc')1 小时前
第 1 章 项目概述与环境搭建
前端·人工智能·大模型
IT_陈寒1 小时前
React组件莫名重渲染?你可能忘了这个小细节
前端·人工智能·后端
天远API1 小时前
零信任架构实战:基于天远公安二要素政务版构建自动化不动产交易与契税核算实名核实网关
人工智能·架构·自动化·php
朋友圈自动点赞工具1 小时前
浏览器端AI模型实测:五个可用场景
人工智能
承渊政道1 小时前
【从零开始大模型开发与微调:基于PyTorch与ChatGLM】(从ChatGLM本地化到LoRA、PEFT的高级微调)
android·人工智能·pytorch·chatglm·本地化部署·大模型开发与微调
盟接之桥1 小时前
盟接之桥谈线束数字化-按单入按单出:线束企业库存管理的破局之道
大数据·前端·网络·数据库·人工智能·制造