My Blog
← Back to home

Agent Company OS — 系统蓝图 + 开发 PRD

Agent Company OS — 系统蓝图 + 开发 PRD

版本:V1.0 | 状态:已定稿 | 基于 agent-company.md 愿景转化为可实现规格


第一部分:系统蓝图(System Blueprint)


一、核心理念技术翻译

原文愿景:

"从'你在驱动系统'变成'系统在驱动任务'"

技术架构:

Human(发起者 / 观察者)
    ↓ 发任务(写 tasks/todo/*.md)
Hermes Core(公司大脑:身份、任务、状态、记忆、日志、交付物)
    ↓ 读状态
Orchestrator(调度中枢:扫描 → 分配 → 启动 → 监控 → 回收)
    ↓ 写信号文件 + 控制 tmux
tmux Session(运行容器:pane 常驻,承载 Agent Runner)
    ↓ 读取信号文件
Agent Runner(Claude Code:执行任务)
    ↓ 写文件系统
outbox/ + logs/(交付物 + 行为轨迹)

二、三层架构

┌──────────────────────────────────────────┐
│ Layer 1: 人类接口层                       │
│  • 任务发起(hermes task create)          │
│  • 结果验收(读 outbox/summary.md)        │
│  • 状态观测(tmux attach / tree)          │
└──────────────────────────────────────────┘
                    ↓
┌──────────────────────────────────────────┐
│ Layer 2: 调度编排层                       │
│  • Hermes Core(CLI、任务 CRUD、状态机)    │
│  • Orchestrator(轮询、分配、监控、回收)    │
└──────────────────────────────────────────┘
                    ↓
┌──────────────────────────────────────────┐
│ Layer 3: 执行引擎层                       │
│  • tmux Session/Pane(常驻容器)           │
│  • Agent Runner(Claude Code)            │
│  • 文件系统(tasks/ logs/ outbox/)        │
└──────────────────────────────────────────┘

边界协议

模块 职责 不管什么
Hermes Core 身份、任务票、状态变迁、日志归档、交付物存储 不启动进程、不控制 tmux、不调度任务
Orchestrator 扫描 todo、分配合适 Agent、锁定任务、启动 Runner、监控心跳、回收结果 不写业务代码、不修改 outbox 内容
tmux 多 Agent 并行长驻、可观察、进程隔离 不理解业务逻辑
Agent Runner 读任务 → 执行 → 写日志 → 写 outbox → 发完成信号 不感知公司调度规则

三、数据模型

3.1 目录结构

agent-company/
├── hermes.py                    # CLI 入口(Hermes Core)
├── orchestrator.py               # 调度器主程序
├── lib/
│   ├── __init__.py
│   ├── task.py                  # 任务 CRUD 和状态机
│   ├── agent.py                # Agent 注册和运行时管理
│   ├── tmux_ctrl.py            # tmux 控制封装
│   └── signals.py              # Runner 信号文件机制
├── config/
│   ├── agents.yaml             # Agent 注册表
│   └── company.yaml            # 公司规则
├── runners/
│   └── claude_runner.md        # Claude Code prompt 模板
├── company/
│   └── AGENT_WORK_RULES.md     # Agent 行为规范
├── agents/
│   └── {agent_name}/
│       ├── profile.json         # 身份定义(Hermes 管)
│       └── runtime.json         # 运行时状态(Orchestrator 管)
├── tasks/
│   ├── todo/
│   ├── doing/
│   ├── blocked/
│   ├── review/
│   └── done/
├── memory/
│   └── {agent_name}/
├── logs/
│   └── {agent_name}/
│       └── YYYY-MM-DD.md
├── outbox/
│   └── {agent_name}/
│       └── {task_id}/
│           ├── summary.md
│           └── DONE
└── signals/                     # Runner 信号文件(Orchestrator → Runner)
    └── {agent_name}/
        └── current_task.json

3.2 核心数据结构

Task 文件

路径:tasks/{state}/{task_id}.md

---
id: 01HW5T3M7Z9A2B3C4D5E6F7G8H
title: 开发知识库商品落地页
project: knowledge-shop
owner: laohuang
priority: P1
state: todo
created_at: 2026-04-26T10:00:00Z
---
 
## Goal
 
完成一个可上线的 Next.js 落地页,包含:
- 商品介绍区
- 价格展示
- 购买引导
 
## Context
 
- 项目路径:/home/projects/knowledge-shop
- 设计稿:docs/design/landing-v1.figma
- 技术栈:Next.js 15, Tailwind CSS, TypeScript

任务锁定(独立 .lock 文件)

路径:tasks/{state}/{task_id}.lock

{
  "task_id": "01HW5T3M7Z9A2B3C4D5E6F7G8H",
  "locked_by": "orchestrator",
  "locked_at": "2026-04-26T13:35:00Z",
  "assigned_agent": "laohuang",
  "tmux_pane": "agent_laohuang",
  "signal_file": "signals/laohuang/current_task.json"
}

设计决策:锁定信息存在独立 .lock 文件,不修改原始 .md 理由:保持原始任务文件纯净,方便 Human 阅读;分离关注点

Agent Profile

路径:agents/{agent_name}/profile.json

{
  "name": "laohuang",
  "role": "fullstack_engineer",
  "description": "资深全栈工程师,负责代码开发和系统架构",
  "capabilities": ["frontend", "backend", "devops"],
  "preferred_engine": "claude-code",
  "max_concurrent_tasks": 1,
  "workspace_root": "/home/laohuang/projects"
}

Runtime State

路径:agents/{agent_name}/runtime.json

{
  "agent": "laohuang",
  "engine": "claude-code",
  "container": "tmux",
  "tmux_session": "hermes",
  "tmux_pane": "agent_laohuang",
  "status": "idle",
  "current_task_id": null,
  "current_task_signal": null,
  "last_heartbeat": "2026-04-26T13:30:00Z",
  "task_history": []
}

Runner 信号文件(Orchestrator → Runner)

路径:signals/{agent_name}/current_task.json

{
  "task_id": "01HW5T3M7Z9A2B3C4D5E6F7G8H",
  "task_file": "/path/to/tasks/doing/01HW5T3M7Z9A2B3C4D5E6F7G8H.md",
  "workspace_root": "/home/laohuang/projects",
  "project_path": "/home/laohuang/projects/knowledge-shop",
  "company_rules": "/path/to/company/AGENT_WORK_RULES.md",
  "memory_path": "/path/to/memory/laohuang",
  "logs_path": "/path/to/logs/laohuang",
  "outbox_path": "/path/to/outbox/laohuang/01HW5T3M7Z9A2B3C4D5E6F7G8H",
  "assigned_at": "2026-04-26T13:35:00Z"
}

设计决策:Orchestrator 与 Runner 之间通过信号文件通信,不依赖 tmux send-keys 理由:Claude Code 交互式运行,send-keys 无法可靠注入复杂上下文;文件信号可靠且可审计

Heartbeat(Runner → Orchestrator)

路径:agents/{agent_name}/heartbeat.json

{
  "agent": "laohuang",
  "task_id": "01HW5T3M7Z9A2B3C4D5E6F7G8H",
  "status": "working",
  "progress": "implementing hero section",
  "started_at": "2026-04-26T13:35:00Z",
  "updated_at": "2026-04-26T13:45:00Z"
}

四、任务状态机

4.1 状态流转

  [todo] ─pickup──→ [doing] ──done──→ [review]
     ↑                   │                  │
     └──retry────────────┘                  │
                                             ↓
  [blocked] ←max_retry exceeded           [done]

4.2 流转规则

当前状态 触发条件 目标状态 操作者
todo Orchestrator pickup doing Orchestrator
doing Runner 写 DONE 信号 review Orchestrator(检测到 DONE 后执行)
doing 超时(30min)/ Runner 报错 blocked Orchestrator
doing Runner 主动放弃 blocked Orchestrator
blocked Human 重试 todo Human(hermes task move)
blocked max_retry 达到(默认 3) done (failed) Orchestrator
review Human 验收通过 done Human
review Human 打回重做 todo Human

4.3 状态变更原子性

所有状态变更通过 task.move() 原子函数:

def move_task(task_id: str, from_state: str, to_state: str) -> None:
    # 1. 验证当前状态
    # 2. 读取原始文件
    # 3. 更新 state 字段
    # 4. 写回目标目录
    # 5. 删除源文件
    # 6. 记录日志
    # 若任何步骤失败则 rollback

五、Orchestrator 调度逻辑

5.1 主循环

class Orchestrator:
    def run(self):
        while self.running:
            self.sync_agent_status()      # 读取所有 runtime.json
            self.process_blocked_tasks()   # 检查 blocked 任务是否可重试
            self.scan_and_assign()         # 扫描 todo,分配给 idle agent
            self.monitor_task_progress()   # 检测 DONE 信号 / 超时
            self.sleep(self.poll_interval)

5.2 任务分配算法

优先级:
1. owner 精确匹配(task.owner == agent.name)
2. agent status == "idle"
3. agent.current_task_id == null
4. FIFO(任务创建时间早的优先)
5. priority(P1 > P2 > P3)

5.3 分配流程(原子操作)

def assign_task(agent: str, task_id: str) -> None:
    # 1. 写 signals/{agent}/current_task.json(包含完整上下文)
    # 2. 写 tasks/{task_id}.lock(锁定信息)
    # 3. 移动 tasks/todo/{task_id}.md → tasks/doing/{task_id}.md
    # 4. 更新 agents/{agent}/runtime.json(status=busy, current_task_id=xxx)
    # 5. 记录日志

5.4 完成检测

def check_completion(agent: str, task_id: str) -> bool:
    done_file = f"outbox/{agent}/{task_id}/DONE"
    return Path(done_file).exists()

5.5 并发控制

MAX_CONCURRENT_AGENTS = 3     # 最多同时分配任务给多少个 agent
MAX_TASK_RUNTIME = 1800        # 单任务超时(秒,30min)
MAX_RETRIES = 3                # blocked 后最大重试次数
POLL_INTERVAL = 10             # 扫描间隔(秒)

六、tmux 架构

6.1 Session / Pane 结构

Session: hermes
  ├── pane: orchestrator   # Orchestrator 进程(用于观察,可选 detach)
  ├── pane: agent_laohuang  # Runner 常驻循环
  ├── pane: agent_market01  # Runner 常驻循环
  └── pane: agent_content01 # Runner 常驻循环

6.2 Runner 在 pane 中的行为

每个 agent pane 启动后运行:

while true; do
  if [ -f signals/{agent}/current_task.json ]; then
    TASK=$(cat signals/{agent}/current_task.json)
    # 解析并执行任务
    claude -p runners/claude_runner.md \
      --extra-var "task_id=$(jq -r '.task_id' <<< $TASK)" \
      --extra-var "task_file=$(jq -r '.task_file' <<< $TASK)" \
      --extra-var "workspace=$(jq -r '.workspace_root' <<< $TASK)" \
      # ... 其他变量
    # 清理信号文件
    rm signals/{agent}/current_task.json
  fi
  sleep 5
done

设计决策:pane 内循环 + 信号文件,而不是 send-keys 理由:Claude Code 是交互式 CLI,send-keys 无法可靠注入多行上下文;信号文件可审计、可重试

6.3 Orchestrator 启动 tmux pane

def ensure_agent_pane(agent: str) -> None:
    pane = f"agent_{agent}"
    if not tmux.pane_exists("hermes", pane):
        tmux.new_window("hermes", pane)
        tmux.send_keys(f"cd {WORKSPACE}", pane=pane)
        tmux.send_keys(RUNNER_BOOT_SCRIPT.format(agent=agent), pane=pane)

七、Agent Runner 规范

7.1 执行流程

1. 读取 signals/{agent}/current_task.json
2. 读取对应 task file
3. 解析 goal 和 context
4. 执行任务(写代码 / 跑命令 / 写文案)
5. 写 logs/{agent}/{date}.md(执行过程)
6. 写 outbox/{agent}/{task_id}/(交付物)
7. 写 outbox/{agent}/{task_id}/summary.md
8. 写 outbox/{agent}/{task_id}/DONE(完成信号)
9. 更新 heartbeat status = "done"
10. 清理 signals/{agent}/current_task.json

7.2 summary.md 格式

# 任务交付总结
 
- 任务 ID:01HW5T3M7Z9A2B3C4D5E6F7G8H
- 执行 Agent:laohuang
- 开始时间:2026-04-26T13:35:00Z
- 结束时间:2026-04-26T14:20:00Z
- 结果状态:✅ 成功
 
## 产出清单
 
| 文件 | 说明 |
|------|------|
| pages/landing.tsx | 落地页主组件 |
| styles/landing.css | 样式文件 |
| package.json | 依赖更新 |
 
## 执行摘要
 
1. 阅读了项目文档和设计稿
2. 使用 Next.js App Router 创建落地页
3. 实现了响应式 Hero 区域
4. 集成了价格展示组件
 
## 遇到的问题(如有)
 

7.3 禁止行为(AGENT_WORK_RULES.md)

# Agent 工作规范
 
## 绝对禁止
 
1. 删除系统目录:/, /boot, /usr, /etc, /var, /home
2. 执行递归删除:rm -rf /
3. 修改系统配置:/etc/hosts, /etc/passwd, /etc/sudoers
4. 使用未授权的 sudo 命令
5. 修改 Hermes 核心文件:hermes.py, orchestrator.py, lib/
6. 修改其他 Agent 的 profile.json / runtime.json
7. 向未授权的网络地址发送数据
 
## 允许的操作
 
- 读写项目文件(workspace_root 内的项目目录)
- 执行 npm/bun/pip 等包管理命令
- 执行 git 命令(commit/push/pull,不强制)
- 创建和删除项目内文件
 
## 交付要求
 
- 每任务必须生成 summary.md
- 每任务必须创建 DONE 文件
- 必须记录执行日志

八、观测能力

8.1 实时观察

# 查看所有 pane 活动
tmux attach -t hermes
 
# 监控任务目录变化
watch -n 3 'tree tasks/ outbox/ signals/ -L 2'

8.2 Agent 状态查询

hermes agent status laohuang
# → current_task: TASK-xxx, status: working, since: 13:35

8.3 日志规范

路径:logs/{agent}/YYYY-MM-DD.md

# 工作日志 — laohuang — 2026-04-26
 
## 任务:01HW5T3M7Z — 开发知识库商品落地页
开始:13:35 | 结束:14:20 | 状态:✅
 
### 执行记录
 
| 时间 | 动作 | 详情 |
|------|------|------|
| 13:35 | 读取任务 | 分析 goal 和 context |
| 13:42 | 阅读代码 | 发现需要 Next.js 15 |
| 13:55 | 创建组件 | pages/landing.tsx |
| 14:10 | 测试验证 | npm run build 通过 |
| 14:18 | 写 summary | outbox/laohuang/01HW5T3M7Z/summary.md |
| 14:20 | 完成 | DONE 信号已写 |

第二部分:V1 开发 PRD


一、产品定义

1.1 名称

Agent Company OS V1 — "最小闭环"

1.2 核心目标

人类只需创建任务,系统自动分配 → 执行 → 交付。人类角色简化为:提任务 → 审结果 → 做决策

1.3 V1 范围

做:

  • Hermes Core CLI(任务 CRUD、Agent 注册、初始化)
  • Orchestrator(轮询调度器)
  • Agent Runner 接口规范(Claude Code 模式)
  • 文件系统状态存储(无数据库)
  • 最多 3 个 Agent 并发

不做:

  • 多 VPS 分布式(V2)
  • Redis 队列(V3)
  • Web Dashboard(V4)
  • Agent 记忆进化(V5)
  • 任务依赖管理(V2)

1.4 成功标准

✅ hermes task create 后系统自动 pickup
✅ Agent 产出 outbox/{agent}/{task}/summary.md + DONE
✅ 任务状态自动 todo → doing → review
❌ 不需要手动运行 agent
❌ 不需要手动复制粘贴任务上下文
❌ 不需要手动推进流程

二、技术选型

组件 选择 理由
Hermes Core Python 3.11+ / Click 跨平台、成熟生态、CLI 友好
Orchestrator Python 3.11+ / asyncio 异步 IO,适合文件轮询场景
tmux 系统包 已有容器层,无需开发
Agent Runner Claude Code(-p prompt 模式) 已有能力,可变参数注入
配置存储 YAML + Markdown 无数据库依赖
任务 ID ULID 时间有序、全球唯一、20 字符紧凑

关于 asyncio:Orchestrator 主要瓶颈是 IO(文件读写),用 asyncio 可优雅处理多 agent 监控,代码也比多线程简洁。


三、CLI 接口(Hermes Core)

3.1 命令清单

# 初始化
hermes init                          # 创建目录结构 + 配置文件
hermes doctor                         # 检查依赖(tmux、claude CLI)
 
# 任务管理
hermes task create --title "..." --owner laohuang --project x --priority P1 --goal "..."
hermes task list [--state todo|doing|review|done]
hermes task show <task_id>
hermes task move <task_id> <target_state> [--reason "..."]
hermes task delete <task_id>
 
# Agent 管理
hermes agent register --name laohuang --role fullstack --engine claude-code
hermes agent list
hermes agent status <name>

3.2 hermes init 行为

创建:

tasks/todo tasks/doing tasks/blocked tasks/review tasks/done
agents/
memory/
logs/
outbox/
signals/
config/
company/
runners/

并生成初始配置文件(若不存在):

config/agents.yaml
config/company.yaml
company/AGENT_WORK_RULES.md
runners/claude_runner.md

3.3 hermes doctor 检查项

  • tmux 已安装
  • claude CLI 已安装(claude --version
  • 目录结构完整
  • config/agents.yaml 存在且非空
  • 所有注册 agent 有对应 profile.json

四、项目结构(V1 实现)

agent-company/
├── pyproject.toml
├── hermes.py               # CLI 入口(Click)
├── orchestrator.py         # 调度器(asyncio 主循环)
├── lib/
│   ├── __init__.py
│   ├── task.py             # TaskManager 类(CRUD + 状态机)
│   ├── agent.py           # AgentManager 类(注册 + 运行时)
│   ├── tmux_ctrl.py       # TmuxController(tmux 操作封装)
│   ├── signals.py         # SignalManager(信号文件读写)
│   └── ulid.py             # ULID 生成工具
├── config/
│   ├── agents.yaml
│   └── company.yaml
├── runners/
│   └── claude_runner.md
├── company/
│   └── AGENT_WORK_RULES.md
├── agents/                 # 每个 agent 一个目录
├── tasks/                  # 状态分目录
├── memory/
├── logs/
├── outbox/
├── signals/                # Orchestrator → Runner
└── tests/
    ├── test_task.py
    ├── test_state_machine.py
    └── test_orchestrator.py

五、实现任务拆分

Phase 0:脚手架(1 天)

  • pyproject.toml + 依赖(click, pyyaml, python-ulid, pytest)
  • 目录结构创建(hermes init)
  • hermes doctor(依赖检查)
  • config/agents.yaml + config/company.yaml schema
  • company/AGENT_WORK_RULES.md
  • runners/claude_runner.md 模板

Phase 1:Hermes Core(2 天)

  • lib/ulid.py(ULID 生成)
  • lib/task.py(TaskManager:create/list/show/move/delete)
  • lib/agent.py(AgentManager:register/list/status)
  • hermes.py CLI(Click 命令绑定)
  • 状态变更原子性保证(写-移动-删除事务)
  • .lock 文件读写逻辑

Phase 2:tmux 控制层(1 天)

  • lib/tmux_ctrl.py(TmuxController)
    • session 创建/检查
    • pane 创建/检查/发送命令
    • pane 内运行 Runner 启动脚本
  • Runner 启动脚本(bash,用于每个 pane)

Phase 3:Orchestrator(3 天)

  • lib/signals.py(SignalManager:写 Runner 信号、读 Runner 心跳)
  • Orchestrator 类(asyncio 主循环)
    • 扫描 todo + 匹配 idle agent
    • 原子分配(写信号 + 移动文件 + 更新 runtime)
    • DONE 信号检测
    • 超时监控
    • blocked 处理
  • Graceful shutdown(SIGTERM 处理)
  • --dry-run 模式
  • 详细日志输出

Phase 4:Runner 集成(1 天)

  • runners/claude_runner.md 变量填充逻辑
  • Runner 执行后的 outbox/summary.md 格式验证
  • 日志格式验证
  • DONE 文件创建验证

Phase 5:集成测试(2 天)

  • 完整流程:task create → pickup → execute → outbox
  • 3 个 agent 并发测试
  • 超时 → blocked 测试
  • blocked → retry → done 测试
  • Orchestrator 重启后状态恢复测试
  • dry-run 验证

Phase 6:文档(1 天)

  • README.md(快速开始)
  • 架构图(ASCII)
  • 验收清单

总工期:约 11 个工作日


六、关键设计决策

决策 选择 理由
Orchestrator ↔ Runner 通信 信号文件(signals/) tmux send-keys 无法可靠注入交互式 Claude Code;文件信号可审计
任务文件锁定 独立 .lock 文件 保持原始 md 纯净;分离调度信息和业务信息
任务 ID ULID 时间有序、支持分布式生成、紧凑(20 字符)
Orchestrator 实现 asyncio 类 适合 IO 密集型轮询;比多线程/多进程简洁
Runner 启动方式 pane 内 bash 循环 Claude Code 无法后台常驻;循环等待信号文件最稳定
完成检测 DONE 文件存在 最简可靠信号;比心跳停止检测更明确
状态存储 文件系统 V1 最小依赖;后续迁移 SQLite 成本低
调度触发 轮询(10s) 简单可靠;比 Webhook 少依赖

七、升级路径

V1 (文件系统 + 轮询)
  ├── 改进:状态存储 → SQLite(事务保证)
  ├── 改进:任务依赖 DAG → topological sort
  └── 改进:调度策略 → 技能最优匹配

V2 (分布式)
  ├── 多 VPS SSH 调度
  └── 远程 tmux pane(via ssh)

V3 (队列化)
  └── Redis Queue + Celery Worker

V4 (可视化)
  └── Web Dashboard + REST API

V5 (智能化)
  └── Agent 记忆进化 + 主动任务发现

八、验收标准

自动测试必须通过

[ ] hermes init 成功创建所有目录
[ ] hermes doctor 无报错(tmux + claude CLI)
[ ] hermes task create 生成 tasks/todo/{ulid}.md,ID 为 ULID 格式
[ ] hermes task list --state todo 正确显示
[ ] hermes task move task_id doing 原子移动文件
[ ] hermes task show 显示完整信息(含 .lock 扩展)
[ ] hermes agent register 生成 agents/{name}/profile.json
[ ] Orchestrator 启动后持续运行(不退出)
[ ] 创建 todo 任务后 15s 内被 pickup(idle agent 存在时)
[ ] pickup 后 tasks/todo/ → tasks/doing/ 文件已移动
[ ] signals/{agent}/current_task.json 被创建且内容正确
[ ] Agent pane 检测到信号文件并执行
[ ] outbox/{agent}/{task}/summary.md 存在且格式正确
[ ] outbox/{agent}/{task}/DONE 文件存在
[ ] DONE 存在后 tasks/doing/ → tasks/review/ 自动流转
[ ] 任务超时(30min)后进入 blocked 状态
[ ] 3 个 agent 并发无冲突(无重复 pickup)

手动验收场景

场景 1:完全无人值守
  $ hermes task create --title "写 hello.py" --owner laohuang --goal "在 /tmp/hello.py 写 print('hello')"
  等待 3 分钟
  $ hermes task list --state review
  → 任务已在 review
  $ cat outbox/laohuang/*/summary.md
  → 有产出内容

场景 2:并发调度
  同时提交 5 个任务(owner = laohuang/market01/content01 混合)
  3 个 pane 并发执行
  无任务丢失,无状态混乱

场景 3:失败恢复
  Orchestrator 运行中,Ctrl+C 重启
  之前 doing 的任务进入 blocked 或恢复 pickup

附录 A:配置文件格式

config/agents.yaml

agents:
  - name: laohuang
    role: fullstack_engineer
    engine: claude-code
    capabilities:
      - frontend
      - backend
      - devops
    workspace_root: /home/laohuang/projects
  - name: market01
    role: marketing_writer
    engine: claude-code
    capabilities:
      - copywriting
      - seo
      - social_media
    workspace_root: /home/laohuang/projects
  - name: content01
    role: content_creator
    engine: claude-code
    capabilities:
      - article
      - video_script
      - documentation
    workspace_root: /home/laohuang/projects

config/company.yaml

company:
  name: Hermes AI Company
  workspace_root: /home/laohuang/projects
  max_concurrent_agents: 3
  task_timeout_seconds: 1800
  poll_interval_seconds: 10
  max_retries: 3
 
paths:
  tasks: tasks
  agents: agents
  logs: logs
  outbox: outbox
  memory: memory
  signals: signals
  runners: runners
  company_rules: company/AGENT_WORK_RULES.md

附录 B:orchestrator.py 核心逻辑(伪代码)

import asyncio
from lib.task import TaskManager
from lib.agent import AgentManager
from lib.signals import SignalManager
from lib.tmux_ctrl import TmuxController
 
class Orchestrator:
    def __init__(self, config):
        self.tasks = TaskManager()
        self.agents = AgentManager()
        self.signals = SignalManager()
        self.tmux = TmuxController()
        self.poll_interval = config.poll_interval
        self.running = True
 
    async def run(self):
        # 确保所有 agent pane 存在
        for agent in self.agents.list():
            self.tmux.ensure_pane(agent)
 
        while self.running:
            await self.step()
            await asyncio.sleep(self.poll_interval)
 
    async def step(self):
        self.sync_agent_status()
        self.process_blocked()
        await self.scan_and_assign()
        self.detect_completions()
 
    async def scan_and_assign(self):
        idle_agents = [a for a in self.agents.list() if a.is_idle()]
        for agent in idle_agents:
            if self.agents.active_count() >= MAX_CONCURRENT:
                break
            task = self.tasks.pick_best_todo()
            if not task:
                break
            self.assign_task(agent, task)
 
    def assign_task(self, agent, task):
        # 原子操作:
        # 1. 写信号文件
        self.signals.write_task_signal(agent, task)
        # 2. 创建锁文件
        self.tasks.lock(task.id, agent)
        # 3. 移动任务文件
        self.tasks.move(task.id, "todo", "doing")
        # 4. 更新 agent 状态
        self.agents.assign(agent, task.id)
        log(f"Assigned {task.id} to {agent}")
 
    def detect_completions(self):
        for agent in self.agents.list_busy():
            task_id = agent.current_task_id
            if self.signals.check_done(agent, task_id):
                self.tasks.move(task_id, "doing", "review")
                self.agents.free(agent)
                log(f"Task {task_id} completed, moved to review")

系统蓝图一句话: Hermes 定义"谁该做什么",Orchestrator 决定"什么时候让谁去做",tmux 承载"他们在哪里做",Claude Code 负责"真正把事情做出来",信号文件连接"调度与执行"。