Skip to content

第 13 章 · 综合实战二:代码库只读审查助手 ​

把第 3、5、6 章拼成真实场景:agent 在一个临时仓库里做只读审查——AGENTS.md 提供仓库规则,audit skill 提供审查清单,FilesystemBackend(virtual_mode=True) 把文件工具关在 root_dir 内。先做无 key 的结构自检,再执行模型步骤。

机制与设计选择 ​

memory 在启动时加载 AGENTS.md;skills 是按需全文,audit skill 的三类检查点只在任务相关时被读取。tools_by_name 检查保证默认七件文件工具都可见——“只读”是 system prompt 的约定,不是工具层强制,真正强制要靠第 3 章的权限与中间件 allowlist。

示例 ​

python
import os, pathlib, tempfile, shutil
from langchain_openai import ChatOpenAI
from deepagents import create_deep_agent
from deepagents.backends import FilesystemBackend

root = tempfile.mkdtemp(prefix="deepagents-audit-")
try:
    repo = pathlib.Path(root) / "repo"
    repo.mkdir()
    (repo / "AGENTS.md").write_text("# Repo rules\n- All CLI writes must be idempotent\n- Tests live in tests/\n")
    (repo / "main.py").write_text("import os\nos.system('rm -rf build')  # risky shell use\n")
    skill = pathlib.Path(root) / "skills" / "audit"
    skill.mkdir(parents=True)
    (skill / "SKILL.md").write_text(
        "---\nname: audit\ndescription: Audit a codebase for risky shell and missing tests\n---\n"
        "Flag: (1) os.system/subprocess without validation, (2) missing tests for public functions.\n"
    )

    model = ChatOpenAI(
        model=os.environ["MODEL_ID"],
        api_key=os.environ["DEEPAGENT_API_KEY"],
        base_url=os.environ.get("DEEPAGENT_BASE_URL", "https://api.openai.com/v1"),
    )
    agent = create_deep_agent(
        model=model,
        backend=FilesystemBackend(root_dir=str(repo), virtual_mode=True),
        memory=[str(repo / "AGENTS.md")],
        skills=[str(skill.parent)],
        system_prompt="Audit this repository. Inspect files with read_file/ls/grep; do not modify files.",
    )

    # Structural self-check (no model call needed):
    available = sorted(agent.nodes["tools"].bound.tools_by_name)
    for required in ["ls", "read_file", "write_file", "edit_file", "delete", "glob", "grep"]:
        assert required in available, (required, available)
    print("file tools visible to the model:", available)

    # Model step (skipped when no key is configured):
    if os.environ.get("DEEPAGENT_API_KEY") not in ("", "sk-fake"):
        result = agent.invoke(
            {"messages": [{"role": "user", "content": "Run the audit skill on this repo and report findings."}]},
            {"configurable": {"thread_id": "ch13"}},
        )
        print(result["messages"][-1].content)
    else:
        print("model step skipped: DEEPAGENT_API_KEY not configured; structural check passed.")
finally:
    shutil.rmtree(root, ignore_errors=True)

运行与验收 ​

无 key 运行:输出文件工具列表与 model step skipped,结构断言通过。配置 key 后运行:最终消息应指出 main.py 里的 os.system 风险与缺失的测试,且不修改任何仓库文件(临时目录在 finally 清理)。

容易踩的坑 ​

系统提示词的“只读”可以被模型违反;审计类任务应在代码层限制写工具或拒绝写路径。临时目录是隔离手段,不能替代权限边界;生产仓库用 StoreBackend/远程沙箱而不是本地临时目录。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. memory 何时加载 AGENTS.md?

2. skills 如何进入上下文?

3. tools_by_name 检查证明什么?

4. 只读如何强制?

动手实践 ​

  1. 把 audit skill 换成你的项目规范。
  2. 用第 3 章权限规则真正禁止写 .env。
  3. 为 main.py 补测试,观察二次审查结果。

官方参考 ​

核验日期:2026-09-17,示例已在本机离线运行验证。