docs(architecture): add startup/register/runtime/shutdown flow docs and architecture overview

This commit is contained in:
2026-04-28 21:09:33 +08:00
parent e66ed9e9c0
commit 9ea475432f
6 changed files with 482 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
# 整体架构与运行流
Partner 是一个多模块、异步协作的智能体运行时。
为平衡扩展性与组件间一致性Partner 内部具备一个小型的 DI 容器,以及多个具备配套接口的注册中心。它们会在 Agent 启动时有序拉起,并将各自的关闭 Hook 注册进名为 `AgentContext` 的对象中,在 JVM 收到终止信号时有序触发各个 shutdown hook 进行关闭。
本文是架构文档入口,用于说明核心文档的阅读顺序和主题边界。下方总览图描述 Partner-Core 中感知、记忆、行动、交流与对话滚动模块在一次运行轮次中的协作关系。
## 阅读顺序
- [Agent 启动流程](startup.md):说明 `Agent.launch()` 的外层启动顺序。
- [Agent 注册链](register-chain.md):说明 `AgentRegisterFactory.launch()` 如何扫描、校验、实例化并注入组件与 Capability。
- [Runtime 输入与模块调度](runtime-flow.md):说明 Gateway 输入如何进入 `AgentRuntime`,以及 Running module 如何被调度。
- [关闭流程](shutdown.md):说明 JVM shutdown hook、生命周期关闭钩子与 `@Shutdown` 方法的执行顺序。
## 核心概念
### AgentContext
`AgentContext` 是注册链和运行时之间的共享容器,主要保存:
- `modules`:扫描并实例化得到的 Running / Sub / Standalone 模块。
- `capabilities`Capability 动态代理、CapabilityCore 实例和方法路由信息。
- `additionalComponents`:非模块类型的 `@AgentComponent` 实例。
- `shutdownHooks`:从 `@Shutdown` 方法收集得到的关闭钩子。
- `preShutdownHooks` / `postShutdownHooks`:框架与应用显式注册的生命周期关闭钩子。
### Configurable
`Configurable` 用于向 `ConfigCenter` 注册配置入口。启动阶段会先注册框架内置和应用传入的 Configurable随后在 `ConfigCenter.initAll()` 阶段读取配置并触发各自的初始化逻辑。
### Gateway
Gateway 是外部输入协议与 Partner Runtime 之间的边界。Gateway 将协议输入转换成 `RunningFlowContext`,再提交给 `AgentRuntime`。响应输出也通过 `ResponseChannel` 抽象回到具体 Gateway。
### Running Module
Running module 是 `AgentRuntime` 直接调度的模块类型。它们按 `module.order()` 分组执行order 小的组先执行,同一 order 内并发执行。
## Partner-Core 模块链路总览
```mermaid
flowchart TD
Wake["wakeSignal"] --> Source["取出 source"]
Source --> Context["构造 Context"]
Context --> Execute["executeTurn"]
Execute --> Perceive["order = 1<br/>感知上下文"]
Perceive --> Planning["order = 2<br/>记忆 / 行动"]
Planning --> Communication["order = 5<br/>交流生成"]
Communication --> Rolling["order = 7<br/>对话滚动"]
Rolling --> End["本轮结束"]
Planning -. "MemorySelector" .-> MemoryAsync["异步召回<br/>MEMORY context"]
Planning -. "ActionPlanner" .-> ActionAsync["异步行动<br/>ACTION context"]
Rolling -. "滚动后" .-> MemoryUpdate["异步更新<br/>召回索引"]
Perceive -.-> Workspace["ContextWorkspace"]
MemoryAsync -.-> Workspace
ActionAsync -.-> Workspace
MemoryUpdate -.-> Workspace
Rolling -. "dialog_history" .-> Workspace
Workspace -. "resolve context" .-> Communication
ActionAsync -. "initiateTurn" .-> Wake
classDef main fill:#eef6ff,stroke:#2f6f9f,color:#1c3144;
classDef async fill:#fff7e6,stroke:#b7791f,color:#3b2f16,stroke-dasharray: 5 5;
classDef state fill:#f1f8f4,stroke:#3f8f5f,color:#173b24;
class Wake,Source,Context,Execute,Perceive,Planning,Communication,Rolling,End main;
class MemoryAsync,ActionAsync,MemoryUpdate async;
class Workspace state;
```
### 图例说明
- 图中蓝色节点表示本轮 `PartnerRunningFlowContext``AgentRuntime.executeTurn()` 中的同步主链路。`AgentRuntime` 会按 `module.order()` 分组调度 Running moduleorder 较小的模块组先执行,同一 order 内的模块并发执行。
- 黄色节点表示模块内部启动的异步任务。它们不会阻塞当前主链路继续向后执行,因此异步任务写入的 `MEMORY context``ACTION context` 不保证一定会被本轮 `CommunicationProducer` 读取;如果写入晚于本轮交流生成,则会影响后续 turn。
- 绿色节点表示 `ContextWorkspace`。感知、记忆、行动、对话滚动等模块会向其中注册不同 focused domain 的上下文块;`CommunicationProducer` 在生成回复前统一 resolve `COGNITION / ACTION / MEMORY / PERCEIVE` 相关上下文,并与对话历史和当前输入一起组装成模型输入。
### 模块链路说明
- `PerceiveMonitor``SystemStatsMonitor` 位于 order 1主要负责刷新交互时间、采集系统状态并写入 `PERCEIVE` 域上下文。
- `MemorySelector``ActionPlanner` 位于 order 2。`MemorySelector` 在同步阶段收集本轮输入,并尝试启动异步 recall worker实际记忆召回、候选切片评估和 `activated_memory_slices` 写入发生在异步任务中。`ActionPlanner` 在同步阶段提取行动意图并写入初始 ACTION 状态,后续评估、确认、执行或调度由异步任务继续处理。
- `CommunicationProducer` 位于 order 5是本轮对外交流的主要出口。它读取 `ContextWorkspace`、当前保留的 conversation history 和本轮输入,生成回复并更新聊天轨迹。
- `DialogRolling` 位于 order 7用于在对话历史达到阈值后执行压缩、总结和滚动。滚动结果会写入记忆系统并向 `ContextWorkspace` 注册 `dialog_history`,供后续 turn 使用。
### 异步回流
`ActionPlanner` 的异步任务可能通过 `initiateTurn()` 重新提交输入,从而触发新的 `wakeSignal`。这不是当前 turn 的下一步,而是后续 turn 的入口。也就是说,图中的虚线回流表示“可能产生新的运行轮次”,不是当前同步链路的一部分。

