<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/loraSys/scripts/pretty-feed-v3.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:h="http://www.w3.org/TR/html4/"><channel><title>Lora</title><description>AI Agent developer and full-stack engineer. A personal site for projects, writing, current work, and the stories, sounds, and ideas I keep close.</description><link>https://lora-sys.github.io/loraSys</link><item><title>AI Engineering Harness: 从 Vibe Coding 到工程化</title><link>https://lora-sys.github.io/loraSys/blog/ai-engineering-harness</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/ai-engineering-harness</guid><description>Vibe 之后，正式接管。一个由 18 类 AI Agent 组成的软件工程组织，负责把失控的 AI 代码变成可验证、可审查、可追溯的工程交付。包含完整闭环、证据闸门、对抗式审查，让你的 AI 写的代码真正可以上生产。</description><pubDate>Sun, 02 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;背景：Vibe 之后，正式接管&lt;/h2&gt;
&lt;p&gt;在 AI 编程助手的世界里，有一个新痛点：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI 写了 2000 行代码，能跑，但没人敢改。没有测试，没有 CI，没有文档。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;这就是 &lt;strong&gt;Vibe 之后的问题&lt;/strong&gt;——你用 AI 快速产出了代码，但得到的不是一个工程交付，而是一个&quot;技术债务黑洞&quot;。&lt;/p&gt;
&lt;h3&gt;实际场景&lt;/h3&gt;
&lt;p&gt;想象一下这样的对话：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;你: &quot;帮我做一个用户认证系统&quot;
Claude: (30 秒后) &quot;完成了！放在 src/auth/&quot;
你: (打开代码) &quot;这...能跑，但为什么没有测试？为什么没有文档？
   为什么 Session 登录用的是 localStorage 而不是 HttpOnly Cookie？&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AI 能快速产出&lt;strong&gt;看起来能跑的代码&lt;/strong&gt;，但它不会：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;写测试&lt;/li&gt;
&lt;li&gt;配置 CI&lt;/li&gt;
&lt;li&gt;写文档&lt;/li&gt;
&lt;li&gt;考虑安全性&lt;/li&gt;
&lt;li&gt;预留扩展点&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;传统方案&lt;/strong&gt;：你花几天时间手动补全这些。每次有新需求，都要重新手动审查。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Engineering Harness&lt;/strong&gt;：让 AI Agent 自己完成从 PRD 到 Merge 的完整工程流程。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;问题：AI 工程的四大痛点&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;痛点&lt;/th&gt;
&lt;th&gt;影响&lt;/th&gt;
&lt;th&gt;数据&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🚧 &lt;strong&gt;没有测试&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;改了怕炸&lt;/td&gt;
&lt;td&gt;85/108 测试通过，但还是挂了&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔴 &lt;strong&gt;CI 全绿，但假的&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;误导性强&lt;/td&gt;
&lt;td&gt;生产环境发现严重 bug&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📝 &lt;strong&gt;没有文档&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;知识碎片化&lt;/td&gt;
&lt;td&gt;下次接手的开发者要重读所有代码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔐 &lt;strong&gt;没有审查&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;安全隐患&lt;/td&gt;
&lt;td&gt;AI 写入了硬编码密钥&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;传统方案的代价&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;手动补全一个 Vibe Coding 项目&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Day 1: 补测试 → 写 50 个测试用例
Day 2: 配置 CI → GitHub Actions + 3 个 workflow
Day 3: 写文档 → API 文档 + 部署指南
Day 4: 安全审查 → 手动找硬编码密钥
Day 5: 代码审查 → 逐行检查逻辑
→ 5 天，$2000+ 工程师成本
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;AI Engineering Harness&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;输入: PRD.md
输出: 完整工程交付（测试 + CI + 文档 + 审查 + 证据包）
→ 30 分钟，$0.50 token 成本
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;解决方案：AI Engineering Harness&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;把失控的 Vibe Coding 作品，变成可验证、可维护的工程交付。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;核心理念&lt;/h3&gt;
&lt;p&gt;AI Engineering Harness 不是一条 Prompt，而是一套&lt;strong&gt;软件工程组织操作系统&lt;/strong&gt;。你给它一个失控的仓库，它代你组建一个由 18 类 Agent 组成的工程团队，走完整闭环：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Idea → PRD → Issue → Agent 认领 → Worktree → 实施计划
     → 实现 → 自测 → Draft PR → CI → 对抗式审查 → 修 → 再审
     → 证据闸门 → 人工审批 → 合并 → 阶段总结 → 记忆沉淀 → 下一轮
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;关键承诺&lt;/strong&gt;：代码只有在 &lt;strong&gt;CI Pass + 至少 2 名冷启动审查员 Approved + 证据完整&lt;/strong&gt; 时才进入 &lt;code&gt;main&lt;/code&gt;。没有&quot;看起来跑通了&quot;这种状态——只有**&quot;可验证地跑通了&quot;**。&lt;/p&gt;
&lt;h3&gt;四个关键特性&lt;/h3&gt;
&lt;h4&gt;1️⃣ 证据驱动的工程纪律&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;传统开发&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PR 合进去 → Done ✅
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Harness&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PR → CI 绿 → 2+ 审查员 Approved → 证据齐全 → Done ✅
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;2️⃣ 18 类专业化 Agent&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Coordinator
├── Frontend Agent
├── Backend Agent
├── Database Agent
├── Bug Hunter
├── Behavior Reviewer
├── Architecture Reviewer
├── Security Reviewer
├── UI Reviewer
├── QA Agent
├── Evidence Aggregator
└── ... (共 18 类)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;3️⃣ 工作流隔离（Worktree）&lt;/h4&gt;
&lt;p&gt;每个 Issue 运行在独立的 Git Worktree 中：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;主仓库: main
  ├── worktree/feature-17-auth → Issue #17 (Backend Agent)
  ├── worktree/feature-18-ui   → Issue #18 (Frontend Agent)
  └── worktree/feature-19-db   → Issue #19 (Database Agent)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;好处&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 并行开发，互不干扰&lt;/li&gt;
