跳转至

03 · 领域模型与公司边界

CompanyGoal / Project / IssueAgent Org聚合边界

一句话结论: Paperclip 用 Company 作为租户与治理根,用 Goal/Project/Issue 表达意图,用 Agent org 表达责任,再用 Run/Workspace/Artifact 记录执行事实;父子结构、依赖关系和所有权彼此独立。

1. 总体对象图

erDiagram
  COMPANY ||--o{ AGENT : employs
  COMPANY ||--o{ GOAL : owns
  COMPANY ||--o{ PROJECT : owns
  COMPANY ||--o{ ISSUE : owns
  COMPANY ||--o{ MEMBERSHIP : governs
  COMPANY ||--o{ BUDGET_POLICY : constrains
  COMPANY ||--o{ APPROVAL : reviews

  AGENT o|--o{ AGENT : manages
  GOAL o|--o{ GOAL : decomposes
  GOAL ||--o{ PROJECT : aligns
  PROJECT ||--o{ ISSUE : contains
  ISSUE o|--o{ ISSUE : decomposes
  ISSUE ||--o{ HEARTBEAT_RUN : executes
  ISSUE ||--o{ DOCUMENT : explains
  ISSUE ||--o{ WORK_PRODUCT : delivers
  HEARTBEAT_RUN o|--o| EXECUTION_WORKSPACE : uses

图中最值得注意的是多个递归关系:Agent 汇报树、Goal 目标树、Issue 工作树。它们长得相似,但约束和用途不同。

2. Company:租户、编号和治理根

companies 表不仅有名称和描述,还保存:

  • status;
  • issuePrefix 与 issueCounter,用于生成如 PAP-123 的稳定标识;
  • 预算与累计支出字段;
  • 单附件上限;
  • 默认 responsible user;
  • 是否要求新 Agent 经 Board 审批;
  • interaction governance 与 branding。

Company 同时承担四个角色:

  1. 数据分区键:业务查询第一过滤条件;
  2. 命名空间:Issue identifier、技能、工具连接和插件配置;
  3. 治理范围:membership、permission grant、预算和审批;
  4. 事件频道:实时事件按 company 订阅。

因此,“关联 ID 存在”不够,服务还会验证关联对象是否属于同一 Company。

3. Goal:保存“为什么”

Goal 有 level、status、parentId 和可选 ownerAgentId。它形成递归目标树,并可通过 project/issue 关联向下传播。

Company mission
  └─ annual / strategic goal
      └─ project goal
          └─ issue execution context

Goal 的价值不是做另一套标签,而是让 Agent context 能带上祖先目标。任务描述回答“做什么”,目标链回答“为什么”。

4. Project:轻量规划容器

Project 保存名称、状态、lead agent、goal 关联和环境/工作区策略。它刻意不等同于 Git repository:

  • 可以没有代码;
  • 可以有多个 project workspace;
  • 可以代表运营、设计或内容项目;
  • execution workspace policy 只是执行默认值,不改变其规划身份。

这个决定避免把“一个 repo”“一个交付目标”“一个运行目录”错误合并。

5. Issue:系统中最密集的聚合

issues 表承载了远多于任务标题的事实,可以按六组理解。

5.1 结构与对齐

  • companyId、projectId、goalId;
  • parentId:工作分解树;
  • projectWorkspaceId:选定的长期 workspace。

5.2 工作状态

  • status:backlog/todo/in_progress/in_review/done/blocked/cancelled;
  • workMode:standard/ask/planning/skill_test;
  • priority、review policy、started/completed/cancelled timestamps。

5.3 责任与执行锁

  • assigneeAgentId 或 assigneeUserId;
  • checkoutRunId;
  • executionRunId;
  • executionAgentNameKey、executionLockedAt。

责任人、checkout 持有者和实际执行 run 分开保存,允许系统表达“仍由 A 负责,但 A 的上一轮已结束,新一轮正在接管”。

5.4 来源与幂等

  • originKind、originId、originRunId、originFingerprint;
  • requestDepth;
  • routine、recovery、watchdog、productivity review 等系统来源。

这些字段让自动化创建的 Issue 可以被去重、识别和排除自触发。

5.5 执行策略

  • adapter/model/runtime overrides;
  • execution policy 与 state;
  • workspace preference/settings;
  • monitor 和 liveness 相关字段。

5.6 信任与责任归属

  • sourceTrust:输入来源的信任元数据;
  • responsibleUserId:Agent 行为最终由哪个人类责任主体承接;
  • unblockDescriptor:blocked 时可路由的解除路径。

这六组字段解释了 issues.ts 和 routes/issues.ts 为什么会变成巨型文件:Issue 是规划、执行、治理和恢复的交点。

6. 三种图不能混用

6.1 父子图:分解

parentId 回答“这个子任务属于哪个更大的任务”。父任务完成与否、子任务是否自动完成,由业务规则和 workflow 决定。

6.2 Blocker 图:依赖

issue_relations 中的 blocks 回答“B 是否必须等待 A”。它不是父子关系:兄弟任务、跨树任务也可以形成 blocker。

6.3 Org 图:管理与升级

agents.reportsTo 回答“谁管理谁”,用于 delegation、direct-report 权限、completion wake 和升级链。

flowchart LR
  subgraph WorkTree["工作分解树"]
    P["父 Issue"] --> C1["子 Issue A"]
    P --> C2["子 Issue B"]
  end
  subgraph Dependency["依赖图"]
    C1 -->|blocks| C2
  end
  subgraph Org["组织图"]
    CEO --> CTO --> ENG
  end

如果把三张图合成一张,系统会出现典型错误:父任务被误当 blocker、经理自动获得任意任务写权、取消上游被误判为依赖满足。

7. Agent:配置、组织身份和运行状态

agents 表可按三层理解:

层 代表字段 含义
组织身份 name、role、title、reportsTo、capabilities 它在公司里是谁
执行配置 adapterType、adapterConfig、runtimeConfig、defaultEnvironmentId 怎样运行它
控制状态 status、budget/spend、pause/error、permissions、lastHeartbeatAt 现在能否运行

状态包括 active、paused、idle、running、error、pending_approval、terminated。但“状态是 active”并不等价于“可立即唤醒”;invokability 还会检查 Company、预算、adapter、树暂停、环境等条件。

7.1 汇报树不是唯一授权来源

reportsTo 支持 delegation 和特定直系汇报场景,但真正授权还要结合:

  • company membership role;
  • principal permission grants;
  • 资源 membership;
  • task/skill/watchdog scope;
  • responsible user 的可用权限;
  • trust preset。

这是一套混合 RBAC + ABAC,而不是“老板可以做一切”。

8. Human、Agent 与 responsible user

Company membership 可以指向 user 或 agent。请求 actor 也可能是 board、agent、system 或 plugin。

为什么还需要 responsibleUserId?因为 Agent 的执行最终应能映射到一个人类责任主体,尤其在工具连接、密钥、审批和私有资源访问中。

可以把授权看成集合相交:

允许动作 = Agent 自身权限
        ∩ 当前 run/task scope
        ∩ responsible user 可代表的范围
        ∩ trust/budget/approval 约束

这避免某个高权限 Agent API key 脱离任务与人类责任上下文后成为万能 token。

9. Run 与 Session:尝试和连续性

heartbeat_runs 记录一次尝试,包含:

  • 状态、来源、开始/结束时间;
  • adapter/session/model 信息;
  • usage/cost/result/log/process metadata;
  • retry 关系和调度时间;
  • liveness 分类;
  • context snapshot。

agent_task_sessions 则以 company + agent + adapter + task key 保持可恢复会话。一次 session 可以跨多个 run,多个 run 不应共享同一条“当前执行事实”。

flowchart LR
  S["Task Session"] --> R1["Run 1"]
  S --> R2["Run 2"]
  S --> R3["Run 3"]
  R1 -->|"resume state"| R2 -->|"resume state"| R3

10. Workspace 也是领域对象

Project workspace 是稳定根;execution workspace 是实际执行位置;environment 是执行能力载体;environment lease 表示某次 run 对能力的占用。

这组对象让系统不必假设:

  • 代码一定在 Server 本机;
  • 每个任务一定创建 Git 分支;
  • 一个 Issue 只能运行一次;
  • workspace 清理可以靠进程退出顺便完成。

第 09 章会详细展开。

11. 证据对象:不要只看最终状态

Paperclip 把不同证据分开保存:

  • activity_log:谁对什么实体做了什么;
  • heartbeat_run_events:执行流中的结构化事件;
  • cost_events / finance_events:用量与账务;
  • documents / revisions / annotations:可审阅文本;
  • attachments/assets:持久化文件;
  • work products:PR、preview、artifact、workspace file 等交付摘要;
  • external objects:GitHub 等外部系统对象映射。

因此状态查询、历史审计和产物浏览可以使用不同读模型。

12. 删除与归档语义

关系使用多种策略:

  • Company 删除通常级联业务数据,但实际删除能力受 deployment/config 保护;
  • Agent 被移除时,历史记录多使用 set null 保留证据;
  • 插件、连接、技能和部分成员更偏向 disable/archive,而非抹去;
  • terminal Issue 保留全部 run/activity/document 历史。

这体现“运行系统里的历史比干净外键更重要”。

13. 可复用经验

  1. 多 Agent 系统应先选清楚租户/治理根,所有对象显式归属。
  2. 父子分解、依赖 DAG、组织汇报树必须分开建模。
  3. 责任人、checkout owner 和 execution lock 不应塞进一个 owner 字段。
  4. Run 表达一次尝试,Session 表达跨尝试连续性。
  5. 交付状态、执行成功与输出证据应能独立查询。
  6. 自动化生成的对象要保存 origin 和 fingerprint,才能可靠去重与防自触发。

源码入口

  • packages/db/src/schema/companies.ts
  • packages/db/src/schema/goals.ts
  • packages/db/src/schema/projects.ts、project_workspaces.ts
  • packages/db/src/schema/agents.ts
  • packages/db/src/schema/issues.ts、issue_relations.ts
  • packages/db/src/schema/heartbeat_runs.ts、agent_task_sessions.ts
  • packages/shared/src/types/issue.ts、agent.ts、heartbeat.ts

下一章进入运行组合根:04 · 服务启动与请求生命周期。