View File

@@ -0,0 +1,158 @@
# Agent 注册链
本文说明 `AgentRegisterFactory.launch(packageName)` 内部的注册链。注册链的职责是基于应用包与外部模块目录扫描结果完成组件、模块、Capability、生命周期方法和关闭方法的注册。
`AgentRegisterContext` 是注册链上下文。它持有 `Reflections` 扫描器,以及供各阶段读写的 `ComponentFactoryContext``CapabilityFactoryContext` 和全局 `AgentContext`
```mermaid
flowchart TD
A["AgentRegisterFactory.launch(packageName)"] --> B["packageNameToURL(packageName)"]
B --> C["创建 AgentRegisterContext"]
subgraph CTX["AgentRegisterContext"]
direction TB
C1["reflections<br/>扫描字段 / 方法 / 类型注解 / 子类"]
C2["componentFactoryContext<br/>缓存 @Init 扫描结果"]
C3["capabilityFactoryContext<br/>缓存 Capability 扫描结果"]
C4["agentContext<br/>注册运行时组件"]
end
C --> CTX
CTX --> F1["ComponentAnnotationValidatorFactory"]
F1 --> F2["ComponentRegisterFactory"]
F2 --> F3["ComponentInjectorFactory"]
F3 --> F4["CapabilityAnnotationValidatorFactory"]
F4 --> F5["CapabilityRegisterFactory"]
F5 --> F6["CapabilityInjectorFactory"]
F6 --> F7["ComponentInitHookExecutorFactory"]
F7 --> F8["ShutdownHookCollectorFactory"]
F8 --> Z["注册链完成"]
subgraph S1["ComponentAnnotationValidatorFactory"]
direction TB
S1A["校验 @Init"]
S1B["校验 @InjectModule"]
S1C["将 @Init 方法缓存到 componentFactoryContext"]
S1A --> S1B --> S1C
end
subgraph S2["ComponentRegisterFactory"]
direction TB
S2A["扫描 @AgentComponent"]
S2B["反射调用无参构造器实例化"]
S2C{"是否 AbstractAgentModule?"}
S2D["注册到 AgentContext.modules"]
S2E["注册到 AgentContext.additionalComponents"]
S2F{"模块类型"}
S2G["ModuleContextData.Running<br/>order / modelInfo / launchTime"]
S2H["ModuleContextData.Sub<br/>injectTarget / modelInfo / launchTime"]
S2I["ModuleContextData.Standalone<br/>injectTarget / modelInfo / launchTime"]
S2A --> S2B --> S2C
S2C -->|是| S2D --> S2F
S2C -->|否| S2E
S2F -->|Running| S2G
S2F -->|Sub| S2H
S2F -->|Standalone| S2I
end
subgraph S3["ComponentInjectorFactory"]
direction TB
S3A["读取 AgentContext.modules"]
S3B["按 Running / Sub / Standalone 分类"]
S3C["处理 @InjectModule"]
S3D["记录 injectTarget"]
S3A --> S3B --> S3C --> S3D
end
subgraph S4["CapabilityAnnotationValidatorFactory"]
direction TB
S4A["扫描 @CapabilityCore"]
S4B["扫描 @Capability"]
S4C["扫描 @CapabilityMethod"]
S4D["校验 Capability value 唯一"]
S4E["校验 CapabilityMethod 位置与唯一实现"]
S4F["校验 @InjectCapability"]
S4G["写入 capabilityFactoryContext"]
S4A --> S4D
S4B --> S4D
S4C --> S4E
S4D --> S4E --> S4F --> S4G
end
subgraph S5["CapabilityRegisterFactory"]
direction TB
S5A["读取 capabilityFactoryContext"]
S5B["实例化 CapabilityCore"]
S5C["构建方法路由表"]
S5D["为 @Capability 接口创建动态代理"]
S5E["注册到 AgentContext.capabilities"]
S5A --> S5B --> S5C --> S5D --> S5E
end
subgraph S6["CapabilityInjectorFactory"]
direction TB
S6A["读取 modules + additionalComponents"]
S6B["读取 AgentContext.capabilities"]
S6C["处理 @InjectCapability 字段"]
S6A --> S6C
S6B --> S6C
end
subgraph S7["ComponentInitHookExecutorFactory"]
direction TB
S7A["读取 componentFactoryContext 中的 @Init 方法"]
S7B["目标为 modules + additionalComponents"]
S7C["按 @Init.order 升序执行"]
S7A --> S7C
S7B --> S7C
end
subgraph S8["ShutdownHookCollectorFactory"]
direction TB
S8A["扫描 @Shutdown 方法"]
S8B["校验位置与参数"]
S8C["AgentContext.addShutdownHook(method, order)"]
S8A --> S8B --> S8C
end
F1 -.-> S1
F2 -.-> S2
F3 -.-> S3
F4 -.-> S4
F5 -.-> S5
F6 -.-> S6
F7 -.-> S7
F8 -.-> S8
```
## AgentContext
`AgentContext` 是注册链的主要产物。它不是单轮对话上下文,而是运行时组件注册结果和关闭逻辑的集中容器。
```mermaid
flowchart TD
A["AgentContext"] --> B["modules"]
A --> C["capabilities"]
A --> D["additionalComponents"]
A --> E["metadata"]
A --> F["shutdownHooks"]
A --> G["preShutdownHooks"]
A --> H["postShutdownHooks"]
B --> B1["ModuleContextData.Running"]
B --> B2["ModuleContextData.Sub"]
B --> B3["ModuleContextData.Standalone"]
C --> C1["CapabilityImplementation"]
C1 --> C2["capability instance"]
C1 --> C3["capability cores"]
C1 --> C4["capability methods"]
F --> F1["RUNNING"]
F --> F2["ADDITIONAL"]
F --> F3["STANDALONE"]
F --> F4["SUB"]
F --> F5["CAPABILITY"]
```

