dexmaddy/ai-agent-harness

GitHub: dexmaddy/ai-agent-harness

基于 hook 的 AI 编码 agent 会话管控框架,通过结构性拦截机制强制执行启动加载、漂移检测、信息整合与自我验证,解决 agent 会话中的规则漂移和上下文浪费问题。

Stars: 1 | Forks: 1

# AI Agent 框架 一个基于 hook 的框架,让 AI 编码 agent 的会话更加可靠—— 从启动、工作到关闭。通过拦截机制进行结构性强制执行, 而不是靠提醒式的建议。 ## 问题所在 如果没有框架,AI agent 的会通常会面临六个问题: 1. **上下文浪费** —— 每次会话都加载所有内容,会在当前任务不需要的规则上消耗大量 token。 2. **规则漂移** —— 事实、计数和引用会在不知不觉中失效。 直到违反了某项规则才会被发现。 3. **启动混乱** —— 指令写着“阅读这些文件”,但没有任何 强制措施。agent 会跳过文件,或者在规则加载完成前就开始工作。 4. **信息分散** —— 学到的知识和决策累积在 对话和随机文件中。会话结束后,它们就丢失了。 5. **会话失忆** —— 每个新会话都从零开始。agent 不 知道上次做了什么,或者下一步该做什么。 6. **未经证实的完成** —— agent 说“完成了”,但修复未经测试, 代码未提交,或者配置未经验证。 AI Agent 框架解决了所有这六个问题: - **分层加载** —— 按需加载,其余延迟加载 (1, 2) - **结构性拦截** —— 在上下文加载完成前阻止工具调用 (3) - **漂移检测** —— 捕获过时的引用,自动修复安全项 (2) - **Rule Zero** —— 在编辑时将分散的信息路由到整合的文件中 (4) - **会话连续性** —— 持久的待办列表和会话交接 (5) - **自我验证** —— 在工作得到验证(而不仅仅是口头叙述)前阻止退出 (6) ## 架构概述 五个 hook 点协同工作: ``` graph TD A[SessionStart] -->|generates| B[manifest.json + sentinel.json] B --> C{UserPromptSubmit} C -->|tier1 incomplete| D[Inject 'read files first'] C -->|tier1 complete| E[Track prompt count + warn at thresholds] F{PreToolUse} -->|tool = Read| G[Track file read + allow] F -->|tier1 incomplete| H[BLOCK tool] F -->|tier1 complete| I{Tier 2 keyword?} I -->|yes| J[BLOCK: read tier2 file first] I -->|no| K[ALLOW tool] K --> O{PostToolUse} O --> O1[Rule Zero enforcement] O --> O2[Edit tracking] O --> O3[Save reminders] L{Stop} -->|repos dirty| M[Exit 2 = retry] L -->|all clean| N[Exit 0 = allow] style A fill:#4a90d9,color:#fff style H fill:#d9534f,color:#fff style J fill:#f0ad4e,color:#fff style K fill:#5cb85c,color:#fff style N fill:#5cb85c,color:#fff ``` **Manifest** (`manifest.json`) —— 列出所有 tier1/tier2 文件及其路径、大小 和触发关键字。每次会话都会重新生成。 **Sentinel** (`startup-complete-{session}.json`) —— 追踪 agent 已经 阅读了哪些文件,tier1 是否完成,以及是否运行了交叉检查。基于会话范围 防止并发或恢复的会话之间发生冲突。 ## 快速开始 (Level 1) 最简单且有用的版本 —— manifest + tier1 加载,无拦截。 ### 1. 安装 ``` # 复制 hooks 到你的项目 mkdir -p .agent/hooks cp hooks/on_session_start.py .agent/hooks/ cp hooks/validators.py .agent/hooks/ # 安装 dependency pip install pyyaml ``` ### 2. 创建你的配置 将 `config.example.yaml` 复制到你的项目根目录,并命名为 `startup-config.yaml`: ``` tiers: tier1: - name: project-rules source: docs/rules.md description: "Core project rules and conventions" - name: infra-report type: checks description: "Infrastructure health" checks: - name: git-clean command: "git status --porcelain" validator: empty_output - name: tests-pass command: "npm test --silent 2>&1 | tail -1" validator: "contains:passing" optional: true gates: block_until_tier1: false # Level 1: no blocking ``` ### 3. 添加 hook 添加到你的 `.agent/settings.json`(或从 `examples/level-1-minimal/` 复制): ``` { "hooks": { "SessionStart": [{ "matcher": "", "hooks": [{ "type": "command", "command": "python3 .agent/hooks/on_session_start.py", "timeout": 60000 }] }] } } ``` ### 4. 开启会话 agent 会在会话开始时看到此输出: ``` STARTUP: 2 OK, 0 FAIL Manifest: /tmp/manifest-abc123.json Tier 1: 2 files (45 lines) ACTION REQUIRED: Read manifest, then read all Tier 1 files. - /tmp/tier1-project-rules-abc123.md (30 lines, project-rules) - /tmp/tier1-infra-report-abc123.md (15 lines, infra-report) ``` 添加到你的项目指令中: ``` ## 启动 Read the manifest from SessionStart hook output, then read all Tier 1 files before responding to any user message. ``` ## Level 2:添加拦截 Level 1 依赖于 agent 自愿阅读文件。Level 2 **强制执行** 此操作—— 在所有 tier1 文件加载完成之前,agent 不能使用除 Read 之外的任何工具。 ### 变更内容 1. **PreToolUse 拦截** —— 阻止 Bash、Write、Edit、Agent 等,直到 tier1 完成。只允许使用 Read(以便 agent 可以加载文件)。 2. **UserPromptSubmit 拦截** —— 如果 tier1 未完成,则向 agent 的上下文中 注入“先读文件”的提示。同时追踪 prompt 数量并在达到阈值时发出警告。 ### 安装 ``` cp hooks/gate_check.py .agent/hooks/ cp hooks/on_prompt_submit.py .agent/hooks/ ``` 更新 `startup-config.yaml`: ``` gates: block_until_tier1: true # NOW ENFORCED prompt_health_warnings: [40, 60, 80] ``` 从 `examples/level-2-gated/settings.json` 复制设置,或者将 PreToolUse 和 UserPromptSubmit hooks 添加到你现有的设置中。 ### 工作原理 1. SessionStart 生成 tier1 文件 + 写入带有 `stage: "tier1_pending"` 的 sentinel 2. agent 尝试使用 Bash → PreToolUse 拦截读取 sentinel → tier1 未完成 → **DENIED** 3. agent 阅读 tier1 文件 → gate_check 在 sentinel 中追踪每一次 Read 4. 所有 tier1 文件已读 → sentinel 更新为 `stage: "complete"` 5. agent 再次尝试 Bash → 拦截检查 sentinel → tier1 完成 → **ALLOWED** **Git commit 直通:** `git commit` 和 `git push` 在 `tier1_pending` 状态下也会被 自动允许,因此版本控制永远不会被阻断。 UserPromptSubmit hook 增加了第二层防护:如果 agent 以某种方式忽略了 PreToolUse 的拒绝,prompt 拦截会注入一条消息“先读文件”, agent 在编写回复之前会看到这条消息。 ## Level 3:按需加载 Tier 2 并非每次会话都需要所有规则。Tier 2 文件**仅在 agent 的工具调用中出现相关 关键字时**才会加载。 ### 变更内容 在你的配置中添加带有触发关键字的 tier2 定义: ``` tiers: tier2: - name: api-rules triggers: ["api", "endpoint", "REST", "swagger"] source: docs/api-rules.md - name: deploy-guide triggers: ["deploy", "CI", "pipeline", "release"] source: docs/deploy-guide.md ``` ### 工作原理 1. agent 运行 `Bash("curl api.example.com/...")` 2. PreToolUse 拦截扫描命令文本以查找 tier2 触发器 3. 发现 "api" 匹配 `api-rules` 触发器 → **DENIES** 并附带消息: "Tier 2 files triggered — read before proceeding: api-rules" 4. agent 阅读该文件 → 拦截对其进行追踪 → 允许下一次工具调用 **关键字扫描具有限制**,以防止误报: - 仅扫描特定的 JSON 字段(command、file_path、prompt、description) - 仅扫描每个字段的前 N 个字符(默认:120) - 不区分大小写的匹配 ### 交叉检查漂移检测 在 tier1 加载后,运行一次漂移检查,比较预期与实际状态。 这能在过时的引用引发问题之前捕获它们。 添加一个检查项目不变量的脚本: ``` # 示例:验证 docs 中的 rule 数量与实际数量匹配 expected = manifest["expected_counts"]["rules"] actual = len(list(Path("rules/").glob("*.md"))) if expected != actual: print(f"DRIFT: rules count {expected} in manifest vs {actual} on disk") ``` 交叉检查每次会话运行一次(由 sentinel 中的 `cross_check_done` 追踪)。 ## Level 4:完整架构 ### 停止 Hook 在清理完成前阻止会话退出: ``` cp hooks/on_stop.py .agent/hooks/ ``` ``` stop: require_clean_repos: true require_transcript: false max_retries: 8 shutdown_steps: # configurable checks before exit - name: lint-clean command: "npm run lint 2>&1 | tail -1" validator: "contains:no errors" fail_message: "Linter has errors" ``` 当检查失败时,stop hook 返回退出代码 2(重试)。agent 会看到 失败消息并可以修复问题(例如,提交未提交的文件)。在达到最大 重试次数后,它会正常退出,以避免困住用户。 `shutdown_steps` 是可配置的 —— 使用与启动检查相同的验证器注册表 定义任意数量的自定义检查。每个失败的步骤都会触发 重试,让 agent 在退出前有机会修复问题。 ### 基于输出的验证器 Shell 退出代码会骗人。像 `git status | grep -v node_modules` 这样的管道命令 即使有未提交的文件也会返回 0(因为 grep 执行成功了)。 验证器注册表会解析 stdout 作为替代方案: | Validator | 通过条件 | |-----------|-------------| | `empty_output` | stdout 为空(仅包含空白字符) | | `not_empty` | stdout 有内容 | | `contains:text` | stdout 包含文本(不区分大小写) | | `equals:text` | stdout 完全等于文本(去除首尾空白) | | `regex:pattern` | regex 在 stdout 的任意位置匹配 | 通过扩展 `validators.py` 添加自定义验证器: ``` VALIDATORS["my_check"] = lambda stdout: ( int(stdout.strip()) > 0, stdout.strip() ) ``` ### 会话范围隔离 所有临时文件都包含会话 ID 后缀(`-{SESSION_ID}`)。这可以防止: - 并发会话互相覆盖状态 - 恢复的会话读取上一次运行的陈旧 sentinel - 多个 AI 编码 agent 实例之间的竞态条件 ## 自定义检查清单 在将其适配到你的项目时: - [ ] **Tier 1 文件** —— agent 必须始终遵守哪些规则/上下文?总数控制在约 1500 行以内 - [ ] **Tier 2 文件** —— 哪些内容仅偶尔需要?选择足够具体的触发关键字以避免误报 - [ ] **基础设施检查** —— 在启动时应验证什么?(DB 健康、git clean、测试通过、服务运行) - [ ] **验证器** —— 是否有任何检查需要自定义 stdout 解析? - [ ] **Prompt 阈值** —— 在什么 prompt 数量下,agent 应该警告上下文健康状况? - [ ] **Stop 检查** —— 会话退出前必须做什么?(提交、保存记录、同步文件) - [ ] **文件路径** —— 更新 `startup-config.yaml` 源以指向你的实际文件 ## 经验教训 这些见解是在数十次会话中构建和迭代该系统时得出的: 1. **记录不等于执行。** 在 CLAUDE.md 中写下“agent 在启动时必须阅读 X”并不能保证它会执行。结构性强制执行(拦截工具调用的 hooks)是唯一可靠的机制。如果没有强制执行,它就是可选的。 2. **退出代码会骗人。** 带有管道、`||`、子shell 和错误掩码的 Shell 命令在不应返回 0 的时候返回了 0。使用验证器解析 stdout,而不是信任 `$?`。 3. **一切皆需会话范围。** 没有会话 ID 的临时文件在会话恢复或并发运行时会导致神秘的失败。始终添加会话 ID 作为后缀。 4. **明智地分层。** tier1 和 tier2 的划分应基于*使用频率*,而不是*重要性*。仅在处理 API 工作时才起作用的关键 API 规则属于带有 "api" 触发器的 tier2 —— 而不是放在 tier1 中浪费每次会话的 token。 5. **限制你的循环。** 交叉检查漂移检测必须是有边界的(最多 2 遍,然后继续)。无限制的自我修复循环在修复产生新漂移时可能会陷入死循环。修复安全的部分,记录其余部分,继续前进。 6. **要拦截,不要唠叨。** 写着“请先阅读 X”的书面指令只是一种建议。返回 `permissionDecision: "deny"` 的 PreToolUse hook 才是拦截。拦截有效。建议无效。 7. **追踪读取,而不是意图。** sentinel 追踪 agent *实际阅读了*哪些文件(通过 Read 工具路径匹配),而不是*被告知*要阅读哪些文件。这缩小了“我加载了规则”与“规则在我的上下文中”之间的差距。 8. **推理越多 = 忠实度越低。** 给予 LLM 更多的思考时间会使摘要对信息源的忠实度*降低* (r = -0.685)。将推理用于验证,永远不要用于生成。参见 `docs/rules/anti-hallucination-rules.md`。 ## 反幻觉规则 `docs/rules/` 目录包含一个经过研究支持的、由 14 项认知 规则组成的框架,用于减少 LLM 生成摘要中的幻觉。这些规则是 通用的 —— 它们适用于任何摘要任务,而不仅仅是某个特定领域。 这些规则被组织成 5 个阶段(READ → WRITE → VERIFY PASS 1 → VERIFY PASS 2 → SIGN-OFF),因为 LLM 会跳过平面 列表中间的规则(U 型注意力偏差)。每条规则都引用了经过同行评审的研究。 要使用它们,请将 `docs/rules/anti-hallucination-rules.md` 作为 Tier 1 文件包含在你的 配置中: ``` tiers: tier1: - name: ah-rules source: docs/rules/anti-hallucination-rules.md description: "Anti-hallucination rules for faithful summaries" ``` 或者在生成摘要时在你的 LLM prompt 中直接引用它们。 ## 幻灯片 下载配套的可视化幻灯片,一目了然地了解架构: - **[PDF](slides/Structural_AI_Agent_Enforcement.pdf)** —— 10 页幻灯片,涵盖问题、5-hook 引擎、分层策略和全部 4 个等级 将这些幻灯片与课程结合使用,或作为团队的独立概述。 ## 入门指南 ### 快速设置(2 分钟) 克隆代码库并运行交互式向导: ``` git clone https://github.com/dexmaddy/ai-agent-harness.git cd ai-agent-harness python3 setup.py ``` 向导将引导你完成: 1. **平台** —— Claude Code、Cursor、Windsurf、Aider 或自定义 agent 2. **数据存储** —— YAML/JSON 文件、SQLite 或 PostgreSQL 3. **等级** —— 你想要多少强制执行力 (1-4) 4. **项目详情** —— 反幻觉规则、持久化待办列表 它会生成所有配置文件,复制正确的 hook 脚本,创建 示例规则,并将所有内容为你选择的平台连接好。 ### 学习概念 **参加[课程](docs/course/README.md)** —— 8 个模块,约 2.5 小时, 逐步为你的项目构建一个完整的工作系统。 **参考文档:** 1. **[引导指南](docs/reference/bootstrapping-guide.md)** —— 在 15 分钟内创建你的前 5 条规则, 包含用于 Web 应用、数据管道和基础设施的入门套件 2. **[规则演进模板](docs/reference/rule-evolution-template.md)** —— 将失败转化为结构性强制的模式: 失败 → 学习 → 规则 → 审计 → hook 3. **[冒烟测试](tests/smoke_test.py)** —— 验证你的设置是否能够端到端运行: `python3/smoke_test.py --verbose` ## 文件结构 ``` ai-agent-harness/ ├── setup.py # Interactive setup wizard ├── README.md # This guide ├── mkdocs.yml # Website config (MkDocs Material) ├── config.example.yaml # Template config ├── settings.example.json # Hook configuration template ├── hooks/ # Hook scripts (copy to your project) │ ├── on_session_start.py # Method A: YAML → manifest │ ├── on_session_start_db.py # Method B: SQLite → manifest │ ├── gate_check.py # PreToolUse gate │ ├── on_prompt_submit.py # UserPromptSubmit gate │ ├── on_stop.py # Stop hook with retries │ ├── on_edit.py # PostToolUse actions │ ├── cross_check.py # Drift detection │ ├── audit.py # Standalone audit runner │ └── validators.py # Output-based validators ├── checks/ # Sample audit check library │ └── audit-checks.yaml # 10 generic checks ├── docs/ # Website content │ ├── index.md # Home page │ ├── course/ # 8-module course │ │ ├── README.md # Course overview │ │ └── module-1 through module-8 # Course modules │ ├── reference/ # Guides, templates, patterns │ │ ├── setup-wizard.md # Wizard docs │ │ ├── bootstrapping-guide.md # First 5 rules │ │ ├── rule-evolution-template.md # Failure → rule → hook │ │ ├── rule-zero.md # Every edit triggers categorization │ │ ├── self-healing-loop.md # Bidirectional rule-audit feedback │ │ ├── self-verification.md # 4-point completion check │ │ ├── audit-runner.md # On-demand audit checks │ │ └── session-continuity.md # Persistent backlog │ └── rules/ # Reusable rule frameworks │ └── anti-hallucination-rules.md # 14 research-backed rules ├── slides/ # Visual companion │ └── Structural_AI_Agent_Enforcement.pdf ├── tests/ │ └── smoke_test.py # 18-check verification ├── examples/ │ ├── level-1-minimal/settings.json # Just SessionStart │ ├── level-2-gated/settings.json # + PreToolUse + UserPromptSubmit │ └── level-4-full/settings.json # All 4 hooks └── LICENSE # MIT ``` ## 数据源:优先使用文件,进阶时使用数据库 本项目默认使用 **YAML 配置 + markdown 规则文件**。无需数据库 即可开始使用。这是刻意为之 —— 对于大多数用户来说,平面文件是 正确的选择。 **当文件适用时(约 50 条规则以内):** - 可使用任何文本编辑器进行编辑,无需 CLI - 免费获得完整的 git 历史 - 易于阅读、审查和新团队成员入职 - 除了 PyYAML 之外没有其他依赖项 **何时进阶到数据库(约 50 条规则以上):** | 痛点信号 | 发生了什么 | 数据库解决方案 | |-------------|-----------------|-------------| | "哪些规则引用了事实 X?" | 交叉引用需要扫描每个文件 | 一次 JOIN 查询 | | 漂移检测很脆弱 | `find + wc -l` 管道在边缘情况会失效 | `SELECT COUNT(*)` 是原子操作 | | 并发的 agent 会话破坏状态 | 两个 agent 同时编辑同一个 YAML | SQLite WAL 模式处理并发写入 | | 规则搜索缓慢 | Grep 20 多个文件才能找到一个类别 | 按 category/trigger 进行索引查询 | | 无法追踪规则何时添加/更改 | Git log 有效但粒度太粗 | `created_at`、`updated_at` 列 | **推荐的进阶路径:** 1. 从 YAML 开始(本项目的默认设置) 2. 注意上述痛点信号 3. 当它们出现时,迁移到 SQLite(单文件,无需服务器,Python 标准库) 4. 构建一个轻量级的 CLI 包装器,这样你就不需要直接编写原始 SQL 推荐使用 SQLite 而不是 Postgres/MySQL,因为它是嵌入式的(无需服务器), 数据库是一个可移植的单文件(与 YAML 相同),并且它随 Python 一起提供。 LangChain 和 CrewAI 都使用 SQLite 来实现持久的 agent 状态。 ## 平台兼容性 **概念**(分层加载、拦截、漂移检测、反幻觉 规则)适用于任何 AI agent 系统。**参考实现**使用 Claude Code 的 hooks API,但这些模式可以适配任何具有生命周期事件的平台。 | 平台 | 如何适配 | |----------|-------------| | **Claude Code** | 直接使用 —— hooks 直接映射到 SessionStart、PreToolUse 等。 | | **Cursor** | 使用 `.cursor/rules/` 作为 tier1 规则,`@rules` 作为 tier2。通过自定义命令进行拦截。 | | **Windsurf** | 使用 `.windsurfrules` 作为规则,使用 Cascade memories 追踪 tier 状态。 | | **Aider** | 使用 `.aider.conf.yml` 约定 + `--read` 标志在启动时加载 tier1。 | | **Continue.dev** | 使用 `.continuerc.json` 上下文提供程序进行分层规则加载。 | | **自定义 agent** | 在你的 agent 循环中将 hook 模式实现为中间件 —— 在工具执行前检查状态。 | | **LangChain/CrewAI** | 添加一个加载规则的启动节点/任务,以及一个在工具使用前检查 sentinel 的 gate 回调。 | **核心模式与框架无关:** 1. **会话工作前:** 加载必要的上下文 (tier1) 2. **每次工具调用前:** 验证上下文已加载,触发按需加载 (tier2) 3. **每次修改后:** 同步状态,检查是否存在漂移 4. **会话结束前:** 验证清理工作 ## 两种部署方式 | | 方式 A:YAML 配置 | 方式 B:SQLite 数据库 | |---|---|---| | **脚本** | `on_session_start.py` | `on_session_start_db.py` | | **规则存储于** | 磁盘上的 Markdown 文件 | SQLite 中的 `rules` 表 | | **Backlog** | `backlog.json` | `backlog` 表 | | **会话交接** | JSON 文件 | `session_summaries` 表 | | **配置** | `startup-config.yaml` | `config` 表 | | **依赖项** | PyYAML | 无(sqlite3 是 Python 标准库) | | **最适合** | 约 50 条规则以内,单用户 | 50 条以上规则,交叉引用,并发会话 | | **设置** | 复制配置,编写 markdown 文件 | `python3 hooks/on_session_start_db.py --init-db project.db` | ### 数据库模式特性 设置 `AGENT_DB_PATH` 后,方式 B(SQLite/PostgreSQL)可启用额外功能: - **编辑日志** —— 每次 Write/Edit 都记录在 `rule_log` 表中 (`on_edit.py`) - **会话摘要强制执行** —— `on_stop.py` 要求在退出前有 `session_summaries` 行 - **陈旧事实检测** —— 当 `system_facts` 或 `fact_references` 陈旧时,`gate_check.py` 会发出警告 这些使用了三个额外的表:`rule_log`、`system_facts`、`fact_references`。 从方式 A 开始。当你遇到数据源指南中描述的 [痛点信号](docs/session-continuity.md#why-sqlite-over-json)时, 进阶到方式 B。 ## 环境要求 - Python 3.10+ - 方式 A:PyYAML (`pip install pyyaml`) - 方式 B:无额外依赖(sqlite3 在 Python 标准库中) - 支持 hook/中间件的 AI 编码 agent(Claude Code、Cursor、Windsurf、Aider 或自定义 agent) ## 许可证 MIT —— 随意使用、改编并分享。
标签:AI代理, Homebrew安装, 人工智能, 可靠性工程, 工作流自动化, 开发框架, 用户模式Hook绕过, 逆向工具, 防幻觉