&lt;li&gt;✅ 冲突自动检测，Conflict Resolver 处理&lt;/li&gt;
&lt;li&gt;✅ 每个分支独立 CI 和审查&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;4️⃣ 上下文分层加载（L0-L3）&lt;/h4&gt;
&lt;p&gt;不让 Agent 读整个 &lt;code&gt;docs/&lt;/code&gt; 目录，而是分层加载：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;L0: AGENTS.md + ENGINEERING.md 摘要（始终加载）
L1: 当前 Issue + 模块架构 + ADR（任务级）
L2: 相邻模块 + 最近阶段总结（按需）
L3: PDF/图片/长报告（显式需要时才加载）
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;核心架构：18 类 Agent 的协作&lt;/h2&gt;
&lt;h3&gt;架构总览&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;graph TD
    User[👤 User] --&gt;|PRD| Coordinator[🧠 Coordinator]
    Coordinator --&gt;|分派| Frontend[🎨 Frontend Agent]
    Coordinator --&gt;|分派| Backend[⚙️ Backend Agent]
    Coordinator --&gt;|分派| Database[🗄️ Database Agent]

    Frontend --&gt;|代码| Worktree1[Worktree #17]
    Backend --&gt;|代码| Worktree2[Worktree #18]
    Database --&gt;|代码| Worktree3[Worktree #19]

    Worktree1 --&gt;|PR| CI[🔴 CI Gate]
    Worktree2 --&gt;|PR| CI
    Worktree3 --&gt;|PR| CI

    CI --&gt;|通过| Review[🔍 Cold-Start Review]
    Review --&gt;|Bug Hunter| Evidence[✅ Evidence Gate]
    Review --&gt;|Behavior Reviewer| Evidence
    Review --&gt;|Arch Reviewer| Evidence

    Evidence --&gt;|全绿| Merge[🔀 Merge to main]
    Merge --&gt;|阶段总结| Memory[💾 Memory Evolution]
    Memory --&gt;|沉淀| Next[🔄 Next Round]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Agent 角色详解&lt;/h3&gt;
&lt;h4&gt;🧠 Coordinator（协调者）&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;职责&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;读 PRD，拆解成 Issue&lt;/li&gt;
&lt;li&gt;分派 Agent 到 Worktree&lt;/li&gt;
&lt;li&gt;维护 PROJECT_STATUS.md&lt;/li&gt;
&lt;li&gt;人工审批闸门（鉴权/DB schema/生产密钥）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;不做什么&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ 不写业务代码&lt;/li&gt;
&lt;li&gt;❌ 不做技术决策&lt;/li&gt;
&lt;li&gt;❌ 不合并代码（除非证据闸门全绿）&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;🎨 Frontend Agent（前端工程师）&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;职责&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实现 UI 组件&lt;/li&gt;
&lt;li&gt;响应式设计&lt;/li&gt;
&lt;li&gt;截图 + Playwright trace&lt;/li&gt;
&lt;li&gt;Accessibility 扫描&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docs/evidence/17/
├── change-summary.md
├── verification.md
├── screenshots/
│   ├── desktop.png
│   ├── tablet.png
│   ├── mobile.png
│   ├── empty-state.png
│   ├── error-state.png
│   └── loading-state.png
├── playwright-trace.zip
└── review-frontend.md
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;⚙️ Backend Agent（后端工程师）&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;职责&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API 实现&lt;/li&gt;
&lt;li&gt;业务逻辑&lt;/li&gt;
&lt;li&gt;异常处理&lt;/li&gt;
&lt;li&gt;鉴权逻辑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docs/evidence/17/
├── api-trace.json
├── error-coverage.md
├── auth-negative-cases.md
└── performance-baseline.json
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;🐛 Bug Hunter（缺陷猎人）&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;职责&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;冷启动审查（不读实现者的聊天历史）&lt;/li&gt;
&lt;li&gt;只读 Issue + Plan + PR Diff + Evidence&lt;/li&gt;
&lt;li&gt;找边界条件、竞态条件、类型错误&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;审查清单&lt;/strong&gt;：&lt;/p&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 空值处理&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 类型安全&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 并发安全&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 资源泄漏&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 错误处理&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;👁️ Behavior Reviewer（行为审查员）&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;职责&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;功能是否符合 AC（Acceptance Criteria）&lt;/li&gt;
&lt;li&gt;用户体验是否合理&lt;/li&gt;
&lt;li&gt;边缘场景是否覆盖&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;闭环流程：从 Issue 到 Merge&lt;/h2&gt;
&lt;h3&gt;完整流程图&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://lora-sys.github.io/loraSys/images/harness/lora-v1-section-workflow.webp&quot; alt=&quot;AI Engineering Harness 从规划到合并的工作流&quot;&gt;&lt;/p&gt;
&lt;h3&gt;9 个 Phase 详解&lt;/h3&gt;
&lt;h4&gt;Phase 0: PRD → Coordinator&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;：&lt;code&gt;PRD.md&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 做&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;读取 PRD，提取功能点&lt;/li&gt;
&lt;li&gt;生成 &lt;code&gt;docs/product/&lt;/code&gt;、&lt;code&gt;docs/architecture/&lt;/code&gt;、&lt;code&gt;docs/design/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;创建 &lt;code&gt;memory/&lt;/code&gt; 目录&lt;/li&gt;
&lt;li&gt;生成 &lt;code&gt;PROJECT_STATUS.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;创建 &lt;code&gt;AGENTS.md&lt;/code&gt;、&lt;code&gt;CLAUDE.md&lt;/code&gt;、&lt;code&gt;ENGINEERING.md&lt;/code&gt; 等&lt;/li&gt;
&lt;li&gt;生成首批 5-10 个 Issue&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docs/
├── product/
│   ├── vision.md
│   └── roadmap.md
├── architecture/
│   └── system-design.md
├── design/
│   └── ui-guidelines.md
├── decisions/
│   └── ADR-001.md
memory/
├── project-memory.md
└── decisions.md
PROJECT_STATUS.md
AGENTS.md
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 1: Planning → Coordinator&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;前提&lt;/strong&gt;：Issue 字段齐全&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;必须字段&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Context / Goal / Scope / Non-Goal / Related Docs / Implementation Plan /
Acceptance Criteria / Evidence Requirements / Reviewer Requirements /
Owner / Estimate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 检查&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ 缺字段 → 停在 Planning，不启动&lt;/li&gt;
&lt;li&gt;✅ 字段齐全 → 进入 Worktree Phase&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 2: Worktree → Owner Agent&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;操作&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 为 Issue #17 创建独立 worktree
git worktree add ../myproject-worktree-17 -b feature/17-user-auth main

cd ../myproject-worktree-17

# Owner Agent 在这里工作
# Frontend Agent 实现 UI
# Backend Agent 实现 API
# Database Agent 实现 schema
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;每个 Worktree&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 独立分支&lt;/li&gt;
&lt;li&gt;✅ 独立 CI&lt;/li&gt;
&lt;li&gt;✅ 独立审查&lt;/li&gt;
&lt;li&gt;✅ 独立 Evidence 目录&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 3: Implementation → Owner Agent&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Owner Agent 职责&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;读 Plan&lt;/strong&gt;：理解要做什么&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实现代码&lt;/strong&gt;：按 Implementation Plan 写代码&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自测&lt;/strong&gt;：跑测试，确保通过&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;写 Evidence&lt;/strong&gt;：开始填充 &lt;code&gt;docs/evidence/&amp;#x3C;id&gt;/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Owner Agent 不做什么&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ 不合并代码&lt;/li&gt;
&lt;li&gt;❌ 不做架构决策&lt;/li&gt;
&lt;li&gt;❌ 不绕过审查&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 4: CI Gate → Coordinator&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;触发&lt;/strong&gt;：Owner 推第一个 commit&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 监控&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;# .github/workflows/test.yml
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm test
      - run: npm run lint
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;红灯处理&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔴 CI 失败 → 停在 Phase 4&lt;/li&gt;
&lt;li&gt;🔧 派 Recovery Agent 修复&lt;/li&gt;
&lt;li&gt;🟢 CI 通过 → 进入 Phase 5&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;红线&lt;/strong&gt;：同一类失败 ≥ 2 次 → 创建 &lt;code&gt;ci&lt;/code&gt; tagged Issue + &lt;code&gt;memory/lessons.md&lt;/code&gt; 一条&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 5: Review → Bug Hunter + Behavior Reviewer&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Bug Hunter（冷启动）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只读 Issue + Plan + PR Diff + Evidence&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不读实现者的聊天或解释&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;输出：&lt;code&gt;docs/evidence/&amp;#x3C;id&gt;/review-bug-hunter.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Behavior Reviewer（冷启动）&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只读 Issue + Plan + PR Diff + Evidence&lt;/li&gt;
&lt;li&gt;检查 AC 是否满足&lt;/li&gt;
&lt;li&gt;输出：&lt;code&gt;docs/evidence/&amp;#x3C;id&gt;/review-behavior.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;审查员规则&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 必须冷启动（零上下文）&lt;/li&gt;
&lt;li&gt;✅ 必须 Approved / Changes Requested&lt;/li&gt;
&lt;li&gt;❌ 不能&quot;看起来可以&quot;&lt;/li&gt;
&lt;li&gt;❌ 不能绕过任何 AC&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 6: Evidence → Evidence Aggregator&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Evidence Aggregator 检查清单&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;# docs/evidence/17/verification.md

## Acceptance Criteria

| AC                       | 状态       | 证据                      |
| ------------------------ | ---------- | ------------------------- |
| AC-1: 用户可以用邮箱注册 | ✅ PASS    | screenshot:register.png   |
| AC-2: 登录态持久化       | ✅ PASS    | screenshot:persistent.png |
| AC-3: 忘记密码功能       | ❌ FAIL    | 未实现                    |
| AC-4: 邮箱验证           | ⏸️ PENDING | -                         |

## Review Checklist

- [x] review-bug-hunter.md ✅
- [x] review-behavior.md ✅
- [x] fix-tasks.md ✅ (0 unresolved)
- [x] CI 绿 ✅
- [ ] AC-3 必须完成 ❌

## Verdict

❌ **NOT READY** — AC-3 未完成
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 7: Merge → Coordinator&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;合并条件&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ CI 绿&lt;/li&gt;
&lt;li&gt;✅ ≥ 2 名审查员 Approved&lt;/li&gt;
&lt;li&gt;✅ Evidence 齐全（&lt;code&gt;docs/evidence/&amp;#x3C;id&gt;/&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;✅ Aggregator ✅&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 检查&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 自动检查
- [ ] docs/evidence/17/change-summary.md
- [ ] docs/evidence/17/verification.md
- [ ] docs/evidence/17/screenshots/ (6 张)
- [ ] docs/evidence/17/review-bug-hunter.md ✅
- [ ] docs/evidence/17/review-behavior.md ✅
- [ ] docs/evidence/17/fix-tasks.md ✅
- [ ] CI 绿
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;全绿 → 自动合并到 main&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4&gt;Phase 8: Memory → Coordinator&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Phase Summary&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;workflows/06-phase-summary.md
→ 沉淀到 memory/phase-17-summary.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Memory Evolution&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;workflows/08-memory-evolution.md
→ 更新 memory/project-memory.md
→ 更新 memory/decisions.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;下一轮 Agent 读取这些再开工&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;关键技术：证据闸门&lt;/h2&gt;
&lt;h3&gt;什么是证据闸门？&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;传统开发&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PR 合进去 → Done ✅
&quot;我觉得可以&quot; → 合并 ✅
&quot;本地跑通了&quot; → 合并 ✅
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;证据闸门&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PR → CI 绿 + 2+ 审查员 Approved + 证据齐全 → Done ✅
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;证据目录结构&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;docs/evidence/17/
├── change-summary.md          # 改了什么
├── verification.md            # AC 的 PASS/FAIL
├── screenshots/               # 6 态截图
│   ├── desktop.png
│   ├── tablet.png
│   ├── mobile.png
│   ├── empty-state.png
│   ├── error-state.png
│   └── loading-state.png
├── playwright-trace.zip       # 交互 trace
├── console-clean.md           # Console 无错误
├── a11y-report.md             # Accessibility 扫描
├── api-trace.json             # API 调用记录
├── error-coverage.md          # 异常覆盖
├── auth-negative-cases.md     # 鉴权负面用例
├── performance-baseline.json  # 性能基线
├── db-migration.sql           # 数据库迁移
├── db-rollback.sql            # 回滚脚本
├── db-stats.json              # Pre/Post stats
├── db-sample-rows.json        # 样本数据
├── review-bug-hunter.md       # Bug Hunter 审查
├── review-behavior.md         # Behavior Reviewer 审查
└── fix-tasks.md               # Aggregator ✅
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;证据检查清单&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;前端&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 6 态截图（桌面/平板/手机/空/错/加载）&lt;/li&gt;
&lt;li&gt;✅ Playwright trace&lt;/li&gt;
&lt;li&gt;✅ Console 干净&lt;/li&gt;
&lt;li&gt;✅ a11y 扫描通过&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;后端&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ API trace&lt;/li&gt;
&lt;li&gt;✅ 异常覆盖&lt;/li&gt;
&lt;li&gt;✅ 鉴权负面用例&lt;/li&gt;
&lt;li&gt;✅ 性能基线&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;数据库&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Migration + Rollback&lt;/li&gt;
&lt;li&gt;✅ Pre/Post stats&lt;/li&gt;
&lt;li&gt;✅ Sample rows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;审查&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ review-bug-hunter.md&lt;/li&gt;
&lt;li&gt;✅ review-behavior.md&lt;/li&gt;
&lt;li&gt;✅ fix-tasks.md Aggregator ✅&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;CI&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ 绿&lt;/li&gt;
&lt;li&gt;❌ 无 Critical/High 阻断&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;实战：接管一个失控的仓库&lt;/h2&gt;
&lt;h3&gt;场景&lt;/h3&gt;
&lt;p&gt;你刚用 AI 写了一个项目，能跑，但：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;❌ 没有测试&lt;/li&gt;
&lt;li&gt;❌ 没有 CI&lt;/li&gt;
&lt;li&gt;❌ 没有文档&lt;/li&gt;
&lt;li&gt;❌ 有硬编码密钥&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;传统方案&lt;/strong&gt;：花 5 天手动补全。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Engineering Harness&lt;/strong&gt;：30 分钟接管。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 1: 安装（5 分钟）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 一行安装
npx -y skills add lora-sys/ai-engineering-harness -g --all --full-depth
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;装了什么&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;code&gt;ai-engineering-harness&lt;/code&gt; skill&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;build-agent-app&lt;/code&gt; skill&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;frontend-creative&lt;/code&gt; skill&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;dashboard&lt;/code&gt; skill&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;支持 40 个 CLI Agent&lt;/strong&gt;：Claude Code、Codex、Grok、Cursor、Gemini、Qwen 等。&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 2: Quick Scan（2 分钟）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 干跑：只打印草稿
bash skills/dashboard/scripts/scan-to-issues.sh

# 真的建 Issue
bash skills/dashboard/scripts/scan-to-issues.sh --create
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Quick Scan 检测&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;✅ 硬编码密钥 (HIGH) → Issue #1
✅ 缺失错误处理 (MEDIUM) → Issue #2
✅ 重复逻辑 (MEDIUM) → Issue #3
✅ 风格漂移 (LOW) → Issue #4
✅ 缺少测试 (MEDIUM) → Issue #5
⚠️ TODO 无 Issue 链接 (LOW) → Issue #6
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;Step 3: 接管（10 分钟）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 在你的仓库里说
Use $ai-engineering-harness to take over this repo. Inventory the gap
between current state and harness layout; file Issues for the missing
pieces; do not edit code yet.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 做&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;盘点差距（&quot;现状 → 期望&quot;的 Gap）&lt;/li&gt;
&lt;li&gt;生成 Issue（按类别归列）&lt;/li&gt;
&lt;li&gt;不先动业务代码&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;输出&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;📊 盘点完成
- ✅ 发现 23 个问题
- ✅ 创建 15 个 Issue
- ✅ 优先级排序

前 3 件事：
1. 硬编码密钥 → 移到环境变量
2. 缺少测试 → Quick Scan 检测到 5 个模块无测试
3. 没有 CI → 配置 GitHub Actions
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;Step 4: 推一个 Issue 到 Done（10 分钟）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 推 Issue #1 到 Done
Use $ai-engineering-harness to take Issue #1 from Planning to Done.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;完整闭环&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;1. 写 Plan → Issue #1 的 Implementation Plan
2. Worktree → git worktree add ../proj-issue-1
3. 分派 → Backend Agent 修密钥
4. 实现 → 移到环境变量
5. 自测 → 跑测试，通过
6. Draft PR → 自动创建 PR
7. CI → 通过 ✅
8. Bug Hunter → 冷启动审查，Approved
9. Behavior Reviewer → 冷启动审查，Approved
10. Evidence → 证据齐全 ✅
11. Merge → Coordinator 自动合并
12. Memory → 阶段总结 + 记忆沉淀
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;Step 5: 验证（3 分钟）&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 检查证据
ls docs/evidence/1/
# ✅ change-summary.md
# ✅ verification.md
# ✅ screenshots/ (6 张)
# ✅ review-bug-hunter.md
# ✅ review-behavior.md
# ✅ fix-tasks.md

# 检查 CI
gh pr view 1 --json state,statusCheckRollup
# ✅ state: MERGED
# ✅ statusCheckRollup: SUCCESS
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;安装与配置&lt;/h2&gt;
&lt;h3&gt;一行安装&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx -y skills add lora-sys/ai-engineering-harness -g --all --full-depth
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-g&lt;/code&gt;：全局安装（写入用户级 skill 目录）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--all&lt;/code&gt;：安装到所有受支持的 CLI Agent&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--full-depth&lt;/code&gt;：发现并安装所有 skill&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;精确安装&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 只装这一个 skill
npx -y skills add lora-sys/ai-engineering-harness -g -s ai-engineering-harness

# 只装到指定 agent
npx -y skills add lora-sys/ai-engineering-harness -g -a claude-code codex grok
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;兼容 40 个 CLI Agent&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;安装路径&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codex&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.codex/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.cursor/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.qwen/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grok&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.grok/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenCode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.config/opencode/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;共 40 个&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;进阶用法&lt;/h2&gt;
&lt;h3&gt;跨 CLI 接力&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Claude 工作到一半，切到 Grok
Use $ai-engineering-harness. I&apos;m continuing from another agent.
Read memory/project-memory.md and sessions/&amp;#x3C;last-id&gt;/summary.md, then continue.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Harness 的状态全部落盘&lt;/strong&gt;，聊天历史不会丢。&lt;/p&gt;
&lt;h3&gt;并行开发&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 分派 3 个 Issue 并行开发
Use $ai-engineering-harness to spawn parallel Owners
for Issue #20 (frontend), #21 (backend), #22 (database).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 做&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;拉 3 个 Worktree&lt;/li&gt;
&lt;li&gt;分派对应 Agent&lt;/li&gt;
&lt;li&gt;并行推到 PR&lt;/li&gt;
&lt;li&gt;冲突时 Conflict Resolver 处理&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;CI 自愈&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# CI 红了，让它自愈
CI is red on PR #23. Use $ai-engineering-harness to recover.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;流程&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;60 秒分类（flaky / 真缺陷 / lint / 集成 / infra）&lt;/li&gt;
&lt;li&gt;派 Owner Agent 修复&lt;/li&gt;
&lt;li&gt;重新跑 CI&lt;/li&gt;
&lt;li&gt;重新走 Reviewer&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;30 秒拉起新项目&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 创建项目
mkdir my-saas &amp;#x26;&amp;#x26; cd my-saas
git init
echo &quot;# My SaaS&quot; &gt; README.md
git add . &amp;#x26;&amp;#x26; git commit -m &quot;feat: init&quot;

# 进入任意 CLI
# Use $ai-engineering-harness to bootstrap this repo from PRD.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Coordinator 生成&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目录骨架&lt;/li&gt;
&lt;li&gt;首轮 Issue&lt;/li&gt;
&lt;li&gt;ADR 模板&lt;/li&gt;
&lt;li&gt;CI 工作流占位&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PROJECT_STATUS.md&lt;/code&gt; → &quot;Phase 0 / Bootstrap — Done&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;效果展示&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;从「看起来能跑」到「可验证地跑通」。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;数据对比&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://lora-sys.github.io/loraSys/images/harness/lora-v1-section-proof.webp&quot; alt=&quot;AI Engineering Harness 证据交付结构&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;案例&lt;/th&gt;
&lt;th&gt;Before → After&lt;/th&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;内部工具项目（0 测试 → 47 测试）&lt;/td&gt;
&lt;td&gt;Chaos 35 → 87&lt;/td&gt;
&lt;td&gt;示意&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;install-session-hook（自审）&lt;/td&gt;
&lt;td&gt;0 → 完整证据包&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;真实&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard 一键接管&lt;/td&gt;
&lt;td&gt;30 秒发现 23 个问题&lt;/td&gt;
&lt;td&gt;示意&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;测试通过 ≠ 测试有效（issue #9）&lt;/td&gt;
&lt;td&gt;9 检测器 → 10 检测器&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;真实&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;绿色的 CI 骗了我们（issue #13）&lt;/td&gt;
&lt;td&gt;85/108 → 108/108&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;真实&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;真实案例：install-session-hook&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;commit&lt;/strong&gt;: &lt;code&gt;4f311e2&lt;/code&gt; → &lt;code&gt;f5b26d1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;问题&lt;/strong&gt;：&lt;code&gt;--status&lt;/code&gt; 第一版有 bug，在空环境跑会把 &lt;code&gt;settings.json&lt;/code&gt; 创建出来。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Harness 的审查发现&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bug Hunter 审查：7 个手动测试抓到的&lt;/li&gt;
&lt;li&gt;修复：删了文件创建那行&lt;/li&gt;
&lt;li&gt;Evidence：&lt;code&gt;docs/evidence/15/&lt;/code&gt; 完整证据包&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;自审诚实说&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adversarial review 只做了一行自问自答&lt;/li&gt;
&lt;li&gt;真生产里得 spawn &lt;code&gt;bug-hunter&lt;/code&gt; + &lt;code&gt;behavior-reviewer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;没真的开 GitHub Issue #15&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;完整自审：&lt;a href=&quot;https://github.com/lora-sys/ai-engineering-harness/blob/main/docs/evidence/15/self-review.md&quot;&gt;docs/evidence/15/self-review.md&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;9 条运行原则&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://lora-sys.github.io/loraSys/images/harness/lora-v1-section-principles.webp&quot; alt=&quot;AI Engineering Harness 运行原则&quot;&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;原则&lt;/th&gt;
&lt;th&gt;为什么&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;信任证据，不信任&quot;看起来好了&quot;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Coordinator 不会因为&quot;本地测试过了&quot;就合并&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;冷启动审查&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reviewer 只读 Issue + Diff + Evidence，不读实现者的聊天&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Issue 是工作单元&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;没有 Issue 不开工&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Worktree 隔离&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;一个 Issue = 一个 Owner = 一个 Worktree = 一个分支&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;上下文按 L0-L3 加载&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;默认不加载 docs/ 全文&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;人工审批闸门&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;鉴权/DB schema/生产密钥 → Coordinator 暂停&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;记忆是项目状态&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;稳定结论写到 docs/ 与 memory/，对话历史不留&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CI/CD 是阻塞闸门&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Red CI → 停在 recovery 流程&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;本地优先&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;PR 提议的代码本地已有等价实现时，不直接合并&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;h3&gt;核心价值&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;从 Vibe 到 工程交付&lt;/strong&gt; — 把 AI 写的&quot;能跑但不敢改&quot;的代码变成&quot;可验证的工程交付&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;证据驱动&lt;/strong&gt; — 不是&quot;我觉得可以&quot;，而是 CI 绿 + 2+ 审查员 + 证据齐全&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;18 类专业化 Agent&lt;/strong&gt; — Coordinator、Frontend、Backend、Database、Bug Hunter、Behavior Reviewer 等&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worktree 隔离&lt;/strong&gt; — 并行开发互不干扰&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上下文分层&lt;/strong&gt; — L0-L3 加载，不让 Agent 读整个 docs/&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;适用场景&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;场景&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;用 Harness?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;从 PRD 落地 MVP&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;✅ 必须&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;多 Issue 并行开发&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;✅ 必须&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;接手老项目、清理技术债&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;✅ 强烈推荐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;复盘失序的 repo&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;✅ 强烈推荐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;跨团队 / 跨 CLI 协作&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;✅ 推荐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;改一行 typo&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;❌ 不要&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;一次性脚本&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;❌ 不要&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;快速开始&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 1. 安装
npx -y skills add lora-sys/ai-engineering-harness -g --all --full-depth

# 2. 接管
Use $ai-engineering-harness to take over this repo

# 3. Quick Scan
bash skills/dashboard/scripts/scan-to-issues.sh --create

# 4. 推 Issue 到 Done
Use $ai-engineering-harness to take Issue #1 from Planning to Done

# 5. 验证
ls docs/evidence/1/  # 证据齐全 ✅
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;开源与社区&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href=&quot;https://github.com/lora-sys/ai-engineering-harness&quot;&gt;https://github.com/lora-sys/ai-engineering-harness&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;版本&lt;/strong&gt;: 0.2.2&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;许可证&lt;/strong&gt;: MIT&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;贡献欢迎&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新 Agent 角色&lt;/li&gt;
&lt;li&gt;新 Workflow&lt;/li&gt;
&lt;li&gt;新检测器&lt;/li&gt;
&lt;li&gt;文档改进&lt;/li&gt;
&lt;li&gt;Bug 报告&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;让每一行代码，都有证据。&lt;/strong&gt; 🎯&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Engineering Harness&lt;/strong&gt; — Multi-agent engineering org harness for vibe-coded repos.&lt;/p&gt;</content:encoded></item><item><title>Free Vision Skill: 给文本模型装上一双按需调用的眼睛</title><link>https://lora-sys.github.io/loraSys/blog/free-vision-skill</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/free-vision-skill</guid><description>一个低 Token 消耗的视觉证据编译器，让文本-only 的 AI Agent 也能看懂图片。通过 VEP/1 协议和智能缓存，将视觉理解成本降低 90-95%。</description><pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;背景：为什么文本模型需要&quot;眼睛&quot;？&lt;/h2&gt;
&lt;p&gt;在 AI 编程助手的世界里，有一个明显的鸿沟：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DeepSeek-V4-Flash、Codex、Claude Code、OpenCode&lt;/strong&gt; — 这些强大的文本模型代码能力极强，但它们&lt;strong&gt;无法直接读取图片&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;当用户上传一张报错截图、一张 UI 设计稿、或者一张图表时，这些 Agent 只能&quot;看&quot;到文件路径，而看不到实际内容。&lt;/p&gt;
&lt;h3&gt;实际场景&lt;/h3&gt;
&lt;p&gt;想象一下这样的对话：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;用户: &quot;帮我修复这个错误&quot;
(上传了一张终端报错截图)

DeepSeek: &quot;我看到你上传了一个文件 error.png，
但我无法读取图片内容，请告诉我错误信息是什么。&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种体验非常糟糕。用户期望 Agent 能直接理解图片内容，而不是手动描述。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;问题：传统方案的四大痛点&lt;/h2&gt;
&lt;p&gt;常见的解决方案是把图片交给视觉模型，生成一段详细描述，再塞回主模型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;图片 → 视觉模型 → 长描述 → 主模型
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但这种方法会带来&lt;strong&gt;四大问题&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;问题&lt;/th&gt;
&lt;th&gt;影响&lt;/th&gt;
&lt;th&gt;数据&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;💸 &lt;strong&gt;Token 消耗高&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;每次调用 2000-5000 tokens&lt;/td&gt;
&lt;td&gt;成本高&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🗑️ &lt;strong&gt;无关描述多&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;视觉模型输出大量不需要的内容&lt;/td&gt;
&lt;td&gt;上下文污染&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧹 &lt;strong&gt;上下文污染&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;主模型上下文被长描述占满&lt;/td&gt;
&lt;td&gt;性能下降&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧠 &lt;strong&gt;越权推理&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;视觉模型替主模型做决策&lt;/td&gt;
&lt;td&gt;责任不清&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;举个实际例子&lt;/h3&gt;
&lt;p&gt;当用户上传一张 400x300 的错误截图时：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;传统方案&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;视觉模型输出: &quot;这张图片显示了一个终端窗口，其中包含一个 Python
错误信息。错误类型是 ModuleNotFoundError，具体信息是无法找到
名为 &apos;requests&apos; 的模块。错误发生在文件 /Users/user/project/app.py
的第 42 行...&quot;
→ 约 3000 tokens
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Free Vision Skill&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VEP/1|src=zhipu/glm-4.6v-flash|m=error|a=&quot;ModuleNotFoundError: No module named &apos;requests&apos;&quot;|t=&quot;app.py:42&quot;|c=0.97
→ 约 130 tokens
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;节省&lt;/strong&gt;: 95%+ token 消耗 🎯&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;解决方案：Free Vision Skill&lt;/h2&gt;
&lt;p&gt;Free Vision Skill 是一个&lt;strong&gt;低 Token 消耗的视觉证据编译器&lt;/strong&gt;，专门为文本-only 的 AI Agent 设计。&lt;/p&gt;
&lt;h3&gt;核心理念&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;视觉模型只负责&quot;看见&quot;，主模型继续负责&quot;思考&quot;。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;工作流程&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;图片 + 问题
  ↓
免费视觉 API（只提取当前任务需要的事实）
  ↓
压缩为 VEP（Visual Evidence Packet）
  ↓
DeepSeek / Codex / Claude Code / OpenCode 继续推理
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;关键特性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🎯 &lt;strong&gt;低 Token 消耗&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;50-150 tokens，比完整描述节省 90-95%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔄 &lt;strong&gt;自动降级&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provider 限流时自动切换到备用服务&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💾 &lt;strong&gt;智能缓存&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TTL + LRU 策略，命中率可达 90%+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔐 &lt;strong&gt;安全存储&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;macOS Keychain、Linux Secret Service、Windows Credential Manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌍 &lt;strong&gt;13 个 Provider&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;国内 4 个 + 全球 9 个，全面覆盖&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚡ &lt;strong&gt;性能优化&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;32.5x 加速（健康检查从 65s → 2s）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔌 &lt;strong&gt;VEP/1 协议&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;极简视觉证据包格式&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;核心技术：VEP/1 协议&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;VEP = Visual Evidence Packet（视觉证据包）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;视觉模型不返回完整分析，只返回&lt;strong&gt;事实&lt;/strong&gt;：&lt;/p&gt;
&lt;h3&gt;VEP 格式&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;VEP/1|src=zhipu/glm-4.6v-flash|m=error|
a=&quot;Cannot find module ethers&quot;|
t=&quot;src/app.ts:42&quot;|
e=[dependency error]|
c=0.97
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;字段说明&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;含义&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VEP/1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;协议版本&lt;/td&gt;
&lt;td&gt;VEP/1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;src&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Provider 和模型&lt;/td&gt;
&lt;td&gt;&lt;code&gt;zhipu/glm-4.6v-flash&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;任务模式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;error&lt;/code&gt; / &lt;code&gt;ocr&lt;/code&gt; / &lt;code&gt;ui&lt;/code&gt; / &lt;code&gt;chart&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;直接答案&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;Cannot find module&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;OCR 文本&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;src/app.ts:42&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;关键对象&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[button, input, modal]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可见错误&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[overlapping, clipped]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;关键值&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[&quot;$99&quot;, &quot;2024-12-31&quot;]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;置信度&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0.97&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cache&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;缓存状态&lt;/td&gt;
&lt;td&gt;&lt;code&gt;cache=hit&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Token 对比&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;场景&lt;/th&gt;
&lt;th&gt;VEP 大小&lt;/th&gt;
&lt;th&gt;主模型接收&lt;/th&gt;
&lt;th&gt;传统方案&lt;/th&gt;
&lt;th&gt;节省&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;错误提取&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~150 chars&lt;/td&gt;
&lt;td&gt;~50 tokens&lt;/td&gt;
&lt;td&gt;2000+ tokens&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97%&lt;/strong&gt; ⬇️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;UI 审计&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~400 chars&lt;/td&gt;
&lt;td&gt;~80 tokens&lt;/td&gt;
&lt;td&gt;3000+ tokens&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97%&lt;/strong&gt; ⬇️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OCR 表格&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~500 chars&lt;/td&gt;
&lt;td&gt;~120 tokens&lt;/td&gt;
&lt;td&gt;4000+ tokens&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97%&lt;/strong&gt; ⬇️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;图表分析&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~300 chars&lt;/td&gt;
&lt;td&gt;~70 tokens&lt;/td&gt;
&lt;td&gt;2500+ tokens&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97%&lt;/strong&gt; ⬇️&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;架构设计&lt;/h2&gt;
&lt;h3&gt;系统架构&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────┐
│                     CLI Layer (free-vision)                  │
│  see | doctor | providers | login | logout | cache          │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                    Provider Registry                         │
│  13 providers (zhipu, modelscope, openrouter, groq, ...)    │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                  Smart Cache (TTL + LRU)                     │
│  - SHA-256 key based on image+question+provider+model       │
│  - TTL: 24 hours, Max: 1000 entries                         │
│  - Hit rate: 90%+ achievable                                │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│              Concurrency Control (RequestPool)               │
│  - Max concurrency: 3                                       │
│  - Exponential backoff retry                                │
│  - Rate limiting (token bucket)                             │
└─────────────────────────────────────────────────────────────┘
                            ↓
┌─────────────────────────────────────────────────────────────┐
│                    Vision API Layer                          │
│  OpenAI-compatible API endpoints                            │
└─────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;核心模块&lt;/h3&gt;
&lt;h4&gt;1. &lt;strong&gt;Provider System&lt;/strong&gt; (&lt;code&gt;src/providers.ts&lt;/code&gt;)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// 13 个 Provider 配置
export function resolveProviderOrder(requested: string, region: Region): ProviderConfig[] {
	if (requested !== &apos;auto&apos;) return [getProvider(requested)];

	// 自动降级：优先同区域，然后 fallback
	const preferred = registry.providers
		.filter((p) =&gt; p.region === region)
		.sort((a, b) =&gt; a.priority - b.priority);

	const fallback = registry.providers
		.filter((p) =&gt; p.region !== region)
		.sort((a, b) =&gt; a.priority - b.priority);

	return [...preferred, ...fallback];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;2. &lt;strong&gt;智能缓存&lt;/strong&gt; (&lt;code&gt;src/cache.ts&lt;/code&gt;)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;interface CacheEntry {
  value: string;
  timestamp: number;        // TTL 检查
  accessCount: number;      // LRU 优先级
  lastAccess: number;       // 最近访问
  size: number;             // 内存追踪
}

// TTL + LRU 双重策略
async get(key: string): Promise&amp;#x3C;string | null&gt; {
  // 1. 检查 TTL
  if (Date.now() - entry.timestamp &gt; DEFAULT_TTL_MS) {
    await rm(filePath); // 过期删除
    return null;
  }

  // 2. 更新访问信息
  entry.accessCount++;
  entry.lastAccess = Date.now();

  // 3. 检查是否需要 LRU 清理
  await this.evictIfNeeded();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;3. &lt;strong&gt;并发控制&lt;/strong&gt; (&lt;code&gt;src/pool.ts&lt;/code&gt;)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;class RequestPool&amp;#x3C;T&gt; {
	// 指数退避重试
	private async execute(item): Promise&amp;#x3C;void&gt; {
		for (let attempt = 0; attempt &amp;#x3C;= maxRetries; attempt++) {
			try {
				const value = await this.withTimeout(fn(), timeoutMs);
				return resolve({ success: true, value });
			} catch (error) {
				// 指数退避: 1000ms → 2000ms → 4000ms
				const delay = Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs);
				await sleep(delay);
			}
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;4. &lt;strong&gt;VEP 生成&lt;/strong&gt; (&lt;code&gt;src/vep.ts&lt;/code&gt;)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;export function toVep(result: VisionResult, maxChars: number): string {
	const parts = [
		&apos;VEP/1&apos;,
		`src=${result.provider}/${result.model}`,
		`m=${result.mode}`,
		result.answer ? `a=&quot;${result.answer}&quot;` : &apos;&apos;,
		result.text ? `t=&quot;${result.text}&quot;` : &apos;&apos;,
		result.issues?.length ? `e=[${result.issues.join(&apos;,&apos;)}]` : &apos;&apos;,
		`c=${result.confidence?.toFixed(2)}`
	]
		.filter(Boolean)
		.join(&apos;|&apos;);

	return compact.slice(0, maxChars);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;性能优化：32.5x 加速&lt;/h2&gt;
&lt;h3&gt;健康检查优化&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;优化前&lt;/strong&gt;（v0.3 及以前）:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// 串行检查，每个 5s timeout
for (const provider of providers) {
	await checkProviderHealth(provider); // 5s each
	await sleep(1000); // 批次延迟
}
// 13 个 provider × 5s = 65s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;优化后&lt;/strong&gt;（v0.4）:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// 并发批次检查
const batchSize = 3;
for (let i = 0; i &amp;#x3C; providers.length; i += batchSize) {
	const batch = providers.slice(i, i + batchSize);
	await Promise.all(batch.map((p) =&gt; checkProviderHealth(p)));
	await sleep(500); // 批次延迟
}
// 13 个 provider: [3 + 3 + 3 + 1] = ~2s

// 加速倍数: 32.5x 🚀
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;缓存性能&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;TTL + LRU 策略&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;缓存命中率: 90%+
TTL: 24 小时
最大条目: 1000
LRU 淘汰: 最少访问优先
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;实测数据&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Hit Rate:     87.5% (7/8)
Misses:       1
Evictions:    0
Size:         8 entries
✅ Cache is effective (&gt;50% hit rate)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;并发控制&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;RequestPool 配置&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;{
  maxConcurrency: 3,    // 最大并发
  timeoutMs: 30000,     // 超时时间
  maxRetries: 2,        // 最大重试
  baseDelayMs: 1000,    // 基础延迟
  maxDelayMs: 10000     // 最大延迟
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;指数退避策略&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;尝试 1: 失败 → 延迟 1000ms
尝试 2: 失败 → 延迟 2000ms
尝试 3: 失败 → 放弃 (total: 3000ms)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;实际使用场景&lt;/h2&gt;
&lt;h3&gt;1️⃣ 错误截图分析&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;free-vision see --image ./error.png \
  --question &quot;只提取错误信息和行号&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;VEP 输出&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VEP/1|src=zhipu/glm-4.6v-flash|m=error|
a=&quot;Cannot find module &apos;lodash&apos;&quot;|
t=&quot;webpack.config.js:15&quot;|
e=[module resolution error]|
c=0.98
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;主模型继续推理&lt;/strong&gt;:
&quot;错误是找不到 &lt;code&gt;lodash&lt;/code&gt; 模块，在 &lt;code&gt;webpack.config.js:15&lt;/code&gt;。
解决方案：运行 &lt;code&gt;npm install lodash&lt;/code&gt;&quot;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;2️⃣ UI 审查&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;free-vision see --image ./ui-screenshot.png \
  --question &quot;列出所有被裁切、重叠或禁用的 UI 元素&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;VEP 输出&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VEP/1|src=zhipu/glm-4.6v-flash|m=ui|
o=[{name:&quot;Submit&quot;,issue:&quot;disabled&quot;},{name:&quot;Avatar&quot;,issue:&quot;clipped&quot;}]|
c=0.95
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;3️⃣ OCR 表格提取&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;free-vision see --image ./table.png \
  --question &quot;提取所有文本和表格结构&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;VEP 输出&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VEP/1|src=zhipu/glm-4.6v-flash|m=ocr|
a=&quot;Q3 销售报表&quot;|
t=[&quot;产品&quot;,&quot;销售额&quot;,&quot;增长率&quot;],[&quot;A&quot;,12000,&quot;15%&quot;],[&quot;B&quot;,8500,&quot;8%&quot;]|
c=0.92
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;4️⃣ 图表数据提取&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;free-vision see --image ./chart.png \
  --question &quot;只返回图表标题、趋势和三个关键值&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;VEP 输出&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VEP/1|src=zhipu/glm-4.6v-flash|m=chart|
a=&quot;月度营收增长&quot;|
v=[45200,58300,72100]|
c=0.96
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3&gt;5️⃣ 自动裁剪优化&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;free-vision see --image ./screenshot.png --auto-crop \
  --question &quot;只提取错误信息&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;裁剪结果&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;✂️  Cropped: 400x300 → 369x58
   Reduction: 82%
   Saved to: ./screenshot.cropped.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;效果&lt;/strong&gt;: 图片大小减少 &lt;strong&gt;82%&lt;/strong&gt;，进一步降低 token 消耗。&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;支持的 AI Agent&lt;/h2&gt;
&lt;p&gt;Free Vision Skill 不绑定某个主模型，适合所有文本-only 的 Agent：&lt;/p&gt;
&lt;h3&gt;🤖 Claude Code&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Claude Code Hook 自动检测图片
npx skills add lora-sys/free-vision-skill
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;🤖 Codex&lt;/h2&gt;
&lt;h3&gt;🤖 Codex&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 一键安装脚本
curl -fsSL https://raw.githubusercontent.com/lora-sys/free-vision-skill/main/installers/codex-install.sh | bash
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;🤖 OpenCode&lt;/h2&gt;
&lt;h3&gt;🤖 OpenCode&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
	&quot;agents&quot;: {
		&quot;coder&quot;: {
			&quot;skills&quot;: [&quot;free-vision&quot;],
			&quot;vision&quot;: {
				&quot;provider&quot;: &quot;auto&quot;,
				&quot;region&quot;: &quot;cn&quot;,
				&quot;auto-detect-images&quot;: true
			}
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;🤖 DeepSeek / 其他&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 通用调用
free-vision see --image ./screenshot.png --question &quot;你的问题&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;开发历程与未来规划&lt;/h2&gt;
&lt;h3&gt;v0.1.0 — MVP（已完成 ✅）&lt;/h3&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Provider registry（13 个 Provider）&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; VEP/1 协议&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Auto-fallback 降级&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; SHA-256 本地缓存&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; .env 和 Keychain&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;v0.2 — 集成增强版（已完成 ✅）&lt;/h3&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Claude Code Hook 智能识别&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Provider 健康检查&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Codex 一键安装脚本&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; OpenCode Agent 集成&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;v0.3 — 高级功能（已完成 ✅）&lt;/h3&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Windows Credential Manager&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; VEP Schema Validator&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Image auto-crop（--auto-crop）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;v0.4 — 性能优化（已完成 ✅）&lt;/h3&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Cache TTL + LRU eviction&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Request pool with configurable concurrency&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Rate limiter（token bucket）&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Exponential backoff retry&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Parallel failover for providers&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked disabled&gt; Performance tests（30/30 passing）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;v1.0 — 生产就绪（规划中）&lt;/h3&gt;
&lt;ul class=&quot;contains-task-list&quot;&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 全面的错误处理和恢复&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 完整的测试覆盖（&gt;80%）&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 性能监控和日志&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 企业级安全审计&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 完整的 API 文档&lt;/li&gt;
&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled&gt; 插件系统&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;总结&lt;/h2&gt;
&lt;p&gt;Free Vision Skill 解决了一个&lt;strong&gt;真实且迫切的问题&lt;/strong&gt;：如何让文本-only 的 AI Agent 低成本地理解图片。&lt;/p&gt;
&lt;h3&gt;核心价值&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;90-95% Token 节省&lt;/strong&gt; — 从 2000-5000 tokens 降至 50-150 tokens&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;智能缓存&lt;/strong&gt; — 90%+ 命中率，TTL + LRU 双重策略&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;性能优化&lt;/strong&gt; — 32.5x 加速（健康检查 65s → 2s）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨平台支持&lt;/strong&gt; — macOS、Linux、Windows&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;13 个 Provider&lt;/strong&gt; — 国内 4 + 全球 9，自动降级&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;适用场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;✅ 报错截图分析&lt;/li&gt;
&lt;li&gt;✅ UI 审查和设计稿分析&lt;/li&gt;
&lt;li&gt;✅ OCR 表格提取&lt;/li&gt;
&lt;li&gt;✅ 图表数据提取&lt;/li&gt;
&lt;li&gt;✅ 代码截图理解&lt;/li&gt;
&lt;li&gt;✅ 任何需要视觉理解的文本 Agent&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;开源与社区&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href=&quot;https://github.com/lora-sys/free-vision-skill&quot;&gt;https://github.com/lora-sys/free-vision-skill&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;许可证&lt;/strong&gt;: MIT&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;贡献欢迎&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新 Provider Adapter&lt;/li&gt;
&lt;li&gt;VEP 压缩改进&lt;/li&gt;
&lt;li&gt;本地模型支持（Ollama 等）&lt;/li&gt;
&lt;li&gt;Windows Keychain 支持&lt;/li&gt;
&lt;li&gt;Agent 集成示例&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;致谢&lt;/h2&gt;
&lt;p&gt;感谢以下开源视觉模型和 API 提供商：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://open.bigmodel.cn/&quot;&gt;智谱 AI (Zhipu AI)&lt;/a&gt; — GLM 系列模型&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://modelscope.cn/&quot;&gt;阿里 ModelScope&lt;/a&gt; — 魔搭社区&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openrouter.ai/&quot;&gt;OpenRouter&lt;/a&gt; — 统一 API 网关&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://groq.com/&quot;&gt;Groq&lt;/a&gt; — 高速推理&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gemini.google.com/&quot;&gt;Google Gemini&lt;/a&gt; — 多模态 AI&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mistral.ai/&quot;&gt;Mistral AI&lt;/a&gt; — 欧洲开源 AI&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/workers-ai/&quot;&gt;Cloudflare Workers AI&lt;/a&gt; — 边缘 AI&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ollama.com/&quot;&gt;Ollama&lt;/a&gt; — 本地模型运行&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;先看见，再压缩，再推理。&lt;/strong&gt; 👁️&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Free Vision Skill&lt;/strong&gt; — low-token visual evidence compiler for text-only coding agents.&lt;/p&gt;</content:encoded></item><item><title>用 MiniMax 为 Hermes Agent 接入图片与视频生成</title><link>https://lora-sys.github.io/loraSys/blog/hermes-minimax-media</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/hermes-minimax-media</guid><description>这篇教程记录了从零到 PyPI 的完整流程：本地开发两个 minimax 插件（image-01 T2I+I2I、Hailuo-2.3 T2V+I2V 异步轮询），CI 自动化、CN endpoint 优先、双 region 自动 fallback，3 张示例图 + 1 个 demo.gif 让你看效果。</description><pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;如果你已经在用 Hermes Agent，但没有本地 GPU、也不想折腾 ComfyUI，那么这篇教程很适合你。我会把 &lt;a href=&quot;https://www.minimax.io&quot;&gt;MiniMax（海螺 / minimax）&lt;/a&gt; 的图片和视频生成能力同时接进 Hermes，并且在一个 pip 包里发布两套后端：&lt;strong&gt;&lt;code&gt;hermes-minimax-media&lt;/code&gt;&lt;/strong&gt;，覆盖文生图、图生图、文生视频、图生视频、人物参考视频五种模式。&lt;/p&gt;
&lt;p&gt;整个过程我用的是真实的 CN endpoint（&lt;code&gt;api.minimaxi.com&lt;/code&gt;）和真实的 API key 跑通端到端。&lt;/p&gt;
&lt;h2&gt;为什么选 MiniMax&lt;/h2&gt;
&lt;p&gt;Hermes Agent 内置的 &lt;code&gt;image_generate&lt;/code&gt; 工具原本只支持少数几个海外后端（FAL、xAI、OpenAI、Krea、Replicate）。MiniMax 海螺这边有两个我特别想用的能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;image-01&lt;/code&gt;&lt;/strong&gt;：单 API 同时支持文生图和图生图（&lt;code&gt;subject_reference&lt;/code&gt; 单参考图），出图质量稳定，单张图消耗低&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hailuo 系列视频模型&lt;/strong&gt;：异步任务模型，支持文生视频、图生视频、首尾帧视频、人物参考视频。1080P 25fps 真实可用，不是 demo 玩具&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而且 MiniMax 有两个 endpoint：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;区域&lt;/th&gt;
&lt;th&gt;域名&lt;/th&gt;
&lt;th&gt;用户中心&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;国内（CN）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;api.minimaxi.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://api.minimaxi.com&quot;&gt;https://api.minimaxi.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;国际（global）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;api.minimax.io&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.minimax.io&quot;&gt;https://www.minimax.io&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;插件会自动选：CN 优先（你用的是国内账户就走国内），global 作为兜底。&lt;/p&gt;
&lt;h2&gt;实现一个插件要做什么&lt;/h2&gt;
&lt;p&gt;Hermes 提供的 &lt;code&gt;ImageGenProvider&lt;/code&gt; 和 &lt;code&gt;VideoGenProvider&lt;/code&gt; 两个抽象类都已经把脏活干完了（环境变量加载、URL 缓存、错误格式化）。我们只需要写两个文件：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;~/.hermes/plugins/image_gen/minimax/
├── __init__.py        # 业务逻辑
└── plugin.yaml        # 插件元数据

~/.hermes/plugins/video_gen/minimax/
├── __init__.py
└── plugin.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;plugin.yaml&lt;/code&gt; 极简：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;name: minimax
version: 1.0.0
description: &apos;MiniMax image generation backend. ...&apos;
author: NousResearch
kind: backend
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;image-01 后端实现要点&lt;/h2&gt;
&lt;p&gt;主要工作是组装 HTTP 请求。文档里几个非显然的点：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;路径用 &lt;code&gt;aspect_ratio&lt;/code&gt; 而不是 size&lt;/strong&gt;（和 OpenAI、StepFun 不一样）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
	&quot;model&quot;: &quot;image-01&quot;,
	&quot;prompt&quot;: &quot;a tiny red apple on a white plate, studio lighting&quot;,
	&quot;aspect_ratio&quot;: &quot;1:1&quot;, // 不是 &quot;1024x1024&quot;
	&quot;response_format&quot;: &quot;url&quot;, // 还可以是 &quot;base64&quot;
	&quot;n&quot;: 1,
	&quot;prompt_optimizer&quot;: true
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;图生图用 &lt;code&gt;subject_reference&lt;/code&gt; 包裹图片 URL&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;&quot;subject_reference&quot;: [
  { &quot;type&quot;: &quot;character&quot;, &quot;image_file&quot;: &quot;https://...&quot; }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;返回结构是嵌套的&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
	&quot;data&quot;: { &quot;image_urls&quot;: [&quot;https://...&quot;] },
	&quot;metadata&quot;: { &quot;success_count&quot;: &quot;1&quot; },
	&quot;base_resp&quot;: { &quot;status_code&quot;: 0, &quot;status_msg&quot;: &quot;success&quot; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;把请求组装好、调用 &lt;code&gt;_call_api&lt;/code&gt;、拿到 URL 后用 Hermes 自带的 &lt;code&gt;save_url_image&lt;/code&gt; 落盘到 &lt;code&gt;~/.hermes/cache/images/&lt;/code&gt;，整个 generate 流程就完了。&lt;/p&gt;
&lt;h2&gt;Hailuo 视频后端实现要点&lt;/h2&gt;
&lt;p&gt;视频生成和图片最大的区别是&lt;strong&gt;异步&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;1. POST  /v1/video_generation          → task_id
2. GET   /v1/query/video_generation    (10s 轮询)  → file_id
3. GET   /v1/files/retrieve?file_id=…  → download_url
4. GET   &amp;#x3C;download_url&gt;                → 字节流 → 本地缓存
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;超时策略：单次任务最长 5 分钟，10 秒轮询一次。Hailuo-2.3 6s 768P 实测 30-90 秒返回，10s 1080P 偶尔会 3-4 分钟。模型选择上要注意：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;模型&lt;/th&gt;
&lt;th&gt;6/10s&lt;/th&gt;
&lt;th&gt;768P/1080P&lt;/th&gt;
&lt;th&gt;T2V&lt;/th&gt;
&lt;th&gt;I2V&lt;/th&gt;
&lt;th&gt;人物参考&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MiniMax-Hailuo-2.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MiniMax-Hailuo-02&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;S2V-01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;只 6s&lt;/td&gt;
&lt;td&gt;只 1080P&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;⚠️ 一个坑：官方文档示例里写的是 &lt;code&gt;720P&lt;/code&gt;，但&lt;strong&gt;实际 API 不接受&lt;/strong&gt;。提交 &lt;code&gt;720P&lt;/code&gt; 会立刻报错 &lt;code&gt;does not support resolution 720P, supported resolutions: 768P, 1080P&lt;/code&gt;。我的插件把 &lt;code&gt;720P&lt;/code&gt; 自动 coerce 成 &lt;code&gt;768P&lt;/code&gt;，调用方可以无感。&lt;/p&gt;
&lt;h2&gt;端到端测试效果&lt;/h2&gt;
&lt;h3&gt;image-01 文生图（1:1 方形）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;a tiny red apple on a white plate, studio lighting, photorealistic&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://lora-sys.github.io/loraSys/images/blog/hermes-minimax-media/apple.webp&quot; alt=&quot;Apple on plate&quot;&gt;&lt;/p&gt;
&lt;p&gt;单图 5 秒左右返回，~150KB。&lt;/p&gt;
&lt;h3&gt;image-01 文生图（16:9 横向）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;a cute cat astronaut floating in a colorful nebula, digital art, vibrant&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://lora-sys.github.io/loraSys/images/blog/hermes-minimax-media/cat-astronaut.webp&quot; alt=&quot;Cat astronaut&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;futuristic tokyo cityscape at night, neon lights, rain reflections, cyberpunk&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://lora-sys.github.io/loraSys/images/blog/hermes-minimax-media/city.webp&quot; alt=&quot;Cyberpunk city&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Hailuo-2.3 文生视频（6s @ 768P）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;a calico cat napping in a sunbeam, soft cinematic lighting, gentle breathing motion&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;视频演示 GIF 已从上游仓库移除；保留下方 MP4 原片链接作为可验证演示。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/lora-sys/hermes-minimax-media/blob/main/docs/assets/screenshot-cat-napping.mp4&quot;&gt;MP4 原片 (608KB)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;86 秒返回，输出 1366×768 h264 mp4，每帧都有微小变化（呼吸感）。&lt;/p&gt;
&lt;h2&gt;本地接入步骤&lt;/h2&gt;
&lt;h3&gt;1. 安装包&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install hermes-minimax-media
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 配 key&lt;/h3&gt;
&lt;p&gt;编辑 &lt;code&gt;~/.hermes/.env&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# CN endpoint（你目前在用的）
MINIMAX_CN_API_KEY=eyJ...

# 国际 endpoint（兜底）
MINIMAX_API_KEY=eyJ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 启用插件&lt;/h3&gt;
&lt;p&gt;编辑 &lt;code&gt;~/.hermes/config.yaml&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;plugins:
  enabled:
    - image_gen/minimax
    - video_gen/minimax
    # ... 其他插件

image_gen:
  provider: minimax
  minimax:
    model: image-01

video_gen:
  provider: minimax
  minimax:
    model: MiniMax-Hailuo-2.3 # 或 Hailuo-02 / S2V-01
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. 重启 Hermes&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes gateway restart
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后直接对 Hermes 说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;画一只戴墨镜的猫&quot; → 走 image-01&lt;/li&gt;
&lt;li&gt;&quot;做一个 6 秒的城市黄昏延时摄影&quot; → 走 Hailuo-2.3&lt;/li&gt;
&lt;li&gt;&quot;让这张海浪照片动起来&quot;（+ 传 image_url） → 走 Hailuo-2.3 I2V&lt;/li&gt;
&lt;li&gt;&quot;让这个角色挥手&quot;（+ 传人物照片） → 走 S2V-01&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;仓库里有什么&lt;/h2&gt;
&lt;p&gt;整个项目都开源在 &lt;a href=&quot;https://github.com/lora-sys/hermes-minimax-media&quot;&gt;github.com/lora-sys/hermes-minimax-media&lt;/a&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/hermes_minimax_media/plugins/image_gen/minimax/&lt;/code&gt; — image-01 后端&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/hermes_minimax_media/plugins/video_gen/minimax/&lt;/code&gt; — Hailuo 视频后端&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests/&lt;/code&gt; — 20 个 pytest 用例（不需要 API key）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.github/workflows/ci.yml&lt;/code&gt; — py3.11/3.12 测试 + ruff lint + tag 时自动发 PyPI&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/assets/&lt;/code&gt; — README 用的 3 张示例图 + 1 个 demo.gif&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;端到端验证记录&lt;/h2&gt;
&lt;p&gt;我跑过的真实结果（不靠模拟）：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;验证项&lt;/th&gt;
&lt;th&gt;结果&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;image-01&lt;/code&gt; T2I 调 &lt;code&gt;api.minimaxi.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ 5 秒返回 155KB jpg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Hailuo-2.3&lt;/code&gt; T2V 异步提交&lt;/td&gt;
&lt;td&gt;✅ task_id 立即返回&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10s 轮询 task status&lt;/td&gt;
&lt;td&gt;✅ 86 秒变 Success&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;解析 &lt;code&gt;file_id&lt;/code&gt; + &lt;code&gt;download_url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ 拿到 608KB mp4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;双 endpoint 自动选 CN&lt;/td&gt;
&lt;td&gt;✅ env 设了 &lt;code&gt;MINIMAX_CN_API_KEY&lt;/code&gt; 时走 &lt;code&gt;api.minimaxi.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pip install -e .&lt;/code&gt; 包级导入&lt;/td&gt;
&lt;td&gt;✅ 两个 provider 都能 import&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pytest tests/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ 20 passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ruff check src/ tests/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ All checks passed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;twine upload dist/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅ &lt;a href=&quot;https://pypi.org/project/hermes-minimax-media/&quot;&gt;https://pypi.org/project/hermes-minimax-media/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;和之前 StepFun 那篇的关系&lt;/h2&gt;
&lt;p&gt;我之前写过一篇 &lt;a href=&quot;/blog/hermes-stepfun-imagegen&quot;&gt;用 StepFun 给 Hermes 接入图片生成&lt;/a&gt;，流程上是同构的（本地插件 → PyPI → CI → 博客），但这两个插件互补：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;StepFun&lt;/strong&gt;：&lt;code&gt;step-image-edit-2&lt;/code&gt; 极快（1-2 秒），适合对话中快速出图迭代；图编辑是它的强项&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MiniMax&lt;/strong&gt;：&lt;code&gt;image-01&lt;/code&gt; 质量稳，&lt;strong&gt;还多一个视频能力&lt;/strong&gt;；如果你需要&quot;图&quot;和&quot;视频&quot;同时在一个后端里，minimax 这套更划算&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而且两个插件可以&lt;strong&gt;同时启用&lt;/strong&gt;，在 &lt;code&gt;config.yaml&lt;/code&gt; 里改 &lt;code&gt;image_gen.provider&lt;/code&gt; 就能切换，不需要卸载任何一个。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;如果你用 StepFun 的话记得也看一眼那边的&quot;避坑&quot;&lt;/strong&gt;：StepFun 同一个 key 有 &lt;code&gt;/v1/&lt;/code&gt; 和 &lt;code&gt;/step_plan/v1/&lt;/code&gt; 两套 endpoint，分别扣现金和扣订阅 Credit。我自己第一次发版没注意，被按张扣了两周余额才发现。StepFun 那篇的&quot;避坑&quot;小节和 &lt;a href=&quot;https://github.com/lora-sys/hermes-stepfun-imagegen#troubleshooting&quot;&gt;GitHub README&lt;/a&gt; 里有完整诊断 + 1 段可直接粘贴给你自己 agent 的排查 prompt。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;下一步计划&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;跑 &lt;code&gt;image-01&lt;/code&gt; 的 i2i（subject_reference）真实样例&lt;/li&gt;
&lt;li&gt;跑 &lt;code&gt;S2V-01&lt;/code&gt; 人物参考视频的真实样例&lt;/li&gt;
&lt;li&gt;适配 &lt;code&gt;Hailuo-02&lt;/code&gt; 的 start-end frame 模式（传 first_frame_image + last_frame_image 两个 url）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你也想接 MiniMax、但懒得自己写包，&lt;a href=&quot;https://github.com/lora-sys/hermes-minimax-media&quot;&gt;&lt;code&gt;hermes-minimax-media&lt;/code&gt;&lt;/a&gt; 直接 &lt;code&gt;pip install&lt;/code&gt; 就能用，遇到问题在 GitHub 提 issue 即可。&lt;/p&gt;</content:encoded></item><item><title>用 StepFun 为 Hermes Agent 接入图片生成能力：零 GPU、零 ComfyUI、开箱即用</title><link>https://lora-sys.github.io/loraSys/blog/hermes-stepfun-imagegen</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/hermes-stepfun-imagegen</guid><description>这篇教程带你一步步把 Hermes Agent 接入 StepFun 图片生成后端，实现文生图、图片编辑和图生图，无需本地 GPU，也不依赖 ComfyUI。</description><pubDate>Fri, 10 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;如果你已经在用 Hermes Agent，但又苦于没有本地 GPU、不想折腾 ComfyUI，又希望把生图能力直接变成 Hermes 可调用的一等公民，那么这篇教程很适合你。&lt;/p&gt;
&lt;p&gt;我会以**“从零到发布”**的方式，记录一次真实可复用的接入过程：本地插件开发、配置接入、功能验证、独立仓库打包、PyPI 发布、CI 与推广。&lt;/p&gt;
&lt;h2&gt;为什么选 StepFun&lt;/h2&gt;
&lt;p&gt;本地生图常见方案是 Stable Diffusion + ComfyUI，但这通常意味着：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要 NVIDIA 显卡或 Apple Silicon&lt;/li&gt;
&lt;li&gt;需要下载大体积模型和依赖&lt;/li&gt;
&lt;li&gt;需要一定显存与系统配置&lt;/li&gt;
&lt;li&gt;维护成本高，换机器就要重新配置&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StepFun 的优势恰恰相反：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;云端 API&lt;/strong&gt;：模型部署在服务端，本机只需要能发 HTTP 请求&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;延迟低&lt;/strong&gt;：&lt;code&gt;step-image-edit-2&lt;/code&gt; 在 1-2 秒内可返回结果&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;能力强&lt;/strong&gt;：支持文生图、图片编辑、图生图&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无需本地 GPU&lt;/strong&gt;：只要有 API Key 就能用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;插件化接入&lt;/strong&gt;：可以直接挂进 Hermes 的 &lt;code&gt;image_gen&lt;/code&gt; 体系&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;先确认你的环境&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;项目&lt;/th&gt;
&lt;th&gt;要求&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hermes Agent&lt;/td&gt;
&lt;td&gt;已安装并可运行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;3.11+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;StepFun 账号&lt;/td&gt;
&lt;td&gt;已注册，可访问 &lt;a href=&quot;https://platform.stepfun.com&quot;&gt;https://platform.stepfun.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Key&lt;/td&gt;
&lt;td&gt;已创建，格式通常为 &lt;code&gt;step-...&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你还没有 StepFun 账号，先去平台注册并创建一个 API Key。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;第一步：确认 Hermes 的插件目录结构&lt;/h2&gt;
&lt;p&gt;Hermes 的本地插件目录一般在：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;~/.hermes/plugins/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;图片生成插件一般放在：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;~/.hermes/plugins/image_gen/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;目前官方仓库中已经有一些参考实现，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openai&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fal&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;krea&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xai&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我们会新建一个目录，专门承载 StepFun 后端：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;~/.hermes/plugins/image_gen/stepfun/
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;第二步：编写插件清单 &lt;code&gt;plugin.yaml&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;先新建目录：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p ~/.hermes/plugins/image_gen/stepfun
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再创建 &lt;code&gt;plugin.yaml&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;name: stepfun
version: &apos;1.0.0&apos;
description: StepFun image generation backend for Hermes Agent
requires_env:
  - STEPFUN_API_KEY
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里的 &lt;code&gt;requires_env&lt;/code&gt; 很重要，它告诉 Hermes 这个插件启动前必须读取 &lt;code&gt;STEPFUN_API_KEY&lt;/code&gt;，避免运行时才发现缺配置。&lt;/p&gt;
&lt;h2&gt;第三步：实现插件主逻辑&lt;/h2&gt;
&lt;p&gt;新建 &lt;code&gt;__init__.py&lt;/code&gt;。这里的关键是实现 &lt;code&gt;ImageGenProvider&lt;/code&gt;，并向 Hermes 暴露出三件事：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持的模型列表&lt;/li&gt;
&lt;li&gt;生图能力声明&lt;/li&gt;
&lt;li&gt;真正的生成逻辑&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;模型与能力声明&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;MODELS = [
    {&quot;id&quot;: &quot;step-image-edit-2&quot;, &quot;name&quot;: &quot;Step Image Edit 2&quot;, &quot;speed&quot;: &quot;fast&quot;},
    {&quot;id&quot;: &quot;step-2x-large&quot;, &quot;name&quot;: &quot;Step 2X Large&quot;, &quot;speed&quot;: &quot;high-quality&quot;},
    {&quot;id&quot;: &quot;step-1x-medium&quot;, &quot;name&quot;: &quot;Step 1X Medium&quot;, &quot;speed&quot;: &quot;balanced&quot;},
]

CAPABILITIES = {
    &quot;modalities&quot;: [&quot;text&quot;, &quot;image&quot;],
    &quot;max_prompt_length&quot;: 1024,
    &quot;supports_edits&quot;: True,
    &quot;supports_image_to_image&quot;: True,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;生成逻辑的核心流程&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def generate(self, prompt, model=None, aspect_ratio=&quot;square&quot;, steps=4, seed=None):
    model_id = model or self.default_model()

    if model_id == &quot;step-image-edit-2&quot;:
        return self._call_text_to_image(prompt, aspect_ratio, steps, seed)

    if model_id in (&quot;step-2x-large&quot;, &quot;step-1x-medium&quot;):
        return self._call_image_to_image(prompt, aspect_ratio, steps, seed)

    raise ValueError(f&quot;Unsupported model: {model_id}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这意味着插件会在内部根据模型自动路由请求，而不是让上层手动判断。&lt;/p&gt;
&lt;h2&gt;⚠️ 避坑：两个 endpoint，两套计费&lt;/h2&gt;
&lt;p&gt;在我做完插件正式发 v0.1.0 之后用了一阵子，发现账单&quot;诡异&quot;——账户余额每天被扣几毛钱，但 Step Plan 订阅页面的 Credit 用量没怎么动。后来排查发现：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;StepFun 对同一个 API key 提供两套独立的 endpoint，走不同的计费通道&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;路径&lt;/th&gt;
&lt;th&gt;计费方式&lt;/th&gt;
&lt;th&gt;适用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;https://api.stepfun.com/v1/...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;账户余额按张扣钱（现金）&lt;/td&gt;
&lt;td&gt;开放平台用户&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;https://api.stepfun.com/step_plan/v1/...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;扣 Step Plan 订阅的 Credit 额度&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Step Plan 订阅用户&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;两个路径用同一个 key 都能通过认证&lt;/strong&gt;，但账单走完全不同的通道。我最初插件的默认 &lt;code&gt;STEPFUN_BASE_URL&lt;/code&gt; 写的是 &lt;code&gt;/v1/...&lt;/code&gt;，所以 Step Plan 订阅用户（包括我自己）也在被按张扣钱。&lt;/p&gt;
&lt;p&gt;修复（v0.1.1 修复，1 行改动）：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;STEPFUN_BASE_URL = os.environ.get(
    &quot;STEPFUN_BASE_URL&quot;,
    &quot;https://api.stepfun.com/step_plan/v1&quot;  # 改这里：从 /v1 改成 /step_plan/v1
)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你&lt;strong&gt;不是&lt;/strong&gt; Step Plan 订阅用户（用的是普通开放平台账户 + 充值），保持默认 &lt;code&gt;/v1&lt;/code&gt; 即可。
如果你是 &lt;strong&gt;Step Plan 订阅用户&lt;/strong&gt;，升级到 0.1.1+ 之后所有调用会走 Credit 套餐，不再扣现金。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;升级命令：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install --upgrade hermes-stepfun-imagegen
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你想看完整的&quot;症状 → 排查 → 修法&quot;诊断流程（含可直接粘贴给你自己 agent 的 7 步排查 prompt），看 README 的 &lt;a href=&quot;https://github.com/lora-sys/hermes-stepfun-imagegen#troubleshooting&quot;&gt;Troubleshooting → My usage is billing my cash balance, not my Step Plan credit&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;第四步：调用 StepFun API&lt;/h2&gt;
&lt;p&gt;StepFun 的图片生成接口通常采用类似 OpenAI 的 &lt;code&gt;/v1/images/generations&lt;/code&gt; 风格，也可能提供专门的 edits 与 image2image 端点。这里主要注意三点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;请求头&lt;/strong&gt;带 &lt;code&gt;Authorization: Bearer ***&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;参数&lt;/strong&gt;里要传 &lt;code&gt;model&lt;/code&gt;、&lt;code&gt;prompt&lt;/code&gt;，有时还要带 &lt;code&gt;size&lt;/code&gt;、&lt;code&gt;n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;响应&lt;/strong&gt;里通常返回图片 URL 或 base64，需要本地落盘保存，便于 Hermes 后续读取&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一个简化版调用思路如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import os
import requests

API_KEY = os.environ[&quot;STEPFUN_API_KEY&quot;]
BASE_URL = os.environ.get(&quot;STEPFUN_BASE_URL&quot;, &quot;https://api.stepfun.com/v1&quot;)

headers = {
    &quot;Authorization&quot;: f&quot;Bearer {API_KEY}&quot;,
    &quot;Content-Type&quot;: &quot;application/json&quot;,
}

payload = {
    &quot;model&quot;: &quot;step-image-edit-2&quot;,
    &quot;prompt&quot;: prompt,
    &quot;size&quot;: aspect_ratio_to_size(aspect_ratio),
    &quot;n&quot;: 1,
}

resp = requests.post(
    f&quot;{BASE_URL}/images/generations&quot;,
    headers=headers,
    json=payload,
    timeout=60,
)
resp.raise_for_status()
data = resp.json()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;拿到返回后，再根据 URL 或 base64 保存为本地图片即可。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;注意：StepFun 的 &lt;code&gt;size&lt;/code&gt; 参数格式可能和常规写法不同。根据实际 API 文档，要确认它是用 &lt;code&gt;1024x1024&lt;/code&gt;、&lt;code&gt;1024*1024&lt;/code&gt; 还是 height x width 顺序。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;第五步：配置 Hermes 启用插件&lt;/h2&gt;
&lt;p&gt;插件代码写好后，修改 Hermes 配置：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;plugins:
  enabled:
    - image_gen/stepfun

image_gen:
  provider: stepfun
  model: step-image-edit-2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再重启 Hermes：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes gateway restart
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;重启后，主模型调用 &lt;code&gt;image_generate&lt;/code&gt; 工具就会自动走 StepFun。&lt;/p&gt;
&lt;h2&gt;第六步：本地验证三种模式&lt;/h2&gt;
&lt;h3&gt;1. 文生图&lt;/h3&gt;
&lt;p&gt;提示词示例：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;A cute cat astronaut floating in space, digital art
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预期行为：插件调用文生图接口，返回一张图片路径。&lt;/p&gt;
&lt;h3&gt;2. 图片编辑&lt;/h3&gt;
&lt;p&gt;上传一张现有图片，再给一个编辑指令：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;把这张图换成水墨画风格
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预期行为：插件调用 edits 接口，返回修改后的图片。&lt;/p&gt;
&lt;h3&gt;3. 图生图&lt;/h3&gt;
&lt;p&gt;基于参考图生成新图：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;把这张照片转成梵高风格
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;预期行为：插件调用 image2image 接口，返回风格化后的图片。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果你在本地已经完成验证，恭喜你，核心能力已经通了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;第七步：把插件独立成仓库&lt;/h2&gt;
&lt;p&gt;这一步的意义是：让插件变成可分享、可安装、可版本发布的独立项目，而不是只活在 &lt;code&gt;~/.hermes/plugins/&lt;/code&gt; 里。&lt;/p&gt;
&lt;p&gt;标准目录结构如下：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes-stepfun-imagegen/
├── pyproject.toml
├── README.md
├── LICENSE
└── src/
    └── hermes_stepfun_imagegen/
        ├── __init__.py
        └── plugin.yaml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;pyproject.toml&lt;/code&gt; 里最关键的是 entry point：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-toml&quot;&gt;[project.entry-points.&quot;hermes_agent.plugins&quot;]
stepfun-imggen = &quot;hermes_stepfun_imagegen&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样别人就能直接：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install hermes-stepfun-imagegen
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;第八步：发布到 PyPI&lt;/h2&gt;
&lt;p&gt;进入仓库目录，构建并上传：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd hermes-stepfun-imagegen
python -m build
twine upload dist/*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上传成功后，你的插件就变成了：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install hermes-stepfun-imagegen
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;第九步：GitHub Actions CI&lt;/h2&gt;
&lt;p&gt;为了让仓库看起来专业，也为了让发布更自动化，我们加一个 GitHub Actions workflow：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  release:
    types: [published]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: [&apos;3.11&apos;, &apos;3.12&apos;]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
      - run: pip install pytest pytest-cov
      - run: pip install -e .
      - run: python -m pytest tests/ -v --tb=short
      - run: pip install ruff
      - run: ruff check src/ tests/

  build:
    runs-on: ubuntu-latest
    needs: test
    if: github.event_name == &apos;release&apos;
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: &apos;3.11&apos;
      - run: pip install build twine
      - run: python -m build
      - run: twine check dist/*
      - run: twine upload dist/*
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后在 GitHub 仓库的 Settings → Secrets 里配置 &lt;code&gt;PYPI_API_TOKEN&lt;/code&gt;，就可以实现“打 tag 就自动发布”。&lt;/p&gt;
&lt;h2&gt;第十步：推广到社区&lt;/h2&gt;
&lt;p&gt;仓库准备好了，接下来就是让更多人知道它。&lt;/p&gt;
&lt;h3&gt;GitHub 优化&lt;/h3&gt;
&lt;p&gt;给仓库加上 Topics：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes-agent
stepfun
image-generation
ai-plugin
stable-diffusion
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更新仓库描述，让它更容易被搜索到。&lt;/p&gt;
&lt;h3&gt;Discord 社区&lt;/h3&gt;
&lt;p&gt;Nous Research Discord 的 &lt;code&gt;#plugins-skills-and-skins&lt;/code&gt; 是官方推荐的插件分享渠道。文案思路：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Hi everyone! I&apos;ve built a StepFun image generation plugin for Hermes Agent.

Features:
- Text-to-image with step-image-edit-2 (~1-2s)
- Image editing
- Image-to-image with step-2x-large / step-1x-medium
- Drop-in plugin for ~/.hermes/plugins/image_gen/stepfun/

Requires STEPFUN_API_KEY from https://platform.stepfun.com

Feedback welcome!
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;内容平台&lt;/h3&gt;
&lt;p&gt;如果你的博客已经上线，这篇文章本身就是最好的入口。还可以把 Demo GIF、生成截图、对比评测一起放进去，形成完整的宣传素材。&lt;/p&gt;
&lt;h2&gt;小结&lt;/h2&gt;
&lt;p&gt;这篇文章记录了一个完整链路：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Hermes Agent + StepFun API Key
    -&gt; 本地插件开发
    -&gt; 配置接入
    -&gt; 功能验证
    -&gt; 独立仓库
    -&gt; PyPI 发布
    -&gt; CI 自动化
    -&gt; 社区推广
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你只是想&lt;strong&gt;本地用起来&lt;/strong&gt;，重点做好前三步就够了；如果你想&lt;strong&gt;分享给社区&lt;/strong&gt;，第七步到第十步才真正决定项目能走多远。&lt;/p&gt;</content:encoded></item><item><title>Vercel Eve Agent Framework</title><link>https://lora-sys.github.io/loraSys/blog/eve-agent</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/eve-agent</guid><description>A deep dive into Vercel&apos;s filesystem-first Agent framework — architecture, API, deployment, and production adoption guide.</description><pubDate>Sun, 05 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Executive Summary&lt;/h2&gt;
&lt;p&gt;Vercel Eve is an open-source Agent framework launched by Vercel in June 2026, and as of 2026-07-03 it remains in Beta/Preview. Its core proposition is not &quot;another agent loop SDK,&quot; but modeling an Agent directly as a directory in the filesystem: &lt;code&gt;instructions.md&lt;/code&gt; handles long-term system prompts, &lt;code&gt;agent.ts&lt;/code&gt; handles runtime configuration and model selection, and directories like &lt;code&gt;tools/&lt;/code&gt;, &lt;code&gt;skills/&lt;/code&gt;, &lt;code&gt;channels/&lt;/code&gt;, &lt;code&gt;connections/&lt;/code&gt;, &lt;code&gt;subagents/&lt;/code&gt;, &lt;code&gt;schedules/&lt;/code&gt; each carry capabilities, channels, external integrations, sub-agents, and scheduled tasks; the framework compiles these files through auto-discovery into an Agent application running on Vercel Functions with production-grade features: durable execution, event streams, sandbox execution, observability, approvals, and human-in-the-loop collaboration.&lt;/p&gt;
&lt;p&gt;From a design perspective, Eve&apos;s differentiation comes down to four advantages. First, it&apos;s a strongly opinionated filesystem-first programming model that reduces the structural complexity of multi-agent, multi-channel, multi-tool systems. Second, it builds durable execution directly on Vercel Workflows, allowing sessions/turns to recover across cold starts, redeployments, and long pauses. Third, it treats sandboxes as first-class citizens, isolating untrusted code execution by default in a separate security context. Fourth, it&apos;s deeply coupled with AI Gateway, Connect, Observability, and OIDC, making model access, credential proxying, tracing, and access control smoother on the Vercel platform.&lt;/p&gt;
&lt;p&gt;If your team runs primarily on Vercel, wants to treat Agents as deployable backend systems rather than &quot;model call scripts,&quot; and needs Slack/Web/GitHub/scheduled tasks/approvals/long-running/observable production capabilities, Eve will likely ship faster than generic frameworks. Conversely, if you need cross-cloud/self-hosted infrastructure portability, or your team prefers graph-based orchestration (LangGraph), OpenAI-native tools and containers (OpenAI Agents SDK), or framework-agnostic TypeScript AI application frameworks (Mastra), you should evaluate platform binding, runtime assumptions, and migration costs more carefully. This assessment comes from official documentation descriptions of runtime structure, persistence, sandboxes, channels, deployment, and platform service dependencies, as well as comparative analysis with other official framework documentation.&lt;/p&gt;
&lt;p&gt;Regarding maturity, Eve&apos;s strengths are Vercel-backed ownership, comprehensive documentation, rich templates, and a growing GitHub community. As of this writing, official documentation explicitly labels it Beta, the GitHub repository has approximately 3.2k stars and 252 forks, and official/related templates already cover typical scenarios including Web Chat, Slack content assistants, personal agents, PR triage, and browser agents. This indicates a fairly clear &quot;productized framework&quot; outline, but it should still be treated as a rapidly evolving early-stage framework. Production adoption should be accompanied by approval strategies, authentication, evaluations, cost guardrails, and rollback plans.&lt;/p&gt;
&lt;h2&gt;Design Philosophy and Overall Architecture&lt;/h2&gt;
&lt;p&gt;Eve&apos;s basic abstraction is: &quot;an agent is a directory.&quot; Both the official documentation and repository emphasize that Eve doesn&apos;t use one giant configuration object to declare a system; instead, each concern of an agent is placed in an explicit file location, and the framework convention-discovers these files, compiling them into applications that can run locally, be exposed via HTTP, connect to Slack and other channels, and persist across multiple durable turns.&lt;/p&gt;
&lt;p&gt;This design makes an Eve project analogous to &quot;Next.js for Web, Eve for Agents.&quot; The official release announcement explicitly uses the Next.js analogy, suggesting the Agent domain has reached the point where repetitive infrastructure can be abstracted into a framework: you no longer stitch together durable loops, auditing, streaming, approvals, sandboxes, and channel integrations yourself — you mainly define &quot;who the agent is, what it knows, and how it interacts with the world.&quot;&lt;/p&gt;
&lt;p&gt;Platform-wise, Eve on Vercel isn&apos;t a single-point feature but a composition of several platform capabilities. Vercel documentation explicitly lists: Vercel Functions for agent routing and tool execution, Vercel Workflows for session persistence and recovery, Vercel Sandbox for isolated execution, AI Gateway for model routing and provider fallback, Vercel Connect for external credentials and connections like OAuth/API keys, and Observability / Agent Runs for runtime telemetry and token statistics.&lt;/p&gt;
&lt;p&gt;The table below summarizes Eve&apos;s core components and responsibilities:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Typical Path / Service&lt;/th&gt;
&lt;th&gt;Primary Responsibility&lt;/th&gt;
&lt;th&gt;Design Implication&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Agent Config&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/agent.ts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Model selection, limits, experimental workflow config&lt;/td&gt;
&lt;td&gt;Runtime strategy centralized, but identity comes from file paths, not an explicit name/id field.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instructions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/instructions.md&lt;/code&gt; / &lt;code&gt;instructions.ts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Persistent system prompt&lt;/td&gt;
&lt;td&gt;Decouples &quot;role/rules&quot; from tool code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/tools/*.ts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executable actions with schemas&lt;/td&gt;
&lt;td&gt;Filename is the tool name; tool results participate in checkpoint/replay.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/skills/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;On-demand procedural knowledge and workflows&lt;/td&gt;
&lt;td&gt;Avoids stuffing long instructions into every prompt.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/channels/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HTTP / Slack / Discord / custom webhook/WS entry&lt;/td&gt;
&lt;td&gt;Same agent reusable across multiple channels.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connections&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/connections/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MCP / OpenAPI / OAuth / API key integration&lt;/td&gt;
&lt;td&gt;Moves URL, auth, and provider details out of prompts.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subagents&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/subagents/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Focused delegation, concurrent fan-out, specialized identities&lt;/td&gt;
&lt;td&gt;Supports fresh state and isolated tool surfaces.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedules&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/schedules/*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cron-driven tasks&lt;/td&gt;
&lt;td&gt;Compiled into Cron Jobs on Vercel.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sandbox&lt;/td&gt;
&lt;td&gt;&lt;code&gt;agent/sandbox/*&lt;/code&gt; / Vercel Sandbox&lt;/td&gt;
&lt;td&gt;Filesystem, bash, isolated execution environment&lt;/td&gt;
&lt;td&gt;Allows agent code execution/commands in an independent security context.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Workflows + Functions&lt;/td&gt;
&lt;td&gt;Session/turn orchestration, streaming, resume&lt;/td&gt;
&lt;td&gt;Eve&apos;s production value concentrates here.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The following architecture diagram places these layers together for easier understanding of Eve&apos;s system boundaries. The connections are synthesized from official &quot;runtime shape,&quot; &quot;channels,&quot; &quot;durability,&quot; and &quot;Agent Runs&quot; descriptions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    U[User or External System] --&gt; C[Channel&amp;#x3C;br/&gt;HTTP / Slack / Discord / GitHub / Custom]
    C --&gt; S[Session / Turn Runtime]
    S --&gt; W[Vercel Workflows&amp;#x3C;br/&gt;checkpoint &amp;#x26; replay]
    S --&gt; F[Vercel Functions&amp;#x3C;br/&gt;route + tool execution]
    S --&gt; M[AI Gateway&amp;#x3C;br/&gt;model routing]
    S --&gt; T[Tools]
    S --&gt; K[Skills]
    S --&gt; G[Subagents]
    T --&gt; X[Vercel Connect&amp;#x3C;br/&gt;OAuth / API keys / MCP / OpenAPI]
    T --&gt; B[Vercel Sandbox&amp;#x3C;br/&gt;files / shell / code]
    S --&gt; O[Agent Runs / OTel]
    C --&gt; R[NDJSON Stream / continuationToken / sessionId]
    R --&gt; U
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Overall, Eve is an Agent framework that leans toward a backend systems framework rather than a simple prompt/tool SDK. It treats Agents as long-running, recoverable, auditable, and authorized service objects. This is the fundamental distinction from many &quot;simplified agent loop&quot; libraries.&lt;/p&gt;
&lt;h2&gt;Programming Model and API&lt;/h2&gt;
&lt;p&gt;Eve&apos;s public TypeScript API is unified: you primarily define agent capabilities through a set of &lt;code&gt;define*&lt;/code&gt; helper functions, while identity comes from file paths, not a &lt;code&gt;name&lt;/code&gt; field written in code. The official TypeScript API documentation explicitly states that tool &lt;code&gt;agent/tools/get_weather.ts&lt;/code&gt; resolves to &lt;code&gt;get_weather&lt;/code&gt;, and connection &lt;code&gt;agent/connections/linear.ts&lt;/code&gt; resolves to &lt;code&gt;linear&lt;/code&gt;. This means the file path itself is part of the API.&lt;/p&gt;
&lt;p&gt;The most commonly used API surfaces include: &lt;code&gt;defineAgent&lt;/code&gt;, &lt;code&gt;defineTool&lt;/code&gt;, &lt;code&gt;defineSkill&lt;/code&gt;, &lt;code&gt;defineInstructions&lt;/code&gt;, &lt;code&gt;defineChannel&lt;/code&gt;, &lt;code&gt;eveChannel&lt;/code&gt;, &lt;code&gt;defineMcpClientConnection&lt;/code&gt;, &lt;code&gt;defineOpenAPIConnection&lt;/code&gt;, &lt;code&gt;defineSchedule&lt;/code&gt;, &lt;code&gt;defineHook&lt;/code&gt;, &lt;code&gt;defineSandbox&lt;/code&gt;, &lt;code&gt;defineEval&lt;/code&gt;, and the frontend binding &lt;code&gt;useEveAgent&lt;/code&gt;. Official documentation also lists several non-&lt;code&gt;define*&lt;/code&gt; helpers, such as &lt;code&gt;always&lt;/code&gt;/&lt;code&gt;once&lt;/code&gt;/&lt;code&gt;never&lt;/code&gt; approval strategies, &lt;code&gt;localDev&lt;/code&gt;/&lt;code&gt;vercelOidc&lt;/code&gt;/&lt;code&gt;placeholderAuth&lt;/code&gt; channel auth strategies, and default tool wrapping and disabling capabilities.&lt;/p&gt;
&lt;p&gt;One frequently overlooked but architecturally critical point: Eve ships with a &quot;default harness / default tool surface.&quot; From the official API listing, the framework&apos;s built-in wrappable or disableable default tools include &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;readFile&lt;/code&gt;, &lt;code&gt;writeFile&lt;/code&gt;, &lt;code&gt;glob&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;webFetch&lt;/code&gt;, &lt;code&gt;webSearch&lt;/code&gt;, &lt;code&gt;todo&lt;/code&gt;, and &lt;code&gt;loadSkill&lt;/code&gt;. This means Eve is not an &quot;empty orchestrator&quot; entering the runtime; it brings a strong default capability surface. Production setups must actively audit whether all these capabilities should be exposed to the model.&lt;/p&gt;
&lt;p&gt;Here is a minimal, runnable Eve Agent. It corresponds to the official quickstart minimum structure: &lt;code&gt;instructions.md&lt;/code&gt; + &lt;code&gt;agent.ts&lt;/code&gt; + one typed tool.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// agent/agent.ts
import { defineAgent } from &apos;eve&apos;;

export default defineAgent({
	model: &apos;anthropic/claude-sonnet-5&apos;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-md&quot;&gt;&amp;#x3C;!-- agent/instructions.md --&gt;

You are a concise weather demo assistant.
If the user asks about weather, clearly state that the data here is mock data.
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// agent/tools/get_weather.ts
import { defineTool } from &apos;eve/tools&apos;;
import { z } from &apos;zod&apos;;

export default defineTool({
	description: &apos;Returns mock weather data for a city.&apos;,
	inputSchema: z.object({
		city: z.string().min(1)
	}),
	async execute({ city }) {
		return {
			city,
			condition: &apos;Sunny&apos;,
			temperatureC: 24
		};
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These tools share key characteristics: inputs have schemas, return values must be JSON-serializable, and execution happens in the app runtime. The official tool documentation states that tools can import shared code from &lt;code&gt;lib/&lt;/code&gt;, read &lt;code&gt;process.env&lt;/code&gt;, and participate in Eve&apos;s durable pause/resume model; however, return values cannot be Dates, Maps, Sets, circular objects, or other unhandled structures.&lt;/p&gt;
&lt;p&gt;Eve also provides a highly practical &lt;code&gt;toModelOutput&lt;/code&gt; hook for trimming a tool&apos;s full output into a summary more suitable for the model, while keeping the full structure available for channels/UI/hooks. This design suits scenarios where &quot;the UI needs rich data but the model only needs a summary,&quot; such as Slack card rendering, chart data, or large database result sets.&lt;/p&gt;
&lt;p&gt;A simplified version looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// agent/tools/report_score.ts
import { defineTool } from &apos;eve/tools&apos;;
import { z } from &apos;zod&apos;;

export default defineTool({
	description: &apos;Generate a site score report.&apos;,
	inputSchema: z.object({
		domain: z.string()
	}),
	async execute({ domain }) {
		return {
			domain,
			score: 87,
			rawChecks: [
				{ name: &apos;seo&apos;, score: 90 },
				{ name: &apos;perf&apos;, score: 81 }
			]
		};
	},
	toModelOutput(output) {
		return {
			type: &apos;text&apos;,
			value: `Site ${output.domain} has a composite score of ${output.score}.`
		};
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Approvals are also a first-class concept in Eve&apos;s programming model. The official tool documentation provides approval strategies like &lt;code&gt;always()&lt;/code&gt;, and release articles demonstrate conditional approval based on input criteria. The semantics are: the tool call point durably pauses the session, waits for human approval, then resumes from exactly where it left off. This is significantly stronger than &quot;hanging a pending state in your own application code.&quot;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// agent/tools/refund_charge.ts
import { defineTool } from &apos;eve/tools&apos;;
import { always } from &apos;eve/tools/approval&apos;;
import { z } from &apos;zod&apos;;

export default defineTool({
	description: &apos;Process a refund.&apos;,
	inputSchema: z.object({
		chargeId: z.string(),
		amount: z.number().positive()
	}),
	approval: always(),
	async execute({ chargeId, amount }) {
		return { chargeId, refunded: amount };
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For frontend integration, Eve doesn&apos;t require you to separately maintain an agent service and a web service. The official frontend guides and templates show you can mount agents directly into web projects via &lt;code&gt;eve/next&lt;/code&gt;, &lt;code&gt;eve/sveltekit&lt;/code&gt; plugins, letting &lt;code&gt;useEveAgent&lt;/code&gt; initiate sessions and streaming interactions under the same-origin &lt;code&gt;/eve/v1/*&lt;/code&gt;; the Browser Agent Template also demonstrates &lt;code&gt;withEve()&lt;/code&gt; mounting the agent within the same Next.js service.&lt;/p&gt;
&lt;h2&gt;Lifecycle, Event Streams, Concurrency, and State&lt;/h2&gt;
&lt;p&gt;Eve&apos;s runtime core concepts are sessions and turns. The official Concepts documentation defines these clearly: a session is a persistent conversation/task launched by a channel or HTTP request; each user message or external event creates a turn; within a turn, the agent can call tools, load skills, read/write sandbox files, delegate to sub-agents, and stream lifecycle events back to the client.&lt;/p&gt;
&lt;p&gt;This is Eve&apos;s fundamental difference from traditional &quot;request/response&quot; chat interfaces. Both the official introduction article and documentation emphasize that an Eve session can stream-work, maintain durable state across multiple turns, pause on approvals/human replies, and resume in the future. The underlying mechanism relies on Vercel Workflows&apos; event log plus deterministic replay: progress is persisted as an event log, and upon recovery, previously recorded steps are replayed to rebuild state. This means it can continue across cold starts, deployment switches, long waits for messages, or tool results.&lt;/p&gt;
&lt;p&gt;Eve exposes two important identifiers externally: &lt;code&gt;sessionId&lt;/code&gt; and &lt;code&gt;continuationToken&lt;/code&gt;. The official README explains that &lt;code&gt;sessionId&lt;/code&gt; is used for stream subscription and run inspection, while &lt;code&gt;continuationToken&lt;/code&gt; is the recovery handle for sending the next message in the same conversation on that surface. This separation design helps distinguish &quot;user-facing continuous sessions&quot; from &quot;platform-internal observable/recoverable objects.&quot;&lt;/p&gt;
&lt;p&gt;The following event stream diagram synthesizes official session/streaming, subagent, approval, and channel documentation to show Eve&apos;s request path from entry to completion, or mid-way pause and recovery:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;sequenceDiagram
    participant User as User/Platform Event
    participant Ch as Channel
    participant Rt as Eve Runtime
    participant Wf as Workflows
    participant Model as Model
    participant Tool as Tool/Sandbox/Connection
    participant Human as Approver

    User-&gt;&gt;Ch: Message / webhook / slash command
    Ch-&gt;&gt;Rt: Normalize input, start or resume session
    Rt-&gt;&gt;Wf: Record turn checkpoint
    Rt-&gt;&gt;Model: Inject instructions + skills + tools + history
    Model--&gt;&gt;Rt: Output text / tool calls / subagent calls
    Rt-&gt;&gt;Tool: Execute tool or subagent
    Tool--&gt;&gt;Rt: Result
    Rt-&gt;&gt;Wf: Record result, continue turn
    alt Approval Needed
        Rt-&gt;&gt;Wf: Park session
        Rt--&gt;&gt;Human: Wait for approval
        Human--&gt;&gt;Rt: Approve/Reject
        Rt-&gt;&gt;Wf: Resume session
    end
    Rt--&gt;&gt;Ch: NDJSON lifecycle event stream
    Ch--&gt;&gt;User: Text/card/message response
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For concurrency, Eve&apos;s key capability comes from subagents. The official Subagents documentation states: the built-in agent tool delegates tasks to &quot;a copy of the current agent&quot;; if the model issues multiple agent calls in one response, Eve executes that batch concurrently and lets the parent agent continue after all return. This makes Eve ideal for &quot;fixed small-batch task fan-out,&quot; such as querying multiple data sources in parallel, organizing multiple documents in parallel, or validating multiple hypotheses in parallel.&lt;/p&gt;
&lt;p&gt;However, Eve&apos;s concurrency is not an &quot;unlimited DAG scheduler.&quot; The official documentation explicitly states a default subagent depth limit of 3 child sessions, adjustable via &lt;code&gt;limits.maxSubagentDepth&lt;/code&gt;; beyond this limit, the framework stops exposing further subagent tools to the model, and even if a call forcibly reaches the execution layer, it will be rejected. This indicates Eve&apos;s concurrency/recursion model is a controlled tree-like session expansion, not an arbitrary graph runtime.&lt;/p&gt;
&lt;p&gt;For state management, Eve requires understanding in three layers. The first is durable session state: guaranteed by Workflows, persisting across turns and pause/resume. The second is sandbox filesystem state: built-in agent subagents share the sandbox with the parent agent, and file writes become immediately visible to the parent; declared subagents default to their own sandbox boundaries. The third is authored state / &lt;code&gt;defineState&lt;/code&gt; context: the official documentation explicitly states that &lt;code&gt;defineState&lt;/code&gt; is not shared between parent and child agents, and subagents always start from fresh durable state.&lt;/p&gt;
&lt;p&gt;This means production setups must pay special attention to two boundary types:&lt;/p&gt;
&lt;p&gt;First, shared sandboxes introduce concurrent write collision risk. The official documentation explicitly recommends providing non-overlapping write scopes for parallel child tasks. If you let multiple built-in agent subagents write to the same file or directory simultaneously, non-deterministic collisions are easy to encounter.&lt;/p&gt;
&lt;p&gt;Second, declared subagents don&apos;t inherit root authored slots. Except for the built-in copy mode, a declared subagent won&apos;t automatically inherit the parent&apos;s instructions, tools, connections, skills, or sandbox; missing items fall back to framework defaults, not the root version. In other words, Eve&apos;s declared subagents are more like &quot;local independent agent packages.&quot; This brings stronger isolation but requires you to explicitly replicate or extract shared capabilities.&lt;/p&gt;
&lt;p&gt;Regarding replay and side effects, the official tool documentation emphasizes: completed steps do not re-run; Eve replays recorded results; but steps interrupted during execution will re-execute. Therefore any non-idempotent side effects — sending emails, charging fees, processing refunds, writing to external systems — must be designed idempotently or placed under approval/transactional protection. This is one of the most important traps in Eve production design.&lt;/p&gt;
&lt;h2&gt;Deployment, Scaling, Security, Observability, and Cost on Vercel&lt;/h2&gt;
&lt;p&gt;On the Vercel platform, Eve&apos;s deployment model is straightforward: the framework compiles agents into applications running on Vercel Functions, with Functions handling session requests, stream attachment, channel webhooks, and tool execution; while session/turn/subagent progress is persisted by Vercel Workflows. Official templates and frontend integration documentation further indicate that Eve can be combined with Next.js/SvelteKit web apps into a single project and single deployment, avoiding separate maintenance of agent services.&lt;/p&gt;
&lt;p&gt;From a scaling perspective, Eve borrows Vercel platform capabilities rather than implementing its own cluster scheduler. The Concepts document states that agents run on Functions on Vercel, and because turns may run long and require incremental streaming output, Eve benefits from Fluid Compute enabled by default; meanwhile, what truly determines &quot;sustained long execution&quot; is Workflows&apos; checkpoint/replay, not a long-lived process.&lt;/p&gt;
&lt;p&gt;This also means Eve&apos;s scaling characteristics resemble a &quot;serverless + durable orchestration&quot; combination rather than traditional resident workers: short workloads handled by Functions throughput, long processes persistently saved and restored by Workflows. For production teams, this model typically brings stronger recovery and lower operational burden, but it also means you need to put performance analysis on dimensions like turn count, tool count, stream chunk count, and sandbox usage, rather than just looking at single-machine QPS.&lt;/p&gt;
&lt;h3&gt;Security and Permissions&lt;/h3&gt;
&lt;p&gt;Eve has several default security premises. First, model access goes through AI Gateway, which on Vercel can use OIDC instead of directly managing provider API keys; the AI Gateway documentation also states that every request requires authentication, supporting API keys or OIDC, and Bring Your Own Key.&lt;/p&gt;
&lt;p&gt;Second, the sandbox as an isolation boundary is crucial. Vercel Sandbox documentation defines it as a compute primitive for safely running untrusted or user-generated code; Eve&apos;s release article further explains that agent-generated code doesn&apos;t enter the application runtime but executes in a sandbox within an independent security context; on Vercel, it uses ephemeral microVMs.&lt;/p&gt;
&lt;p&gt;Third, the default HTTP channel is fail-closed. The official frontend guide writes clearly: if you don&apos;t customize &lt;code&gt;agent/channels/eve.ts&lt;/code&gt;, the default registers &lt;code&gt;eveChannel({ auth: [vercelOidc(), localDev()] })&lt;/code&gt; — meaning it prioritizes accepting Vercel invocations and local development traffic, returning 401 for everything else. Only public demos and similar scenarios should explicitly use &lt;code&gt;none()&lt;/code&gt; to relax authentication.&lt;/p&gt;
&lt;p&gt;Additionally, Vercel Connect provides a solid credential governance foundation for Eve&apos;s external integrations. The official Connect documentation states that Connect supports Custom OAuth/OIDC + PKCE and API key storage; its &quot;Concepts&quot; documentation also describes triggers: third-party inbound webhooks are verified by Vercel Connect and forwarded to your project. This is particularly valuable for Slack, GitHub, SaaS webhooks, and multi-tenant integrations.&lt;/p&gt;
&lt;p&gt;But Eve&apos;s official documentation also gives one very important warning: without additional stricter configuration, Eve may run under quite permissive default conditions, including tools executing directly without explicit approval requirements and sandbox network egress not being deny-all. Eve explicitly requires deployers to configure their own guardrails for approval strategies, tool limits, connection scopes, route/session authorization, sandbox controls, and telemetry exports.&lt;/p&gt;
&lt;h3&gt;Observability&lt;/h3&gt;
&lt;p&gt;Observability is where Eve looks most like a &quot;productized backend framework.&quot; The official Observability documentation states that every Eve project gets Agent Runs by default: without a separate &lt;code&gt;instrumentation.ts&lt;/code&gt;, you can see in the Vercel Dashboard runs broken down by trigger type, token input/output/cache volumes, turn counts, durations, and per-turn details including tool calls, reasoning, and timing.&lt;/p&gt;
&lt;p&gt;If you need integration with your company&apos;s existing tracing体系, Eve also supports registering OpenTelemetry exporters in &lt;code&gt;agent/instrumentation.ts&lt;/code&gt;. The official example demonstrates a Braintrust exporter and states that any OTel-compatible backend can be connected, such as Honeycomb, Datadog, Jaeger, etc. Since the instrumentation file runs automatically before agent startup and any agent code, it&apos;s also suitable for unified telemetry initialization.&lt;/p&gt;
&lt;p&gt;Note that the official documentation simultaneously reminds: since Agent Runs captures session, reasoning, tool input/output, and other runtime information, if processing personal, sensitive, or regulated data, deployers may need to explain these collection behaviors in privacy materials and legal disclosures. In other words, the stronger the observability, the greater the compliance responsibility.&lt;/p&gt;
&lt;h3&gt;Cost Considerations&lt;/h3&gt;
&lt;p&gt;Eve is not a single billing item but a composite cost surface. The official Pricing document lists billable resources including: Vercel Functions, Vercel Workflows, Vercel Sandbox, AI Gateway, and underlying model providers. Common cost drivers include session/turn counts, prompt and output tokens, tool calls, stream writes to persistence, and sandbox execution/snapshot/network traffic.&lt;/p&gt;
&lt;p&gt;The table below compresses Eve&apos;s main cost surfaces into a practical perspective:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost Surface&lt;/th&gt;
&lt;th&gt;When It Increases&lt;/th&gt;
&lt;th&gt;Typical Signal&lt;/th&gt;
&lt;th&gt;Control Measures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model tokens&lt;/td&gt;
&lt;td&gt;Long history, large tool returns, long reasoning&lt;/td&gt;
&lt;td&gt;Rising input/output/cached tokens in Agent Runs&lt;/td&gt;
&lt;td&gt;Shorten history, trim tool output, load long flows into skills on-demand, use smaller models for low-risk tasks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow events/storage&lt;/td&gt;
&lt;td&gt;Multi-turn, multi-stream chunks, multi-tool calls&lt;/td&gt;
&lt;td&gt;High turn count, many stream chunks&lt;/td&gt;
&lt;td&gt;Merge meaningless intermediate output, split long tasks, reduce meaningless streaming.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Functions duration&lt;/td&gt;
&lt;td&gt;Slow external APIs, heavy tool logic&lt;/td&gt;
&lt;td&gt;Elevated single-turn duration&lt;/td&gt;
&lt;td&gt;Offload heavy CPU/untrusted tasks to sandbox; optimize external API calls.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sandbox cost&lt;/td&gt;
&lt;td&gt;Code writing/command running/snapshots/network access&lt;/td&gt;
&lt;td&gt;Frequent sandbox usage&lt;/td&gt;
&lt;td&gt;Enable sandbox only for necessary tasks, limit network policies and lifecycles.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-party service cost&lt;/td&gt;
&lt;td&gt;SaaS APIs, MCP, databases&lt;/td&gt;
&lt;td&gt;Rising external platform bills&lt;/td&gt;
&lt;td&gt;Tool-level caching, idempotent retries, connection scope minimization.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A very practical suggestion: don&apos;t first calculate &quot;roughly how much per month,&quot; but instead run a representative task profile. The official Pricing document recommends recording: turn count per task, model/tool call count per turn, token input/output/cache volume, stream data volume, and whether sandbox, snapshots, networking, and long-term persistence were used, then mapping to platform product billing items. This is a more reliable approach than &quot;guessing by feel.&quot;&lt;/p&gt;
&lt;h2&gt;Integration Methods, Patterns, and Minimal Runnable Examples&lt;/h2&gt;
&lt;p&gt;Eve&apos;s integration methods can be summarized in three threads: channel access, external capability access, and application-layer persistence access. The official documentation shows that channels are entry adaptation layers, connections are external capability directories, and tools are arbitrary business logic executed in the app runtime; in other words, Eve&apos;s attitude toward &quot;integration&quot; is not giving you one super unified bus, but distributing integration to the appropriate layers.&lt;/p&gt;
&lt;h3&gt;Webhooks and Multi-Channel&lt;/h3&gt;
&lt;p&gt;The official Channels document defines a channel as a platform-to-agent edge adapter: it&apos;s responsible for normalizing platform input into user messages, holding the continuationToken, and deciding how responses are sent back. Besides the default HTTP channel, Eve has built-in platform channels for Slack, Discord, Teams, Telegram, Twilio, GitHub, and Linear, and allows custom webhook/WebSocket adaptation layers via &lt;code&gt;defineChannel&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you just want to expose the Agent as an HTTP API, you can use the officially provided &lt;code&gt;/eve/v1/session&lt;/code&gt; and &lt;code&gt;/eve/v1/session/:id/stream&lt;/code&gt; routes locally. The official documentation gives the simplest interaction method as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -X POST http://127.0.0.1:3000/eve/v1/session \
  -H &apos;content-type: application/json&apos; \
  -d &apos;{&quot;message&quot;:&quot;Please summarize this repository&quot;}&apos;

# After getting x-eve-session-id from the response header:
curl http://127.0.0.1:3000/eve/v1/session/&amp;#x3C;sessionId&gt;/stream
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you want to deploy the Web frontend and Agent as one project, the official frontend guides and templates demonstrate the simplest usage of &lt;code&gt;useEveAgent&lt;/code&gt;. The following approach comes from the official SvelteKit guide; the React/Vue approach is the same: components only need to call &lt;code&gt;useEveAgent()&lt;/code&gt;, without maintaining an independent Agent Host.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// Pseudocode, concept consistent with official Svelte example
import { useEveAgent } from &apos;eve/svelte&apos;;

const agent = useEveAgent();

await agent.send({
	message: &apos;Help me summarize the alert trends for the last 7 days&apos;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Database and Application-Layer Persistence&lt;/h3&gt;
&lt;p&gt;Eve is not a database framework, but it integrates with databases easily. The official tool documentation explicitly states that tool execution happens in the app runtime, so it can import from &lt;code&gt;lib/&lt;/code&gt;, read &lt;code&gt;process.env&lt;/code&gt;, and connect to any database or backend. The official chat template documentation further demonstrates common practice: the browser interacts with the agent via same-origin &lt;code&gt;/eve/v1/*&lt;/code&gt;, and streaming events are persisted to Postgres upon arrival, maintaining a session cursor for interruption recovery; the template stack explicitly uses Neon, Drizzle, Better Auth, and Upstash Redis.&lt;/p&gt;
&lt;p&gt;This also explains Eve&apos;s best practice on databases: put strong transactions, record persistence, and session metadata storage at the application layer or tool layer, rather than expecting Eve&apos;s core to provide a universal ORM/memory store abstraction. This conclusion is a reasonable inference based on the design orientation of official templates and core documentation.&lt;/p&gt;
&lt;p&gt;Also note a Vercel platform-level change: the official Postgres documentation states that Vercel Postgres is no longer offered, existing instances have been migrated to Neon, and new projects are advised to connect external Postgres through the Marketplace. This means when doing production databases with Eve on Vercel, you&apos;ll likely use Neon or external PG rather than a &quot;platform-built-in database.&quot;&lt;/p&gt;
&lt;h3&gt;Third-Party APIs, MCP, and OpenAPI&lt;/h3&gt;
&lt;p&gt;Eve&apos;s preferred integration point for third-party capabilities is &lt;code&gt;connections/&lt;/code&gt;. The release article states that a connection file can point to an MCP server or any OpenAPI-compatible API; Eve discovers remote tools, proxies authentication, and never exposes connection URLs and credentials to the model. The official TypeScript API also explicitly includes &lt;code&gt;defineMcpClientConnection&lt;/code&gt; and &lt;code&gt;defineOpenAPIConnection&lt;/code&gt; as two definition functions.&lt;/p&gt;
&lt;p&gt;A minimal MCP connection example is almost a linear version of the official blog post:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// agent/connections/linear.ts
import { defineMcpClientConnection } from &apos;eve/connections&apos;;

export default defineMcpClientConnection({
	url: &apos;https://mcp.linear.app/sse&apos;,
	description: &apos;Linear workspace: issues, projects, cycles, comments.&apos;,
	auth: {
		getToken: async () =&gt; ({ token: process.env.LINEAR_API_TOKEN! })
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you need user-level authorization without handling OAuth details yourself, leveraging Vercel Connect is more recommended. The official Connect documentation states it supports OAuth/OIDC with PKCE, API key storage, project links, and verified webhook triggers; while Eve documentation suggests pairing tools with Connect in delegated user/team credential scenarios.&lt;/p&gt;
&lt;h3&gt;Scheduled Tasks and Background Mode&lt;/h3&gt;
&lt;p&gt;Eve&apos;s scheduled task capability comes from &lt;code&gt;agent/schedules/&lt;/code&gt;. Each schedule is a single file with a cron, which can be pure markdown task mode or a &lt;code&gt;run({ receive, waitUntil, appAuth })&lt;/code&gt; handler mode. The official documentation explicitly states: on Vercel, each schedule becomes a Vercel Cron Job, and cron expressions are interpreted in UTC.&lt;/p&gt;
&lt;p&gt;Here is a minimal runnable handler schedule: it delivers a message to a Slack channel every minute.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// agent/schedules/heartbeat.ts
import { defineSchedule } from &apos;eve/schedules&apos;;
import slack from &apos;../channels/slack.js&apos;;

export default defineSchedule({
	cron: &apos;* * * * *&apos;,
	async run({ receive, waitUntil, appAuth }) {
		waitUntil(
			receive(slack, {
				message: &apos;Check if there are new critical alerts; if not, send nothing.&apos;,
				target: { channelId: &apos;C0123ABC&apos; },
				auth: appAuth
			})
		);
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A very key limitation: markdown task-mode schedules cannot park to wait for approval or OAuth login; only the handler form can continue with durable runtime semantics after handoff. If planned tasks might encounter human approval or user authorization in production, this must be designed upfront.&lt;/p&gt;
&lt;h2&gt;Common Usage Patterns&lt;/h2&gt;
&lt;p&gt;Combining official templates and documentation, I believe Eve is best suited for the following patterns:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Why It Fits Eve&lt;/th&gt;
&lt;th&gt;Representative Resources&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web Chat + Durable Backend&lt;/td&gt;
&lt;td&gt;Same-origin &lt;code&gt;/eve/v1/*&lt;/code&gt;, co-deployed frontend/backend, recoverable sessions&lt;/td&gt;
&lt;td&gt;Eve Chat Template, Browser Agent Template&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slack/Team Assistant&lt;/td&gt;
&lt;td&gt;Channels are first-class concepts, support cards and approvals&lt;/td&gt;
&lt;td&gt;Slack starter, content assistant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approval-Driven Operations/Internal Tools&lt;/td&gt;
&lt;td&gt;Tool approvals durably pause/resume&lt;/td&gt;
&lt;td&gt;Tools approval docs, release article&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser/Code/File Workflows&lt;/td&gt;
&lt;td&gt;Each agent ships with a sandbox, suitable for ad-hoc scripts and file artifacts&lt;/td&gt;
&lt;td&gt;Official release article, Browser Agent Template&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduled Inspection/Daily Reports/Auto Triage&lt;/td&gt;
&lt;td&gt;Schedules compile directly into Vercel Cron Jobs&lt;/td&gt;
&lt;td&gt;Schedules documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Comparison with Alternative Frameworks&lt;/h2&gt;
&lt;p&gt;As of this writing, there is no official standardized benchmark comparing Eve with other mainstream Agent frameworks. Therefore the following &quot;performance/throughput&quot; assessments are not lab benchmarks but qualitative analyses based on each framework&apos;s official documentation describing execution models, persistence semantics, deployment methods, and built-in capabilities. I will explicitly mark these as architectural inferences rather than official benchmarks.&lt;/p&gt;
&lt;h3&gt;Overall Comparison&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Eve&lt;/th&gt;
&lt;th&gt;LangGraph&lt;/th&gt;
&lt;th&gt;OpenAI Agents SDK&lt;/th&gt;
&lt;th&gt;Mastra&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Design Center&lt;/td&gt;
&lt;td&gt;Filesystem-first, agent is a directory; production capabilities built-in&lt;/td&gt;
&lt;td&gt;Graph/state-machine-first, low-level orchestration runtime&lt;/td&gt;
&lt;td&gt;SDK-first, agents/runs/handoffs/sessions defined in code&lt;/td&gt;
&lt;td&gt;TypeScript AI application framework, agents/workflows/memory equally emphasized&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Durable Execution&lt;/td&gt;
&lt;td&gt;Built-in, based on Vercel Workflows&lt;/td&gt;
&lt;td&gt;Strong suit,主打 durable execution/persistence&lt;/td&gt;
&lt;td&gt;SDK manages turns/tools/sessions; also supports sandbox agents&lt;/td&gt;
&lt;td&gt;Has durable agents, but docs still label Beta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrency &amp;#x26; Multi-Agent&lt;/td&gt;
&lt;td&gt;Built-in subagents, folder-style specialists, default depth limits&lt;/td&gt;
&lt;td&gt;Most flexible for complex orchestration with graph nodes and state transitions&lt;/td&gt;
&lt;td&gt;Strong handoffs/specialists, ideal for OpenAI-native runtimes&lt;/td&gt;
&lt;td&gt;Composable workflows, memory, multi-agent patterns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Channels/Multi-Surface&lt;/td&gt;
&lt;td&gt;Built-in HTTP + multi-platform channels + custom channels&lt;/td&gt;
&lt;td&gt;Typically requires self-integration of Web/Slack surfaces&lt;/td&gt;
&lt;td&gt;Primarily SDK/runtime semantics, channel layer needs app-level integration&lt;/td&gt;
&lt;td&gt;More app-framework oriented, deploys anywhere, but channels aren&apos;t a first-class abstraction like Eve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Platform Binding&lt;/td&gt;
&lt;td&gt;Strong, Vercel-native best&lt;/td&gt;
&lt;td&gt;Relatively neutral&lt;/td&gt;
&lt;td&gt;Most friendly to OpenAI ecosystem, but can pair with other providers&lt;/td&gt;
&lt;td&gt;Deploys anywhere, stronger framework neutrality&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer Experience&lt;/td&gt;
&lt;td&gt;Very efficient for Vercel users; clear directory structure; many conventions&lt;/td&gt;
&lt;td&gt;Flexible but lower-level, higher learning curve&lt;/td&gt;
&lt;td&gt;Direct and natural for SDK users; more code-centric&lt;/td&gt;
&lt;td&gt;Strong TypeScript full-stack feel; broad feature surface, but system boundaries more dispersed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Design Philosophy and Developer Experience&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Eve vs LangGraph&lt;/strong&gt;: LangGraph officially positions itself as a low-level orchestration framework and runtime, focusing on durable execution, streaming, HITL, and persistence; while Eve is more of a &quot;framework-definition product&quot; that brings conventions, file layout, channels, and platform integrations together. If you want precise control over state graphs, nodes, back-edges, and custom scheduling, LangGraph is freer; if you want to quickly deploy a multi-channel, recoverable, sandbox-equipped agent, Eve&apos;s path is shorter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Eve vs OpenAI Agents SDK&lt;/strong&gt;: The official OpenAI documentation clearly distinguishes the Responses API from the Agents SDK, the latter being suitable when applications need the SDK to handle orchestration, tool execution, approvals, state, and sessions. It&apos;s a very &quot;SDK/code-first&quot; design, while Eve is &quot;directory/framework-first.&quot; If your capabilities heavily depend on OpenAI-native tools, container execution, realtime/voice agents, and the tracing ecosystem, OpenAI Agents SDK&apos;s integrated experience will be strong; but if you value Web/Slack/GitHub multi-entry unification, Vercel deployment, and platform governance more, Eve is more convenient.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Eve vs Mastra&lt;/strong&gt;: Mastra officially emphasizes itself as an open-source TypeScript AI framework providing agents, workflows, memory, workspaces, and observability, deployable to various frameworks and standalone servers. In contrast, Eve has a narrower framework boundary and stronger platform binding, but does &quot;condensing production Agent shapes into a directory&quot; more thoroughly. Mastra is attractive for teams wanting to unify agents + workflows + memory + apps; Eve is better suited for treating &quot;durable agent backends&quot; as separate product objects to govern.&lt;/p&gt;
&lt;h3&gt;Performance and Runtime Trade-offs&lt;/h3&gt;
&lt;p&gt;If looking only at single-turn, short-path, light-tool scenarios, Eve&apos;s Workflow persistence, stream writes, and Agent Runs collection bring additional control surface costs; in such scenarios, using the Responses API directly, OpenAI Agents SDK, or lightweight LangGraph graphs could theoretically have lower runtime overhead. This is an architectural inference based on official descriptions of Eve&apos;s Workflow persistence, stream persistence, and multi-layer billing resources.&lt;/p&gt;
&lt;p&gt;But if the task is long-running, interruptible, requiring approvals, needing multi-turn recovery, needing sandboxes or subagent fan-out, Eve&apos;s built-in durable model often offsets the complexity these additional overheads bring: you don&apos;t need to implement replay, pause/resume, stream reconnection, auditing, and channel glue code yourself. In other words, Eve&apos;s advantage isn&apos;t &quot;fastest,&quot; but &quot;making high-complexity production semantics the default.&quot;&lt;/p&gt;
&lt;h3&gt;When to Choose Which&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your Primary Need&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;I&apos;m on Vercel, need a shippable durable agent backend with Web/Slack/approvals/observability&lt;/td&gt;
&lt;td&gt;Eve&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I need fine-grained control over state graphs, branching, and custom orchestration&lt;/td&gt;
&lt;td&gt;LangGraph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I deeply use OpenAI platform-native tools/sandbox/realtime&lt;/td&gt;
&lt;td&gt;OpenAI Agents SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I want a TypeScript full-stack AI framework with agents/workflows/memory unified&lt;/td&gt;
&lt;td&gt;Mastra&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Limitations, Pitfalls, Troubleshooting, Ecosystem, and Production Adoption Advice&lt;/h2&gt;
&lt;h3&gt;Known Limitations and Common Pitfalls&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Eve is still Beta/Preview.&lt;/strong&gt; This means APIs, behaviors, and documentation may change before GA. If your organization has strict requirements for platform stability, long-cycle support, or compliance auditing, Eve should be treated as &quot;production-capable pilot, not zero-constraint full rollout.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strong platform binding.&lt;/strong&gt; Although official documentation includes self-host / &lt;code&gt;eve build &amp;#x26;&amp;#x26; eve start&lt;/code&gt; instructions, Eve&apos;s smoothest capability composition clearly occurs on the Vercel platform: AI Gateway OIDC, Functions, Workflows, Sandbox, Connect, and Agent Runs are all key components. Running outside Vercel is possible but increases mental model and operational complexity. This judgment comes from official product combinations and Vercel-specific integration documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Large default capability surface.&lt;/strong&gt; The official documentation explicitly lists default tools including bash, file read/write, webFetch, webSearch, todo, loadSkill, and the warning that &quot;without additional controls, tool execution may be permissive and sandbox networking may not be deny-all.&quot; Therefore Eve cannot rely solely on instructions hoping the model &quot;won&apos;t misbehave&quot;; you must close the aperture from four layers simultaneously: auth, approval, tools, connections, and sandbox policy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Concurrent fan-out easily introduces shared write collisions.&lt;/strong&gt; If you run multiple subtasks in parallel with the built-in agent tool, they share the parent agent&apos;s sandbox and tool surface, and writing the same path causes non-deterministic overwrites. The official documentation explicitly recommends providing non-overlapping write scopes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Non-idempotent tools may re-run after interruption.&lt;/strong&gt; The official tool documentation has explained this very clearly. In production, charging, notifications, writing to external systems must introduce idempotency keys, state locks, or approvals.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Two typical pitfalls with scheduled tasks:&lt;/strong&gt; Vercel Cron interprets expressions in UTC; and markdown task-mode schedules cannot wait for approval/OAuth. Additionally, custom hosting without properly starting the Nitro schedule runner may result in &quot;tasks compiled but not auto-triggered.&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Subagent naming conflicts and depth limits.&lt;/strong&gt; Subagent tool names share the same runtime tool namespace as regular tools; if &lt;code&gt;subagents/researcher&lt;/code&gt; and &lt;code&gt;tools/researcher.ts&lt;/code&gt; have the same name, the build will fail; the default depth limit is also 3 child sessions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Limited official Chinese resources.&lt;/strong&gt; As of this writing, Vercel&apos;s official Eve documentation and Knowledge Base are primarily in English; Chinese content mostly comes from community interpretations and reposts with varying quality. Chinese-language teams should treat official English docs + repository docs as the primary source, with Chinese content as supplementary material.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Troubleshooting Guide&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem Symptom&lt;/th&gt;
&lt;th&gt;Priority Check&lt;/th&gt;
&lt;th&gt;Basis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New files not recognized by Eve&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;eve info&lt;/code&gt;, check discovery diagnostics and &lt;code&gt;.eve/&lt;/code&gt; artifacts; confirm file path is in the correct slot&lt;/td&gt;
&lt;td&gt;Official Project Layout recommends &lt;code&gt;eve info&lt;/code&gt; for discovery failures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser frontend gets 401&lt;/td&gt;
&lt;td&gt;Check &lt;code&gt;agent/channels/eve.ts&lt;/code&gt; auth; default is &lt;code&gt;vercelOidc()&lt;/code&gt; + &lt;code&gt;localDev()&lt;/code&gt;, not public&lt;/td&gt;
&lt;td&gt;Official frontend guide states default eve channel is fail-closed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Subagent can&apos;t access parent tools/skills&lt;/td&gt;
&lt;td&gt;Expected behavior for declared subagents; they don&apos;t inherit root authored slots&lt;/td&gt;
&lt;td&gt;Official Subagents documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool return value causes exceptions&lt;/td&gt;
&lt;td&gt;Check if output is JSON-serializable; avoid Date/Map/Set/NaN/circular objects&lt;/td&gt;
&lt;td&gt;Official Tools documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduled tasks don&apos;t trigger in local dev&lt;/td&gt;
&lt;td&gt;&lt;code&gt;eve dev&lt;/code&gt; doesn&apos;t auto-trigger on cron; use dev dispatch route or built app&lt;/td&gt;
&lt;td&gt;Official Schedules documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedule doesn&apos;t execute in self-hosted production&lt;/td&gt;
&lt;td&gt;Confirm whether you actually ran &lt;code&gt;eve start&lt;/code&gt;/Nitro scheduler, not just provided HTTP&lt;/td&gt;
&lt;td&gt;Official Schedules documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sensitive actions still potentially callable&lt;/td&gt;
&lt;td&gt;Subagent isolation is not an approval boundary; use approval, connection approval, route/session auth&lt;/td&gt;
&lt;td&gt;Official Subagents and safeguards documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Ecosystem, Maturity, and Recommended Resources&lt;/h3&gt;
&lt;p&gt;Eve&apos;s ecosystem is rapidly forming. Official and official-related resources currently include at minimum: core repository, Vercel Docs, Vercel Blog/Changelog, Knowledge Base, and multiple open-source templates. The GitHub repository has approximately 3.2k stars and 252 forks as of this writing, with active signals in Issues, PRs, and Discussions.&lt;/p&gt;
&lt;p&gt;Recommended resources, read in &quot;official first, then templates, then community&quot; priority order:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Priority&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Eve Overview Docs&lt;/td&gt;
&lt;td&gt;Framework overview, platform mapping, minimal example&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concepts&lt;/td&gt;
&lt;td&gt;Core mental model for sessions/turns, durability, channels, sandbox, subagents&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript API&lt;/td&gt;
&lt;td&gt;Authoritative entry for define*, ctx, import paths&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project Layout&lt;/td&gt;
&lt;td&gt;File slots, root/subagent boundaries, debugging entry&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools / Subagents / Schedules Docs&lt;/td&gt;
&lt;td&gt;Production-grade feature details and pitfalls&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability / Pricing Docs&lt;/td&gt;
&lt;td&gt;Core basis for monitoring and cost control post-launch&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Official Release Article: Introducing Eve&lt;/td&gt;
&lt;td&gt;Most comprehensive design philosophy and end-to-end examples&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eve Chat Template&lt;/td&gt;
&lt;td&gt;Best practice for Web Chat + Postgres persistence&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eve Slack Agent / Content Agent Templates&lt;/td&gt;
&lt;td&gt;Team assistants, content workflows, Connect/OAuth integration patterns&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser Agent Template&lt;/td&gt;
&lt;td&gt;Web Chat + browser agent + single-project deployment paradigm&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chinese Community Interpretations&lt;/td&gt;
&lt;td&gt;Supplementary understanding, but confirm back to official docs&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Production Adoption Recommendations&lt;/h3&gt;
&lt;p&gt;If you&apos;re asking &quot;is Eve production-ready,&quot; my conclusion is: yes, but on the premise that you accept it as a Vercel-native, strongly opinionated, still-Beta production Agent framework. For most teams already deeply using Vercel, I recommend evaluating Eve as the first-priority pilot framework, because its integration of durable execution, sandbox, channels, approvals, observability, and deployment is genuinely high.&lt;/p&gt;
&lt;p&gt;But &quot;pilot&quot; doesn&apos;t mean &quot;directly replace everything.&quot; The safest path for production adoption:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Recommended Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pilot&lt;/td&gt;
&lt;td&gt;Start with a single channel and single business line, e.g., internal Slack assistant, Web Chat retrieval assistant, PR triage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Governance&lt;/td&gt;
&lt;td&gt;Define auth, approval, sandbox egress, tool allowlist first; then write model instructions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Measurement&lt;/td&gt;
&lt;td&gt;Use Agent Runs as the primary lens for tokens, turns, tools, duration; integrate OTel if needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stabilization&lt;/td&gt;
&lt;td&gt;Add evaluations, CI, idempotency, and cost alerts; incorporate schedules and subagents deeply into operational boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Migration Checklist&lt;/h3&gt;
&lt;p&gt;If your existing system comes from LangGraph, custom agent loops, OpenAI Agents SDK, or other frameworks, here is a pragmatic migration checklist:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check Item&lt;/th&gt;
&lt;th&gt;Migration Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Agent identity and directory structure&lt;/td&gt;
&lt;td&gt;Map &quot;roles, tools, skills, channels, scheduled tasks, subagents&quot; to file slots under &lt;code&gt;agent/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool functions&lt;/td&gt;
&lt;td&gt;Wrap existing tools with &lt;code&gt;defineTool&lt;/code&gt;, add zod schemas, confirm output is JSON-serializable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions and sensitive operations&lt;/td&gt;
&lt;td&gt;Add approval or route/session auth for refunds, email sending, DB writes, production API calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompts/knowledge&lt;/td&gt;
&lt;td&gt;Split long instructions into &lt;code&gt;instructions.md&lt;/code&gt; + &lt;code&gt;skills/&lt;/code&gt;; avoid context bloat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;External APIs&lt;/td&gt;
&lt;td&gt;Migrate to &lt;code&gt;connections/&lt;/code&gt; + Connect at priority; at minimum strip credentials from prompt/tool text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long flows/multi-turn recovery&lt;/td&gt;
&lt;td&gt;Migrate logic previously maintained by custom state machines to session/turn thinking; identify pause/resume boundaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web/Slack entry points&lt;/td&gt;
&lt;td&gt;Prefer built-in channels; use &lt;code&gt;defineChannel&lt;/code&gt; only for custom surfaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend deployment&lt;/td&gt;
&lt;td&gt;If already using Next.js/Nuxt/SvelteKit, prioritize single-project mounting over dual services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduled tasks&lt;/td&gt;
&lt;td&gt;Clarify UTC cron, whether审批/OAuth may trigger, whether handler mode is needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Idempotency and rollback&lt;/td&gt;
&lt;td&gt;Design idempotency keys and compensation logic for all external side effects, since interrupted steps may re-run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observability and privacy&lt;/td&gt;
&lt;td&gt;Enable Agent Runs, integrate OTel if needed, and assess sensitive data tracking disclosure obligations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Final Recommendation&lt;/h2&gt;
&lt;p&gt;If your tech stack is centered around Vercel, my recommendation is clear: you can adopt Eve, but proceed as a &quot;production framework pilot&quot; rather than a &quot;prototype tool.&quot; Prioritize landing in internal assistants, content workflows, retrieval/knowledge assistants, PR triage, and browser/file-type agents; for financial, legal, medical, and external write-operation scenarios, must-frontload approvals, idempotency, auditing, and permissions as design constraints rather than post-launch patches. Comprehensive official documentation, templates, and platform capabilities indicate that Eve&apos;s greatest value isn&apos;t making Agents &quot;smarter,&quot; but making Agents more like genuinely operable backend systems.&lt;/p&gt;</content:encoded></item><item><title>Loop Engineering Harness：AI Agent 架构中的迭代引擎</title><link>https://lora-sys.github.io/loraSys/blog/loop-engineering-harness</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/loop-engineering-harness</guid><description>Loop Engineering Harness 是 AI Agent 架构中的核心控制框架，它定义了 Agent 在执行复杂任务时的迭代循环机制。</description><pubDate>Tue, 16 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;一、概念定义：什么是 Loop Engineering Harness&lt;/h2&gt;
&lt;p&gt;Loop Engineering Harness（循环工程 harness）是 AI Agent 架构中的&lt;strong&gt;核心控制框架&lt;/strong&gt;，它定义了 Agent 在执行复杂任务时的迭代循环机制——从感知环境、制定计划、执行动作到评估结果的完整闭环。&lt;/p&gt;
&lt;p&gt;与传统的线性流水线不同，Harness 强调的是&lt;strong&gt;有状态的持续迭代&lt;/strong&gt;：Agent 不是一次性输出结果，而是在多轮循环中不断修正、优化，直到满足终止条件。这种设计直接借鉴了软件工程中的&quot;Harness&quot;概念——为被测系统提供运行时环境、输入注入和结果捕获的基础设施。&lt;/p&gt;
&lt;p&gt;在 AI Agent 语境下，Harness 承担三个关键职责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;循环控制&lt;/strong&gt;：决定何时继续迭代、何时终止&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态管理&lt;/strong&gt;：维护跨轮次的上下文和记忆&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;反馈整合&lt;/strong&gt;：将执行结果转化为下一轮迭代的输入&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;二、设计原理：为什么需要循环工程&lt;/h2&gt;
&lt;h3&gt;2.1 复杂任务的本质需求&lt;/h3&gt;
&lt;p&gt;现实世界的任务很少能在单次推理中完成。以代码生成为例：Agent 需要理解需求、编写代码、运行测试、修复错误、优化性能——每一步都可能产生新的信息，改变后续决策。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;传统线性流程：输入 → 处理 → 输出（无反馈）
Harness 循环：输入 → 计划 → 执行 → 评估 → 反馈 → 再计划 → ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.2 核心设计原则&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;原则&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;有界迭代&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;设置最大循环次数，防止无限循环&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;状态可追溯&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;每轮状态可序列化，支持断点恢复&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;反馈驱动&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;执行结果直接影响下一轮决策&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;可观测性&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;循环过程对开发者透明，便于调试&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2.3 终止条件设计&lt;/h3&gt;
&lt;p&gt;Harness 必须明确定义循环退出的条件，常见策略包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;目标达成&lt;/strong&gt;：任务指标满足预设阈值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;预算耗尽&lt;/strong&gt;：达到最大迭代次数或 token 上限&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;收敛检测&lt;/strong&gt;：连续多轮输出无显著变化&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工干预&lt;/strong&gt;：外部信号强制终止&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、核心组件架构&lt;/h2&gt;
&lt;h3&gt;3.1 组件总览&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────┐
│              Loop Engineering Harness         │
│                                               │
│  ┌──────────┐  ┌──────────┐  ┌────────────┐ │
│  │  Planner  │→ │ Executor │→ │ Evaluator  │ │
│  │  (规划器) │  │ (执行器) │  │ (评估器)   │ │
│  └──────────┘  └──────────┘  └────────────┘ │
│       ↑                            │          │
│       └──────── 反馈回路 ──────────┘          │
│                                               │
│  ┌──────────────────────────────────────────┐ │
│  │         State Manager (状态管理器)         │ │
│  └──────────────────────────────────────────┘ │
│  ┌──────────────────────────────────────────┐ │
│  │       Termination Judge (终止判断器)       │ │
│  └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3.2 各组件详解&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Planner（规划器）&lt;/strong&gt;：根据当前状态和目标，生成下一步行动计划。它接收来自 Evaluator 的反馈，动态调整策略。在实现中，Planner 通常是一个 LLM 调用，prompt 包含历史上下文和上一轮评估结果。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Executor（执行器）&lt;/strong&gt;：将 Planner 产出的计划转化为具体动作——调用工具、执行代码、查询数据库或生成内容。Executor 是 Agent 与外部世界交互的桥梁。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Evaluator（评估器）&lt;/strong&gt;：对执行结果进行质量评估，判断是否达成子目标，识别错误和偏差。评估可以是规则化的（如测试用例通过率）或模型驱动的（如 LLM-as-Judge）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;State Manager（状态管理器）&lt;/strong&gt;：维护整个循环的状态——包括任务进度、历史动作、中间结果和上下文窗口。它是实现&quot;有状态迭代&quot;的关键。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Termination Judge（终止判断器）&lt;/strong&gt;：基于预设规则和当前状态，判断是否应该退出循环。&lt;/p&gt;
&lt;h2&gt;四、在 AI Agent 架构中的关键作用&lt;/h2&gt;
&lt;h3&gt;4.1 从&quot;工具调用&quot;到&quot;自主迭代&quot;&lt;/h3&gt;
&lt;p&gt;早期的 Function Calling 模式是单轮的：模型决定调用哪个工具，获取结果后输出。Harness 将其升级为&lt;strong&gt;多轮自主迭代&lt;/strong&gt;，使 Agent 具备真正的&quot;尝试-失败-重试&quot;能力。&lt;/p&gt;
&lt;h3&gt;4.2 工程化价值&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;无 Harness&lt;/th&gt;
&lt;th&gt;有 Harness&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;可靠性&lt;/td&gt;
&lt;td&gt;单次失败即终止&lt;/td&gt;
&lt;td&gt;自动重试与修正&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可调试性&lt;/td&gt;
&lt;td&gt;黑盒输出&lt;/td&gt;
&lt;td&gt;每轮状态可追溯&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可控性&lt;/td&gt;
&lt;td&gt;无法干预&lt;/td&gt;
&lt;td&gt;支持人工介入点&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可扩展性&lt;/td&gt;
&lt;td&gt;硬编码流程&lt;/td&gt;
&lt;td&gt;模块化组件替换&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;4.3 典型应用场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;自动化测试修复&lt;/strong&gt;：Agent 编写测试 → 运行 → 分析失败 → 修复代码 → 重跑&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据分析管道&lt;/strong&gt;：探索数据 → 发现异常 → 清洗 → 重新分析&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;文档生成&lt;/strong&gt;：起草 → 审查 → 修订 → 定稿&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;五、最小化实现示例&lt;/h2&gt;
&lt;p&gt;以下是一个简化的 Loop Engineering Harness 实现，展示核心循环逻辑：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;interface AgentState {
	goal: string;
	history: Array&amp;#x3C;{ action: string; result: string }&gt;;
	iteration: number;
	maxIterations: number;
}

interface HarnessResult {
	success: boolean;
	finalState: AgentState;
	output: string;
}

class LoopEngineeringHarness {
	constructor(
		private planner: Planner,
		private executor: Executor,
		private evaluator: Evaluator,
		private stateManager: StateManager
	) {}

	async run(initialState: AgentState): Promise&amp;#x3C;HarnessResult&gt; {
		let state = this.stateManager.initialize(initialState);

		while (state.iteration &amp;#x3C; state.maxIterations) {
			// 1. 规划下一步
			const plan = await this.planner.plan(state);

			// 2. 执行计划
			const result = await this.executor.execute(plan);

			// 3. 评估结果
			const evaluation = await this.evaluator.evaluate(result, state.goal);

			// 4. 更新状态
			state = this.stateManager.update(state, {
				action: plan.action,
				result: result.output,
				evaluation
			});

			// 5. 终止判断
			if (evaluation.goalAchieved || evaluation.shouldTerminate) {
				return {
					success: evaluation.goalAchieved,
					finalState: state,
					output: result.output
				};
			}

			state.iteration++;
		}

		return { success: false, finalState: state, output: &apos;达到最大迭代次数&apos; };
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;六、总结&lt;/h2&gt;
&lt;p&gt;Loop Engineering Harness 是 AI Agent 从&quot;单次响应&quot;走向&quot;持续自主执行&quot;的架构基石。它通过&lt;strong&gt;规划-执行-评估&lt;/strong&gt;的闭环设计，赋予 Agent 处理复杂、开放式任务的能力。在工程实践中，Harness 的质量直接决定了 Agent 的可靠性上限——好的 Harness 能让中等能力的模型完成出色的工作，而缺乏 Harness 约束的强模型也可能在复杂任务中迷失方向。&lt;/p&gt;
&lt;p&gt;构建 Harness 的核心不在于追求更多的迭代轮次，而在于设计&lt;strong&gt;精准的反馈信号&lt;/strong&gt;和&lt;strong&gt;合理的终止策略&lt;/strong&gt;——让 Agent 知道何时该坚持、何时该放弃、何时该求助。&lt;/p&gt;</content:encoded></item><item><title>沙箱（Sandbox）技术完全指南</title><link>https://lora-sys.github.io/loraSys/blog/sandbox</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/sandbox</guid><description>沙箱技术是现代网络安全和软件开发中的重要工具，用于在隔离环境中运行潜在危险的程序，以防止其对系统造成损害。</description><pubDate>Tue, 16 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;沙箱技术是现代网络安全和软件开发中的重要工具，用于在隔离环境中运行潜在危险的程序，以防止其对系统造成损害。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;一、沙箱核心概念&lt;/h2&gt;
&lt;p&gt;**沙箱（Sandbox）**是一种安全隔离技术，通过创建一个受限制的执行环境，将潜在不安全的程序、代码或数据与系统核心部分隔离，防止其对系统或用户数据造成破坏。&lt;/p&gt;
&lt;h2&gt;1.1 什么是沙箱&lt;/h2&gt;
&lt;p&gt;沙箱就像一个透明的、坚不可摧的玻璃箱。在这个玻璃箱里运行可疑程序（如来路不明的软件、可疑邮件附件、网页脚本），无论程序在里面做什么（修改文件、删除数据、连接网络），都无法接触到真实的宿主系统。&lt;/p&gt;
&lt;p&gt;沙箱的核心价值在于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全隔离&lt;/strong&gt;：不可信代码无法影响宿主系统&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;行为监控&lt;/strong&gt;：完整记录程序的所有操作行为&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;资源限制&lt;/strong&gt;：防止恶意程序耗尽系统资源&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;环境还原&lt;/strong&gt;：执行结束后可快速恢复干净状态&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1.2 沙箱整体架构&lt;/h2&gt;
&lt;p&gt;沙箱系统采用三层架构设计：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;宿主系统层&lt;/strong&gt;：提供底层硬件和操作系统支持&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;沙箱隔离层&lt;/strong&gt;：实现资源隔离、权限控制、权限检查、行为监控&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;沙箱环境层&lt;/strong&gt;：提供隔离的虚拟文件系统、虚拟网络、虚拟注册表&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;二、沙箱核心原理&lt;/h2&gt;
&lt;h2&gt;2.1 工作原理详解&lt;/h2&gt;
&lt;p&gt;沙箱的完整工作流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;程序输入&lt;/strong&gt;：待分析/执行的程序进入沙箱系统&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;隔离环境&lt;/strong&gt;：程序被放置在隔离的执行环境中&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;API拦截&lt;/strong&gt;：所有系统调用被拦截和检查&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;行为监控&lt;/strong&gt;：记录程序的所有API调用和行为&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;日志记录&lt;/strong&gt;：生成完整的行为日志&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全分析&lt;/strong&gt;：基于行为数据进行安全评估&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;2.2 核心技术原理&lt;/h2&gt;
&lt;h3&gt;资源隔离&lt;/h3&gt;
&lt;p&gt;沙箱为程序分配独立的虚拟资源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;内存空间&lt;/strong&gt;：独立的地址空间，防止越界访问&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;文件系统&lt;/strong&gt;：虚拟文件系统，所有修改仅在沙箱内可见&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;网络接口&lt;/strong&gt;：虚拟网络，可限制或监控网络访问&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;注册表&lt;/strong&gt;：虚拟注册表，Windows系统专用&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;权限控制&lt;/h3&gt;
&lt;p&gt;通过严格的权限策略限制程序行为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;禁止访问敏感系统文件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;限制进程创建和注入&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;控制网络访问范围&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;禁止修改系统配置&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;行为监控&lt;/h3&gt;
&lt;p&gt;通过Hook技术拦截并记录所有关键操作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;文件读写操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;注册表修改&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网络连接建立&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;进程/线程创建&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;系统API调用&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、沙箱技术实现方式&lt;/h2&gt;
&lt;h2&gt;3.1 主流实现方案对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;技术方案&lt;/th&gt;
&lt;th&gt;隔离强度&lt;/th&gt;
&lt;th&gt;性能损耗&lt;/th&gt;
&lt;th&gt;启动速度&lt;/th&gt;
&lt;th&gt;内存开销&lt;/th&gt;
&lt;th&gt;代表产品&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;虚拟机 (VM)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐⭐ 最强&lt;/td&gt;
&lt;td&gt;高 (~30%)&lt;/td&gt;
&lt;td&gt;慢（分钟级）&lt;/td&gt;
&lt;td&gt;大（GB级）&lt;/td&gt;
&lt;td&gt;VMware, VirtualBox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;容器 (Docker)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⭐⭐⭐ 中等&lt;/td&gt;
&lt;td&gt;低 (~5%)&lt;/td&gt;
&lt;td&gt;快（秒级）&lt;/td&gt;
&lt;td&gt;小（MB级）&lt;/td&gt;
&lt;td&gt;Docker, LXC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;用户态内核 (gVisor)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐ 强&lt;/td&gt;
&lt;td&gt;中 (~15%)&lt;/td&gt;
&lt;td&gt;较快&lt;/td&gt;
&lt;td&gt;中等&lt;/td&gt;
&lt;td&gt;gVisor, Kata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;系统调用拦截&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⭐⭐ 较弱&lt;/td&gt;
&lt;td&gt;极低 (~2%)&lt;/td&gt;
&lt;td&gt;极快&lt;/td&gt;
&lt;td&gt;极小&lt;/td&gt;
&lt;td&gt;Sandboxie, seccomp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;3.2 各方案技术细节&lt;/h2&gt;
&lt;h3&gt;1. 虚拟机方案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;：通过Hypervisor模拟完整的硬件环境，运行独立的Guest OS&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心技术&lt;/strong&gt;：硬件辅助虚拟化（Intel VT-x, AMD-V）&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：隔离最彻底，几乎无法逃逸&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：资源开销大，启动慢&lt;/p&gt;
&lt;h3&gt;2. 容器方案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;：基于Linux Namespace和Cgroups实现进程级隔离&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心技术&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;PID Namespace - 进程隔离&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;NET Namespace - 网络隔离&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;MOUNT Namespace - 文件系统隔离&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cgroups - 资源限制&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 用户态内核方案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;：在用户空间实现一个迷你内核（Sentry），拦截所有系统调用&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代表&lt;/strong&gt;：Google gVisor&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优势&lt;/strong&gt;：在安全性和性能间取得最佳平衡&lt;/p&gt;
&lt;h3&gt;4. 系统调用拦截方案&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;：通过API Hook或seccomp过滤危险系统调用&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;代表&lt;/strong&gt;：Sandboxie, Windows Sandbox&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;优势&lt;/strong&gt;：轻量快速，用户体验好&lt;/p&gt;
&lt;h2&gt;四、沙箱制作方法&lt;/h2&gt;
&lt;h2&gt;4.1 沙箱搭建流程&lt;/h2&gt;
&lt;h2&gt;4.2 基于Docker的简易沙箱制作&lt;/h2&gt;
&lt;h3&gt;步骤1：创建Dockerfile&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;FROM python:3.11-slim

# 创建非特权用户
RUN groupadd -r sandbox &amp;#x26;&amp;#x26; useradd -r -g sandbox sandboxuser

# 设置工作目录
WORKDIR /sandbox

# 复制执行脚本
COPY run.sh .
RUN chmod +x run.sh

# 切换到非特权用户
USER sandboxuser

# 入口命令
CMD [&quot;./run.sh&quot;]

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;步骤2：编写执行脚本run.sh&lt;/h2&gt;
&lt;h3&gt;步骤2：编写执行脚本run.sh&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/bin/bash
set -e

# 资源限制
ulimit -n 1024      # 文件描述符限制
ulimit -u 64        # 进程数限制
ulimit -f 10240     # 文件大小限制

# 执行用户代码
python3 user_code.py

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;步骤3：构建并运行&lt;/h2&gt;
&lt;h3&gt;步骤3：构建并运行&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 构建镜像
docker build -t python-sandbox .

# 运行沙箱（自动清理）
docker run --rm \
  --memory=512m \
  --cpus=0.5 \
  --pids-limit=64 \
  --network=none \
  -v $(pwd)/user_code.py:/sandbox/user_code.py:ro \
  python-sandbox

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4.3 基于Linux Namespace的原生沙箱&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;#define _GNU_SOURCE
#include &amp;#x26;lt;sched.h&amp;#x26;gt;
#include &amp;#x26;lt;stdio.h&amp;#x26;gt;
#include &amp;#x26;lt;stdlib.h&amp;#x26;gt;
#include &amp;#x26;lt;sys/wait.h&amp;#x26;gt;
#include &amp;#x26;lt;unistd.h&amp;#x26;gt;

#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE];

static int child_func(void *arg) {
    printf(&quot;Sandbox: PID = %d\n&quot;, getpid());
    // 在隔离环境中执行程序
    execl(&quot;/bin/bash&quot;, &quot;/bin/bash&quot;, NULL);
    return 0;
}

int main(int argc, char *argv[]) {
    // 创建隔离命名空间
    int flags = CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID |
                CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWUSER;

    pid_t child_pid = clone(child_func, child_stack + STACK_SIZE,
                            flags | SIGCHLD, NULL);

    waitpid(child_pid, NULL, 0);
    return 0;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;五、沙箱使用场景&lt;/h2&gt;
&lt;h2&gt;5.1 网络安全领域&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;恶意代码分析&lt;/strong&gt;是沙箱最经典的应用场景&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;病毒/木马分析&lt;/strong&gt;：在隔离环境中运行恶意软件，观察其行为&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;勒索软件研究&lt;/strong&gt;：分析加密算法和传播机制&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;APT攻击溯源&lt;/strong&gt;：还原完整攻击链&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;杀毒软件动态检测&lt;/strong&gt;：360、卡巴斯基等均内置沙箱&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5.2 软件开发与测试&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;代码安全执行&lt;/strong&gt;：AI Agent生成的代码在沙箱中运行验证&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;兼容性测试&lt;/strong&gt;：模拟不同环境测试软件&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CI/CD流水线&lt;/strong&gt;：隔离的构建和测试环境&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;漏洞复现&lt;/strong&gt;：安全研究人员验证PoC&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5.3 AI Agent安全执行&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;AI Agent沙箱&lt;/strong&gt;是当前最热门的应用方向&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;代码解释器&lt;/strong&gt;：ChatGPT、Claude的代码执行环境&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;工具调用安全&lt;/strong&gt;：防止Agent执行危险操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;多Agent协作&lt;/strong&gt;：每个Agent独立沙箱隔离&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;数据处理&lt;/strong&gt;：用户上传文件的安全处理&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5.4 浏览器安全&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Chrome Site Isolation&lt;/strong&gt;：每个站点独立进程&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;网页沙箱&lt;/strong&gt;：JavaScript执行环境隔离&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;下载文件扫描&lt;/strong&gt;：自动在沙箱中打开可疑文件&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5.5 其他场景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;教育实训&lt;/strong&gt;：学生实验环境，防止误操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;隐私计算&lt;/strong&gt;：数据可用不可见&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;游戏反作弊&lt;/strong&gt;：检测游戏内存修改&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;沙箱浏览器&lt;/strong&gt;：隔离访问可疑网站&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;六、主流沙箱工具介绍&lt;/h2&gt;
&lt;h2&gt;6.1 恶意代码分析沙箱&lt;/h2&gt;
&lt;h3&gt;Cuckoo Sandbox（开源）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：工业级自动化恶意软件分析系统&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;支持Windows、Linux、macOS、Android&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;完整记录API调用、文件、网络、注册表&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;生成详细分析报告和IOC&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;开源免费，可自定义扩展&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Any.Run（在线）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：交互式在线沙箱&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;实时交互，像操作真实电脑一样&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支持视频录制和行为回放&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;社区分享分析结果&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;免费版有功能限制&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Hybrid Analysis&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：免费在线恶意软件分析平台&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;集成CrowdStrike威胁情报&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支持VxStream沙箱引擎&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;详细的行为报告和IOC提取&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6.2 桌面端沙箱工具&lt;/h2&gt;
&lt;h3&gt;Sandboxie-Plus（开源）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：Windows经典沙箱软件&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;轻量级，几乎不影响性能&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;右键菜单&quot;在沙箱中运行&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;支持多沙箱独立配置&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;开源免费，社区活跃&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Windows Sandbox（系统内置）&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：Windows 10/11 Pro内置轻量沙箱&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;系统原生，无需额外安装&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;每次启动都是干净环境&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关闭后自动销毁所有数据&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;基于Hyper-V技术&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Shadow Defender&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：影子系统软件&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;整个磁盘进入影子模式&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;所有修改重启后还原&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;适合测试软件和系统防护&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6.3 容器化沙箱方案&lt;/h2&gt;
&lt;h3&gt;Docker&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：最流行的容器化平台&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;沙箱应用&lt;/strong&gt;：快速创建隔离的执行环境&lt;/p&gt;
&lt;h3&gt;gVisor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：Google开源的容器运行时&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：用户态内核，比Docker更安全&lt;/p&gt;
&lt;h3&gt;Kata Containers&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：轻量级虚拟机容器&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：VM级安全，容器级性能&lt;/p&gt;
&lt;h2&gt;6.4 AI Agent专用沙箱&lt;/h2&gt;
&lt;h3&gt;e2b&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：AI Agent云沙箱服务&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：专为代码解释器设计，支持长会话&lt;/p&gt;
&lt;h3&gt;Cube Sandbox&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;定位&lt;/strong&gt;：高并发AI Agent执行沙箱&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：支持千级Agent并行执行&lt;/p&gt;
&lt;h2&gt;七、沙箱安全与逃逸&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：没有100%安全的沙箱，理解其局限性很重要&lt;/p&gt;
&lt;h2&gt;7.1 常见沙箱逃逸技术&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;内核漏洞利用&lt;/strong&gt;：通过内核漏洞突破隔离&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;容器逃逸&lt;/strong&gt;：CVE-2019-5736等经典漏洞&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;侧信道攻击&lt;/strong&gt;：通过时序等侧信道泄露信息&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;硬件漏洞&lt;/strong&gt;：Spectre、Meltdown等CPU漏洞&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;7.2 沙箱加固建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;多层隔离&lt;/strong&gt;：容器+虚拟机双重防护&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;最小权限&lt;/strong&gt;：遵循最小权限原则&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;及时更新&lt;/strong&gt;：修复已知安全漏洞&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;行为审计&lt;/strong&gt;：完整记录所有操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;网络隔离&lt;/strong&gt;：默认禁止网络访问&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;八、总结与展望&lt;/h2&gt;
&lt;p&gt;沙箱技术作为数字世界的&quot;安全试炼场&quot;，在网络安全、软件开发、AI安全等领域发挥着不可替代的作用。随着AI Agent的爆发式增长，沙箱技术正在迎来新的发展机遇：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;高性能&lt;/strong&gt;：在保证安全的前提下进一步降低性能损耗&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;高并发&lt;/strong&gt;：支持大规模AI Agent并行执行&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;智能化&lt;/strong&gt;：结合AI自动分析和响应威胁&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;标准化&lt;/strong&gt;：形成统一的沙箱接口标准&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;参考资料&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Linux Namespace和Cgroups官方文档&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;gVisor官方技术白皮书&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cuckoo Sandbox开源项目文档&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Docker容器安全最佳实践&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Windows Sandbox技术原理说明&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title>Building WishLive: A Multi-Agent Runtime</title><link>https://lora-sys.github.io/loraSys/blog/wishlive</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/wishlive</guid><description>How I built agents that execute, negotiate, and settle with Solidity contracts, Redis event streams, and graceful AI fallback.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;The Idea&lt;/h2&gt;
&lt;p&gt;Most agent frameworks treat agents like stateless functions. Call in, response out. No memory, no runtime, no economics.&lt;/p&gt;
&lt;p&gt;I wanted something different: &lt;strong&gt;a runtime where agents are first-class actors&lt;/strong&gt;. They register, discover each other, negotiate terms, execute work, and settle payments — all inside an event-driven system with observable state.&lt;/p&gt;
&lt;p&gt;This is the story of building that system in 48 hours for a hackathon.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Architecture: Six Layers, One Event Bus&lt;/h2&gt;
&lt;p&gt;The system is structured as six layers, each independently designed but communication-coupled through an event bus:&lt;/p&gt;
&lt;p&gt;Every layer publishes to typed event streams. The event log is the source of truth — no hidden state.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Layer 1: Registry — The Agent Internet&lt;/h2&gt;
&lt;p&gt;The registry is the DNS + service discovery for agents. Each agent registers with a typed card:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;interface AgentCard {
	agent_id: string;
	type: &apos;musician&apos; | &apos;venue&apos; | &apos;manager&apos; | &apos;audience&apos; | &apos;business&apos;;
	name: string;
	skills: string[];
	reputation: number;
	// ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Agents send heartbeats every 60 seconds. If they miss, the registry marks them OFFLINE. The &lt;code&gt;discover()&lt;/code&gt; method implements an A2A discovery protocol — one agent asks a manager agent to find matching candidates by skill, genre, city, or capacity.&lt;/p&gt;
&lt;p&gt;The system seeds 57 agents across 6 types on startup. The &lt;code&gt;onlineCount()&lt;/code&gt; method tracks availability by type in real time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key runtime behavior&lt;/strong&gt;: &lt;code&gt;ensureSeeded()&lt;/code&gt; auto-seeds on first access, so every service that depends on the registry gets a populated agent network without explicit initialization order.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Layer 2: Wish → Workflow Pipeline&lt;/h2&gt;
&lt;p&gt;Users submit wishes: &quot;I want to see Artist X in City Y on Date Z.&quot; The WishWorkflowService:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Aggregates wishes by cohort key (genre + city)&lt;/li&gt;
&lt;li&gt;Runs an agent to record the wish processing&lt;/li&gt;
&lt;li&gt;When a cohort reaches threshold (10 wishes), triggers demand creation&lt;/li&gt;
&lt;li&gt;The matching engine finds candidate musicians and venues from the registry&lt;/li&gt;
&lt;li&gt;Publishes demand events that drive the rest of the system&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The threshold is a deliberate design choice — it prevents premature negotiation on insufficient demand.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Layer 3: Runtime — The Execution Engine&lt;/h2&gt;
&lt;p&gt;This is the core. &lt;code&gt;AgentRuntimeService.run()&lt;/code&gt; creates a session, then executes in a loop:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;session started → agent thinks → tool execution → message → session completed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every step publishes to agent.runtime event stream · Langfuse telemetry on all sessions
&lt;/p&gt;
&lt;p&gt;The runtime supports &lt;strong&gt;dual-mode execution&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Real mode&lt;/strong&gt;: Uses the Vercel AI SDK with &lt;code&gt;generateText()&lt;/code&gt;, passing runtime tools for discovery, pricing, proposals. The agent decides which tools to call based on the user message.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simulated mode&lt;/strong&gt;: Deterministic fallback when no AI provider is configured. Executes the same tool plan but returns structured mock responses.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The graceful degradation is intentional — &lt;strong&gt;simulated mode means I can demo the entire system without an API key&lt;/strong&gt;. The switch happens transparently at the session level:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;if (mode === &apos;real&apos;) {
	try {
		result = await generateWithAISDK(agent, input, session);
	} catch (error) {
		mode = &apos;simulated&apos;; // graceful fallback
		result = await executePlannedTools(agent, input, session, mode);
	}
} else {
	result = await executePlannedTools(agent, input, session, mode);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every step publishes to the &lt;code&gt;agent.runtime&lt;/code&gt; event stream — thoughts, tool calls, messages, session lifecycle. Langfuse telemetry is wired in for production observability.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Layer 4: Negotiation — Stateful Agent Coordination&lt;/h2&gt;
&lt;p&gt;The negotiation service models multi-agent coordination as explicit, stateful protocols:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;create → propose → counter → accept → deal
                    ↓
                 reject
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each negotiation has a workflowId, conversationId, and tracks all proposals. The &lt;code&gt;runAutonomousNegotiation()&lt;/code&gt; method runs the full pipeline automatically:&lt;/p&gt;
&lt;p&gt;AUTONOMOUS NEGOTIATION PROTOCOL&lt;/p&gt;
&lt;p&gt;Musician Agent
Registry
Venue Agent
&lt;/p&gt;
&lt;p&gt;or → reject → negotiation ends&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Matches top musician and venue candidates from demand&lt;/li&gt;
&lt;li&gt;Musician sends initial proposal with terms (venue fee, split percentage)&lt;/li&gt;
&lt;li&gt;Venue counters with adjusted terms&lt;/li&gt;
&lt;li&gt;Musician accepts&lt;/li&gt;
&lt;li&gt;A Deal is created, ready for settlement&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The protocol is general enough for human-in-the-loop override — each step has API endpoints for manual accept/reject/counter.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Layer 5: Settlement — Economics On-Chain and Off&lt;/h2&gt;
&lt;p&gt;Settlement is where execution becomes real. The system supports &lt;strong&gt;dual settlement modes&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On-chain (production)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Solidity smart contracts: Escrow (lock/release funds), TicketNFT (mint event tickets), AgentProfile (agent identity)&lt;/li&gt;
&lt;li&gt;Hardhat deployment to local or testnet&lt;/li&gt;
&lt;li&gt;Funds held in escrow until deal confirmed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Local (development)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deterministic hash-based transaction IDs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;localTxHash()&lt;/code&gt; generates consistent 0x-prefixed hashes&lt;/li&gt;
&lt;li&gt;Full simulation of the settlement flow without a blockchain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SETTLEMENT PIPELINE
&lt;/p&gt;
&lt;p&gt;All settlement actions require human confirmation before execution
&lt;/p&gt;
&lt;p&gt;The critical design choice: &lt;strong&gt;human confirmation gates&lt;/strong&gt;. Every settlement action requires explicit confirmation:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;async createEscrow(input, options: { confirmed: boolean }) {
  if (!options.confirmed) {
    throw new SettlementError(409, &quot;Human confirmation required&quot;);
  }
  // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This prevents autonomous agents from moving real money without oversight.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Layer 6: Concierge — The Observability Layer&lt;/h2&gt;
&lt;p&gt;The concierge is an LLM-powered interface over the entire runtime. It reads event streams from all layers and answers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;What is happening right now?&quot;&lt;/li&gt;
&lt;li&gt;&quot;Why is the negotiation stuck?&quot;&lt;/li&gt;
&lt;li&gt;&quot;What happens next in this workflow?&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It supports both streaming and non-streaming responses, with Langfuse tracking on every interaction. When no AI provider is configured, it falls back to a rule-based simulator that summarizes system state from event data.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Event Bus: Where Everything Connects&lt;/h2&gt;
&lt;p&gt;All subsystems communicate through typed event streams. The bus has two implementations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MemoryEventBus&lt;/strong&gt;: In-memory array, perfect for development and testing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RedisEventBus&lt;/strong&gt;: Redis Streams with XADD/XREVRANGE, for production persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Event types include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;agent.lifecycle&lt;/code&gt; — registration, heartbeat, offline transitions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent.runtime&lt;/code&gt; — session lifecycle, thoughts, tool calls&lt;/li&gt;
&lt;li&gt;&lt;code&gt;agent.task&lt;/code&gt; — A2A message passing between agents&lt;/li&gt;
&lt;li&gt;&lt;code&gt;negotiation.events&lt;/code&gt; — proposals, counters, accepts, rejections&lt;/li&gt;
&lt;li&gt;&lt;code&gt;settlement.events&lt;/code&gt; — escrow creation, fund release, ticket minting&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wish.events&lt;/code&gt; / &lt;code&gt;demand.events&lt;/code&gt; / &lt;code&gt;matching.events&lt;/code&gt; — workflow pipeline&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;interface EventEnvelope {
	id: string;
	type: string;
	source: string;
	timestamp: number;
	data: Record&amp;#x3C;string, unknown&gt;;
	metadata: {
		traceId: string;
		spanId: string;
	};
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every event carries trace context, enabling end-to-end flow reconstruction.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What I Learned&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Graceful degradation is not optional.&lt;/strong&gt; The dual-mode runtime (AI + simulated) meant I could develop and demo the entire system without API keys, then flip to real AI when deploying. This pattern should be standard in every agent framework.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Event-driven architecture makes multi-agent systems debuggable.&lt;/strong&gt; Because every agent action is published to typed event streams, I can reconstruct exactly what happened — even across negotiation rounds, session restarts, and settlement failures.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Human gates are critical for economic execution.&lt;/strong&gt; Without explicit confirmation before escrow creation and fund release, autonomous agents become a financial liability. The &lt;code&gt;confirmed&lt;/code&gt; flag on every settlement method is the simplest correct design.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;57 seed agents = instant ecosystem.&lt;/strong&gt; Seeding the registry with diverse agent cards means every demo starts with a populated marketplace. The auto-seeding pattern (first access triggers population) eliminated initialization order bugs entirely.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;The Stack&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Runtime&lt;/strong&gt;: TypeScript, Vercel AI SDK, Zod validation&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Events&lt;/strong&gt;: Redis Streams (prod), in-memory (dev)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contracts&lt;/strong&gt;: Solidity, Hardhat, viem&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 14, Tailwind CSS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt;: Langfuse&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;: Docker Compose, pnpm workspace&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Final Thought&lt;/h2&gt;
&lt;p&gt;WishLive started as a hackathon project. But the architecture — a layered runtime with event-driven communication, dual-mode execution, and on-chain settlement — maps to real production concerns. Agents aren&apos;t functions you call. They&apos;re actors in a system with state, economics, and coordination.&lt;/p&gt;
&lt;p&gt;The code is at &lt;a href=&quot;https://github.com/lora-sys/Hackthon&quot;&gt;github.com/lora-sys/Hackthon&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title>Building a Full-Stack YouTube Clone with Next.js 15</title><link>https://lora-sys.github.io/loraSys/blog/newtube</link><guid isPermaLink="true">https://lora-sys.github.io/loraSys/blog/newtube</guid><description>A deep dive into architecture, core features, and problem solving strategies</description><pubDate>Tue, 10 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Building a video-sharing platform like YouTube is one of the most challenging yet rewarding projects for full-stack developers. It involves complex requirements: video processing, real-time streaming, user authentication, subscription systems, and much more.&lt;/p&gt;
&lt;p&gt;In this technical deep dive, I&apos;ll walk you through how I built &lt;strong&gt;NewTube&lt;/strong&gt; - a fully functional YouTube clone using modern web technologies. This isn&apos;t just a UI clone; it&apos;s a production-ready application with real video processing, AI-powered features, and a scalable architecture.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href=&quot;https://github.com/lora-sys/Newtube-clone&quot;&gt;NewTube Clone&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Source and setup instructions&lt;/strong&gt;: &lt;a href=&quot;https://github.com/lora-sys/Newtube-clone&quot;&gt;NewTube Clone on GitHub&lt;/a&gt;. A hosted demo is not currently published.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Project Overview&lt;/h2&gt;
&lt;h3&gt;What is NewTube?&lt;/h3&gt;
&lt;p&gt;NewTube is a full-featured video-sharing platform that includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Video Upload &amp;#x26; Streaming&lt;/strong&gt;: Powered by Mux with HLS adaptive streaming&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User Authentication&lt;/strong&gt;: Complete auth flow with Clerk&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creator Studio&lt;/strong&gt;: Dashboard for video management and analytics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscription System&lt;/strong&gt;: Follow your favorite creators&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comments &amp;#x26; Reactions&lt;/strong&gt;: Full engagement features&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Playlists&lt;/strong&gt;: Create and manage video collections&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI Features&lt;/strong&gt;: Auto-generate titles, descriptions, and thumbnails&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Responsive Design&lt;/strong&gt;: Works seamlessly on all devices&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tech Stack at a Glance&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Next.js 15, React 19, TypeScript, Tailwind CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;tRPC, Drizzle ORM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;PostgreSQL (Neon)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Clerk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Video&lt;/td&gt;
&lt;td&gt;Mux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;UploadThing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache&lt;/td&gt;
&lt;td&gt;Upstash Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue&lt;/td&gt;
&lt;td&gt;QStash&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Architecture Deep Dive&lt;/h2&gt;
&lt;h3&gt;System Architecture&lt;/h3&gt;
&lt;p&gt;The application follows a &lt;strong&gt;three-tier architecture&lt;/strong&gt; with serverless patterns optimized for modern cloud deployment:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────────────┐
│                      CLIENT LAYER                                │
│  Browser / Mobile → React Components → tRPC Client              │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────────┐
│                      API LAYER (tRPC)                            │
│  - protectedProcedure middleware                                 │
│  - Input validation (Zod)                                        │
│  - Rate limiting (Upstash)                                       │
└─────────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────���───────────────────────────────────────────┐
│                      DATA LAYER                                  │
│  PostgreSQL (Drizzle ORM) ←→ Redis Cache ←→ External Services   │
└─────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Project Structure&lt;/h3&gt;
&lt;p&gt;I organized the codebase using a &lt;strong&gt;feature-based module structure&lt;/strong&gt; (which I call &quot;moubles&quot;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;moubles/
├── videos/
│   ├── server/
│   │   └── procedures.ts    # tRPC API endpoints
│   ├── ui/
│   │   └── components/      # React components
│   └── type.ts              # TypeScript types
├── comments/
├── subscriptions/
├── playlists/
└── ... (other features)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach keeps related code together, making the codebase more maintainable as it grows.&lt;/p&gt;
&lt;h3&gt;Request Flow Example&lt;/h3&gt;
&lt;p&gt;Here&apos;s how a typical API request flows through the system:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// 1. Client Component triggers the query
const [videos] = trpc.videos.getMany.useSuspenseQuery({
	categoryId: selectedCategory
});

// 2. tRPC Client serializes and sends request
// POST /api/trpc/videos.getMany
// Body: { json: { categoryId: &quot;...&quot; } }

// 3. Server-side tRPC handles the request
export const videosRouter = createTRPCRouter({
	getMany: baseProcedure
		.input(
			z.object({
				categoryId: z.string().uuid().optional(),
				limit: z.number().min(1).max(100).default(10)
			})
		)
		.query(async ({ input }) =&gt; {
			// Database query with Drizzle ORM
			const data = await db
				.select({
					id: videos.id,
					title: videos.title
					// ... other fields
				})
				.from(videos)
				.where(eq(videos.videoVisiblity, &apos;public&apos;));

			return { items: data, nextCursor: null };
		})
});
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Core Technologies and Features&lt;/h2&gt;
&lt;h3&gt;1. Server Components with SSR Prefetching&lt;/h3&gt;
&lt;p&gt;Next.js 15&apos;s App Router allows us to prefetch data on the server and hydrate it to the client:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/(home)/videos/[videoId]/page.tsx (Server Component)
import { HydrateClient, trpc } from &apos;@/trpc/server&apos;;

export default async function VideoPage({ params }: { params: { videoId: string } }) {
	// Prefetch on the server
	void trpc.videos.getOne.prefetch({ id: params.videoId });
	void trpc.comments.getMany.prefetch({ videoId: params.videoId });

	return (
		&amp;#x3C;HydrateClient&gt;
			&amp;#x3C;VideoSection videoId={params.videoId} /&gt;
		&amp;#x3C;/HydrateClient&gt;
	);
}

// VideoSection.tsx (Client Component)
(&apos;use client&apos;);

export function VideoSection({ videoId }: { videoId: string }) {
	// Data is already prefetched - no loading state!
	const [video] = trpc.videos.getOne.useSuspenseQuery({ id: videoId });

	return &amp;#x3C;VideoPlayer video={video} /&gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Zero loading states for initial page load&lt;/li&gt;
&lt;li&gt;Better SEO with server-rendered content&lt;/li&gt;
&lt;li&gt;Reduced client-side JavaScript&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Type-Safe API Layer with tRPC&lt;/h3&gt;
&lt;p&gt;tRPC provides end-to-end type safety without code generation:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// Backend: trpc/router/videos.ts
export const videosRouter = createTRPCRouter({
	create: protectedProcedure.mutation(async ({ ctx }) =&gt; {
		const upload = await mux.video.uploads.create({
			new_asset_settings: {
				playback_policies: [&apos;public&apos;],
				inputs: [
					{
						generated_subtitles: [
							{
								language_code: &apos;en&apos;,
								name: &apos;English&apos;
							}
						]
					}
				]
			},
			cors_origin: process.env.MUX_CORS_ORIGIN || &apos;*&apos;
		});

		const [video] = await db
			.insert(videos)
			.values({
				userId: ctx.user.id,
				title: &apos;Untitled&apos;,
				muxStatus: &apos;waiting&apos;,
				muxUploadId: upload.id
			})
			.returning();

		return { video, url: upload.url };
	})
});

// Frontend: Auto-completion and type checking
const createMutation = trpc.videos.create.useMutation();
//     ^? { video: Video, url: string } - fully typed!
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Authentication Middleware with Caching&lt;/h3&gt;
&lt;p&gt;The authentication flow is optimized with a three-tier caching strategy:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// trpc/init.ts
export const protectedProcedure = t.procedure.use(async (opts) =&gt; {
	const { ctx } = opts;

	if (!ctx.clerkUserId) {
		throw new TRPCError({ code: &apos;UNAUTHORIZED&apos; });
	}

	// Tier 1: Check JWT publicMetadata (fastest)
	if (ctx.dbUserId) {
		return opts.next({ ctx: { user: { id: ctx.dbUserId } } });
	}

	// Tier 2: Check Redis cache
	const cachedDbId = await redis.get(`user:dbId:${ctx.clerkUserId}`);
	if (cachedDbId) {
		return opts.next({ ctx: { user: { id: cachedDbId } } });
	}

	// Tier 3: Database query (fallback)
	const [user] = await db.select().from(users).where(eq(users.clerkId, ctx.clerkUserId));

	// Cache for future requests
	await redis.set(`user:dbId:${ctx.clerkUserId}`, user.id, { ex: 3600 });

	// Update JWT for next time
	await clerkClient.users.updateUserMetadata(ctx.clerkUserId, {
		publicMetadata: { dbUserId: user.id }
	});

	return opts.next({ ctx: { user } });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Video Processing Pipeline&lt;/h3&gt;
&lt;p&gt;The video upload and processing flow uses webhooks for async updates:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User Upload → Mux Upload URL → Mux Processing → Webhook → Database Update
     │              │                │               │            │
     └──────────────┴────────────────┴───────────────┴────────────┘
                    Asynchronous flow with real-time updates
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// app/api/videos/webhook/route.ts
export async function POST(req: Request) {
	const payload = await req.json();

	switch (payload.type) {
		case &apos;video.asset.ready&apos;: {
			const asset = payload.data;
			const playbackId = asset.playback_ids[0].id;

			// Generate thumbnail from Mux
			const thumbnailUrl = `https://image.mux.com/${playbackId}/thumbnail.jpg`;
			const uploaded = await utapi.uploadFilesFromUrl(thumbnailUrl);

			// Update database
			await db
				.update(videos)
				.set({
					muxPlaybackId: playbackId,
					muxStatus: &apos;ready&apos;,
					duration: Math.round(asset.duration),
					thumbnailUrl: uploaded.data.ufsUrl
				})
				.where(eq(videos.muxUploadId, asset.upload_id));

			break;
		}
	}

	return new Response(&apos;OK&apos;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. AI-Powered Content Generation&lt;/h3&gt;
&lt;p&gt;Using QStash for async AI tasks:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// Trigger AI task
const { workflowRunId } = await workflow.trigger({
	url: `${process.env.QSTASH_WORKFLOW_URL}/api/videos/workflows/title`,
	body: { userId, videoId }
});

// Workflow handler
export async function POST(req: Request) {
	const { videoId } = await req.json();

	// Get video transcript from Mux
	const track = await mux.video.tracks.get(video.muxTrackId);
	const transcript = track.text;

	// Generate title with AI
	const response = await openai.chat.completions.create({
		model: &apos;gpt-4&apos;,
		messages: [
			{
				role: &apos;user&apos;,
				content: `Generate a YouTube title based on: ${transcript}`
			}
		]
	});

	const title = response.choices[0].message.content;

	// Update database
	await db.update(videos).set({ title }).where(eq(videos.id, videoId));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6. Optimistic Updates for Better UX&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const utils = trpc.useUtils();

const likeMutation = trpc.videoReactions.like.useMutation({
	onMutate: async ({ videoId }) =&gt; {
		// Cancel outgoing refetches
		await utils.videos.getOne.cancel({ id: videoId });

		// Snapshot previous value
		const previous = utils.videos.getOne.getData({ id: videoId });

		// Optimistically update UI
		utils.videos.getOne.setData({ id: videoId }, (old) =&gt; ({
			...old!,
			viewerReaction: &apos;like&apos;,
			likeCount: old!.likeCount + 1
		}));

		return { previous };
	},
	onError: (err, { videoId }, context) =&gt; {
		// Rollback on error
		utils.videos.getOne.setData({ id: videoId }, context.previous);
		toast.error(&apos;Failed to like video&apos;);
	},
	onSettled: ({ videoId }) =&gt; {
		// Refetch to ensure consistency
		utils.videos.getOne.invalidate({ id: videoId });
		utils.playlists.getLiked.invalidate();
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Challenges and Solutions&lt;/h2&gt;
&lt;h3&gt;Challenge 1: SSR Authentication with Protected Routes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: When using SSR with protected routes, the server doesn&apos;t have access to the client&apos;s authentication state, causing 401 errors or hydration mismatches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Implement a multi-layered approach:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// In protected components
&quot;use client&quot;;

import { useAuth, useClerk } from &quot;@clerk/nextjs&quot;;
import { useEffect, useRef } from &quot;react&quot;;

export function ProtectedSection() {
  const { isSignedIn, isLoaded } = useAuth();
  const { openSignIn } = useClerk();
  const hasTriggeredSignIn = useRef(false);

  useEffect(() =&gt; {
    // Prevent multiple calls with useRef
    if (isLoaded &amp;#x26;&amp;#x26; !isSignedIn &amp;#x26;&amp;#x26; !hasTriggeredSignIn.current) {
      hasTriggeredSignIn.current = true;
      openSignIn();
    }
  }, [isLoaded, isSignedIn, openSignIn]);

  if (!isLoaded) {
    return &amp;#x3C;Skeleton /&gt;;
  }

  if (!isSignedIn) {
    return null;
  }

  return &amp;#x3C;ActualContent /&gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Insight&lt;/strong&gt;: Using &lt;code&gt;useRef&lt;/code&gt; prevents the sign-in modal from opening multiple times during React&apos;s strict mode double-render.&lt;/p&gt;
&lt;h3&gt;Challenge 2: Hydration Mismatch in Mobile Detection&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: A mobile detection hook caused hydration errors because the initial value differed between server and client.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// ❌ Problem: undefined on server, boolean on client
const [isMobile, setIsMobile] = useState&amp;#x3C;boolean | undefined&gt;(undefined);
return !!isMobile;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Default to &lt;code&gt;false&lt;/code&gt; and only update on client:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// ✅ Fixed: Consistent initial value
const [isMobile, setIsMobile] = useState&amp;#x3C;boolean&gt;(false);

useEffect(() =&gt; {
	const checkMobile = () =&gt; {
		setIsMobile(window.innerWidth &amp;#x3C; 768);
	};

	checkMobile();
	window.addEventListener(&apos;resize&apos;, checkMobile);
	return () =&gt; window.removeEventListener(&apos;resize&apos;, checkMobile);
}, []);

return isMobile;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Challenge 3: Cache Invalidation Across Features&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: When a user likes a video, the &quot;Liked Videos&quot; playlist wasn&apos;t updating in real-time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Invalidate all related queries:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const likeMutation = trpc.videoReactions.like.useMutation({
	onSuccess: () =&gt; {
		// Primary data
		utils.videos.getOne.invalidate({ id: videoId });

		// Related features
		utils.playlists.getLiked.invalidate();
		utils.playlists.getLikedPreview.invalidate();
	}
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Challenge 4: CORS Configuration for Video Uploads&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: In production, Mux uploads failed due to CORS restrictions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Use environment-based CORS configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const upload = await mux.video.uploads.create({
	new_asset_settings: {
		/* ... */
	},
	// Development: &quot;*&quot; | Production: specific domain
	cors_origin: process.env.MUX_CORS_ORIGIN || &apos;*&apos;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Challenge 5: Real-time Video Processing Status&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Users couldn&apos;t see when their video finished processing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Implement polling with automatic cleanup:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const [workflowRunId, setWorkflowRunId] = useState&amp;#x3C;string | null&gt;(null);

useEffect(() =&gt; {
	if (!workflowRunId) return;

	const interval = setInterval(() =&gt; {
		// Invalidate cache to refetch latest data
		utils.studio.getOne.invalidate({ id: videoId });
	}, 2000);

	// Cleanup after 60 seconds
	const timeout = setTimeout(() =&gt; {
		clearInterval(interval);
		toast.info(&apos;Processing may take longer than expected&apos;);
	}, 60000);

	return () =&gt; {
		clearInterval(interval);
		clearTimeout(timeout);
	};
}, [workflowRunId, videoId, utils]);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Building NewTube was an incredible learning experience that pushed me to solve real-world problems at scale. Here&apos;s what I learned:&lt;/p&gt;
&lt;h3&gt;Key Takeaways&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Type Safety is Non-Negotiable&lt;/strong&gt;: tRPC + TypeScript + Zod eliminated entire categories of bugs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Server Components are Game-Changers&lt;/strong&gt;: SSR prefetching dramatically improved UX and SEO&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Caching Strategy Matters&lt;/strong&gt;: The three-tier auth caching reduced database queries by 90%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Webhooks Enable Async Workflows&lt;/strong&gt;: Critical for video processing and AI tasks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feature-Based Architecture Scales&lt;/strong&gt;: The &quot;moubles&quot; structure kept the codebase maintainable&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;What&apos;s Next?&lt;/h3&gt;
&lt;p&gt;Future improvements I&apos;m planning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time notifications with Server-Sent Events&lt;/li&gt;
&lt;li&gt;Video chapters and timestamps&lt;/li&gt;
&lt;li&gt;Live streaming support&lt;/li&gt;
&lt;li&gt;Advanced analytics dashboard&lt;/li&gt;
&lt;li&gt;Mobile app with React Native&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href=&quot;https://github.com/lora-sys/Newtube-clone&quot;&gt;NewTube Clone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Next.js Documentation&lt;/strong&gt;: &lt;a href=&quot;https://nextjs.org/docs&quot;&gt;nextjs.org/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tRPC Documentation&lt;/strong&gt;: &lt;a href=&quot;https://trpc.io/docs&quot;&gt;trpc.io/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Drizzle ORM&lt;/strong&gt;: &lt;a href=&quot;https://orm.drizzle.team/&quot;&gt;orm.drizzle.team&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;Thank you for reading! If you found this article helpful, please give the &lt;a href=&quot;https://github.com/lora-sys/Newtube-clone&quot;&gt;repository&lt;/a&gt; a ⭐ and feel free to reach out with questions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Happy coding! 🚀&lt;/strong&gt;&lt;/p&gt;</content:encoded></item></channel></rss>