View File

@@ -0,0 +1,98 @@
# Runtime 输入与模块调度
本文说明外部输入如何经由 Gateway 进入 `AgentRuntime`,以及 `AgentRuntime` 如何按 `source` 聚合输入、去重、debounce 并调度 Running module。
## Gateway 与输入提交
Gateway 负责把外部输入转换成 `RunningFlowContext`,再提交给 `AgentRuntime``AgentRuntime` 不直接感知 WebSocket 等具体输入协议。
```mermaid
flowchart TD
A["外部输入\nWebSocket / 其他 Gateway"] --> B["AgentGateway.receive(inputData)"]
B --> C["parseRunningFlowContext(inputData)"]
C --> D["AgentRuntime.submit(context)"]
D --> E["按 context.source 聚合输入"]
E --> E1["latestContextsBySource[source]\n旧 context 与新 context mergedWith"]
E --> E2["sourceVersions[source] + 1"]
E --> E3["sourceQueue 加入 source\n队列内 source 不重复"]
E3 --> F{"当前是否正在执行同一 source?"}
F -->|是| G["currentExecutingContext.status.interrupted = true"]
F -->|否| H["发送 wakeSignal"]
G --> H
H --> I["AgentRuntime 后台协程消费 wakeSignal"]
I --> J["drainQueue()"]
J --> K["executeSource(source)"]
```
## 模块运行时
`AgentRuntime` 采用按 `source` 聚合的异步执行模型。同一个 `source` 的连续输入会合并为最新的 `RunningFlowContext`;如果新输入到达时该 `source` 正在执行,当前上下文会被标记为 interrupted当前轮结束后 runtime 会从 Running module 链头重新执行最新合并后的上下文。
```mermaid
flowchart TD
A["AgentRuntime 后台协程"] --> B["收到 wakeSignal"]
B --> C["drainQueue()"]
C --> D["取 sourceQueue.firstOrNull()"]
D --> E{"是否存在 source?"}
E -->|否| Z["返回,等待下一次 wakeSignal"]
E -->|是| F["executeSource(source)"]
F --> G["awaitDebouncedExecution(source)"]
G --> G1{"debounceWindow > 0?"}
G1 -->|是| G2["等待 debounceWindow"]
G2 --> G3{"sourceVersions 是否变化?"}
G3 -->|变化| G2
G3 -->|稳定| H["构造 SourceExecution(context, version)"]
G1 -->|否| H
H --> I["标记 currentExecutingSource/context"]
I --> J["executeTurn(context)"]
J --> K{"runningModules 是否为空?"}
K -->|是| L["refreshRunningModules()"]
K -->|否| M["按 order 遍历 Running modules"]
L --> M
M --> N["过滤 maskedModules"]
N --> O["按 order 分组并排序"]
O --> P["同一 order 内 coroutineScope + async 并发执行"]
P --> Q["module.execute(runningFlowContext)"]
Q --> R{"context.status.interrupted?"}
R -->|是| S["本轮中断"]
R -->|否| T["本轮完成"]
S --> U["检查 latest version"]
T --> U
U --> V{"执行期间是否有新输入或版本变化?"}
V -->|是| W["保留 source\n从链头重新执行最新 merged context"]
W --> G
V -->|否| X["清理 latestContextsBySource/sourceQueue/sourceVersions"]
X --> Z
```
Running module 的执行顺序由 `module.order()` 决定。order 较小的组先执行,同一 order 内的模块并发执行。
```mermaid
flowchart LR
A["Running modules from AgentContext.modules"] --> B["过滤 maskedModules"]
B --> C["按 module.order() 分组"]
C --> D["order 小的组先执行"]
D --> E1["order = 10"]
D --> E2["order = 20"]
D --> E3["order = 30"]
E1 --> F1["同组模块并发执行"]
F1 --> E2
E2 --> F2["同组模块并发执行"]
F2 --> E3
E3 --> F3["同组模块并发执行"]
F3 --> G["所有 order 执行完成"]
```

View File

@@ -0,0 +1,50 @@
# 关闭流程
本文说明 Partner 在 JVM 终止时的关闭顺序。
关闭阶段由 `AgentContext` 安装到 JVM 的 shutdown hook 统一触发。生命周期 Hook 与注解式 `@Shutdown` Hook 是两套机制:前者用于框架级收尾,如关闭 Gateway、保存状态、关闭配置监听后者用于模块、额外组件与 Capability Core 自己声明的关闭逻辑。
当前关闭顺序为:
1. `preShutdownHooks`
2. `RUNNING`
3. `ADDITIONAL`
4. `STANDALONE`
5. `SUB`
6. `CAPABILITY`
7. `postShutdownHooks`
```mermaid
flowchart TD
A["JVM 收到终止信号"] --> B["Runtime.addShutdownHook 触发"]
B --> C["AgentContext.computeInstances()"]
C --> C1["收集 Running module 实例"]
C --> C2["收集 Standalone module 实例"]
C --> C3["收集 Sub module 实例"]
C --> C4["收集 additional component 实例"]
C --> C5["收集 capability core 实例"]
C1 --> D["执行 preShutdownHooks"]
C2 --> D
C3 --> D
C4 --> D
C5 --> D
D --> D1["AgentGatewayRegistry.close()"]
D1 --> D2["停止所有 running gateway channel"]
D2 --> D3["AgentRuntime.unregisterResponseChannel(channel)"]
D3 --> D4["默认响应通道恢复为 LogChannel"]
D --> E["执行 @Shutdown: RUNNING"]
E --> F["执行 @Shutdown: ADDITIONAL"]
F --> G["执行 @Shutdown: STANDALONE"]
G --> H["执行 @Shutdown: SUB"]
H --> I["执行 @Shutdown: CAPABILITY"]
I --> J["执行 postShutdownHooks"]
J --> J1["StateCenter.save()"]
J1 --> J2["TraceSinkRegistry.close()"]
J2 --> J3["ConfigCenter.close()"]
J3 --> K["关闭流程结束"]
```

View File

@@ -0,0 +1,55 @@
# Agent 启动流程
本文说明 `Agent.newAgent(appClass).launch()` 的外层启动顺序。
`Agent.launch()` 负责拉起基础单例、注册配置参与者、注册 Gateway、安装关闭钩子、添加外部模块目录并启动注册工厂。组件扫描、模块实例化和能力注册的细节见 [注册链](register-chain.md)。
```mermaid
flowchart TD
A["Agent.newAgent(appClass).launch()"] --> B["加载基础单例<br/>ConfigCenter / StateCenter"]
B --> C["注册 ExceptionReporter"]
C --> D
subgraph D["注册 Configurable"]
direction TB
D1["LogAdviceProvider.register()"]
D2["ModelRuntimeRegistry.register()"]
D3["AgentGatewayRegistry.register()"]
D4["应用传入的 Configurable.register()"]
end
D --> E["注册 AgentGatewayRegistration"]
E --> F
subgraph F["注册关闭钩子"]
direction TB
F1["preShutdown<br/>AgentGatewayRegistry.close()"]
F2["preShutdown hooks"]
F3["postShutdown<br/>StateCenter.save()"]
F4["postShutdown<br/>TraceSinkRegistry.close()"]
F5["postShutdown<br/>ConfigCenter.close()"]
F6["postShutdown hooks"]
F1 --> F2
F3 --> F4 --> F5 --> F6
end
F --> G["添加外部模块扫描目录<br/>resources/module"]
G --> H["启动注册工厂<br/>AgentRegisterFactory.launch(application package)"]
H --> I
subgraph I["初始化配置系统"]
direction TB
I1["ConfigCenter.initAll()<br/>初始化已注册的 Configurable"]
I2["触发各 Configurable.init(config, json)"]
I3["ConfigCenter.start()<br/>启动配置监听"]
I1 --> I2 --> I3
end
I --> K["Agent 启动完成"]
```
Gateway 的实际 `launch()` 不在 `AgentGatewayRegistration.register()` 中直接发生。Gateway registration 只把可用通道注册到 `AgentGatewayRegistry`;真正的通道创建、启动和默认响应通道设置发生在 `ConfigCenter.initAll()` 阶段,由 `AgentGatewayRegistry.init()` 根据 `gateway.json` 执行。