跳转至

Architecture cn

Jianmu 采用严格的三层分层架构设计,从底层的事件驱动运行时引擎,到中层的节点组合与行为树编排,再到上层可插拔的能力模块,形成一条清晰的依赖链:运行时引擎负责驱动执行,节点组合负责编排逻辑,能力模块负责提供具体功能。理解这三层的边界和协作方式,是深入掌握 Jianmu 全部子系统的基础。

三层架构全景

在深入各层之前,先用一张图建立全局视角:

graph TB
    subgraph 配置层["配置层 (jianmu.yaml / .env)"]
        CONFIG[Config Loader]
    end

    subgraph 运行时引擎层["运行时引擎层 (Engine)"]
        AGENT[Agent / AgentTeam 外观]
        RUNNER[ReactiveRunner 事件驱动调度器]
        SM[StateManager 类型化状态]
        CTX[RunContext 依赖容器]
        INTERACT[InteractionController 挂起/恢复]
        EVENTS[RuntimeEventBus 事件总线]
    end

    subgraph 节点组合层["节点组合层 (Node)"]
        direction TB
        PRESETS[预设模式: ReAct / Plan-Execute]
        BUILTIN[内置节点: LLM / Tool / Skill / Swarm]
        COMPOSITES[组合节点: Sequence / Selector / LoopUntilSuccess]
        BASE[基类: AsyncNode / Node / JianmuNodeMixin]
        PRESETS --> BUILTIN
        PRESETS --> COMPOSITES
        BUILTIN --> BASE
        COMPOSITES --> BASE
    end

    subgraph 能力模块层["能力模块层 (Capability)"]
        MODEL[Model 模型接入]
        TOOL[Tool 工具系统]
        SKILL[Skill 技能系统]
        GUARD[Guard 防护审批]
        EXEC[Execution 执行沙箱]
        MEMORY[Memory 记忆系统]
        SWARM[Swarm 多Agent]
        MCP[MCP 外部协议]
        RAG[RAG 知识检索]
        TELE[Telemetry 遥测]
    end

    CONFIG --> AGENT
    AGENT --> RUNNER
    RUNNER --> SM
    RUNNER --> CTX
    RUNNER --> INTERACT
    RUNNER --> EVENTS
    RUNNER --> BASE
    PRESETS --> MODEL
    PRESETS --> TOOL
    PRESETS --> GUARD
    BUILTIN --> MODEL
    BUILTIN --> TOOL
    BUILTIN --> SKILL
    BUILTIN --> SWARM
    BUILTIN --> GUARD
    BUILTIN --> EXEC
    BUILTIN --> MEMORY

箭头方向表示依赖关系:运行时引擎驱动节点执行,节点在运行时消费能力模块提供的服务。配置层横切所有层级,提供全局参数默认值。

第一层:运行时引擎 (Runtime Engine)

运行时引擎是 Jianmu 的执行心脏,负责将行为树从初始状态驱动到终态(SUCCESS 或 FAILURE)。核心组件包括:

ReactiveRunner —— 事件驱动的 tick 调度器

ReactiveRunner 是整个框架最底层的执行驱动器。它绑定一棵 py_trees 行为树、一个 StateManager 状态管理器、以及一个可选的 RunContext 依赖容器。在初始化阶段,Runner 遍历整棵树的所有节点,通过 inject_runtime_deps() 向每个 Jianmu 原生节点注入运行时依赖(RunContext、StateManager、wake_up 回调)。

Runner 提供三个核心执行入口:

入口 语义 适用场景
tick_once() 执行一次同步 tick 最低层 API,交互式单步调试
step() 一次异步 tick + step 级状态处理 TUI / Studio 等交互应用
run() 驱动树直到终态 标准 Agent 执行

Runner 内部使用 asyncio.Event 机制实现事件驱动的唤醒:当状态变化或异步节点完成时,通过 wake_up 回调触发 tick 信号,Runner 收到信号后执行下一轮 tick。这种设计避免了忙轮询(busy-wait),实现高效的异步调度。

StateManager —— 类型化状态管理

StateManager 是线程安全的状态容器,基于 Pydantic Schema 提供编译时类型校验和运行时状态合并。它支持三种关键机制:

  • Reducer 合并:通过 Annotated 标注自定义合并函数,实现增量更新而非全量覆盖
  • Ephemeral 字段:通过 Ephemeral("step"|"run"|"call") 标注临时字段,在指定粒度自动重置
  • Change Listener:状态变更时通知订阅者(如 Runner),触发行为树重新 tick
class AgentState(BaseModel):
    task: str = ""
    final_answer: Annotated[str | None, Ephemeral("run")] = None
    scratchpad: Annotated[list[str], Ephemeral("step")] = []

RunContext 与依赖注入

RunContext 是运行时依赖容器,承载不应序列化到状态中的共享服务对象:模型客户端、审批管理器、沙箱句柄、约束配置等。InjectPayload 将 RunContext、StateManager 和 wake_up 回调统一打包,由 Runner 注入每个节点。

@dataclass
class RunContext:
    model_client: Any = None
    approval_manager: Optional[ApprovalManager] = None
    sandbox: Optional[Any] = None
    constraints: Optional[Constraints] = None
    runtime: Optional[Any] = None
    prompt_runtime: Optional[PromptRuntimeContext] = None
    runtime_event_bus: Optional[RuntimeEventBus] = None

InteractionController —— 挂起与恢复

运行时引擎内置完整的挂起/恢复协议,支持三种挂起类别:审批等待(REQUIRE_APPROVAL)、用户输入等待(REQUIRE_USER_INPUT)、外部执行等待(REQUIRE_EXTERNAL_EXECUTION)。挂起记录(SuspensionRecord)序列化到状态中,支持跨进程恢复。

RuntimeEventBus —— 运行时事件总线

RuntimeEventBus 是线程安全的内存事件总线,发布 RuntimeEvent 事件(如 reply.started、tool.call.completed、execution.failed)。上层应用(TUI、Studio)通过订阅这些事件实现 UI 实时更新。

Agent 与 AgentTeam 外观

Agent 和 AgentTeam 是面向用户的外观类,封装了 Runner 的构造、配置默认值解析、以及 Checkpoint 检查点接线。用户通常不直接操作 ReactiveRunner,而是通过 Agent 外观来运行单 Agent,通过 AgentTeam 来编排多 Agent 协作。

外观类 封装对象 用途
Agent ReactiveRunner + StateManager + Checkpointer 单 Agent 执行
AgentTeam AgentRuntime + 角色注册 + 工具提供者 多 Agent Swarm 协作

第二层:节点组合 (Node Composition)

节点层是行为树编排的构建块,处于运行时引擎和能力模块之间的桥梁位置。节点从引擎层接收注入的依赖(RunContext、StateManager),在 tick 时调用能力模块的服务。

基类体系

Jianmu 的节点基类建立在 py_trees 之上,形成了清晰的继承层次:

Jianmu 类 py_trees 等价 说明
Node / Behaviour py_trees.behaviour.Behaviour 同步节点基类
AsyncNode / AsyncBehaviour 自定义扩展 异步节点基类,支持 update_async()
Decorator py_trees.decorators.Decorator 装饰器节点基类

JianmuNodeMixin 混入类为所有节点提供统一的端口绑定(port binding)和状态读写能力。每个节点可以声明输入端口(从状态读取数据)和输出端口(将结果写回状态),通过 bind(inputs=..., outputs=...) 完成端口到状态字段的映射。

# 端口绑定示例
node.bind(
    inputs={"messages": "chat_history"},
    outputs={"final_answer": "result"},
)

内置节点分类

内置节点按功能域分为六类:

类别 节点 功能
LLM AgentLLMNode、SimpleLLMNode 模型推理:上下文构建、模型调用、流式输出
工具 ToolExecutor、ToolNode 工具执行:LLM 工具调用解析、Guard 检查、沙箱运行
技能 SkillNode 技能加载与执行
Swarm SpawnAgent、SendMessage、WaitMessage 多 Agent 通信原语
条件 StateCondition 基于状态断言的分支控制
工具 Log、Wait、Timeout、EvaluationNode 辅助节点

每个内置节点在 update_async() 中实现核心逻辑,通过 read_port() / write_port() 与状态交互,通过 self.ctx 访问能力模块。

预设模式:节点组合的模板

预设模式是将内置节点按最佳实践组装成可复用的子树。两种核心预设:

ReAct 预设 (create_react_node):组装 AgentLLMNode → ToolExecutor → StateCondition 的循环体,包裹在 LoopUntilSuccess 中,并附加 Token 预算检查的 abort 钩子。这是工具使用型 Agent 的默认模式。

Plan-Execute 预设 (create_plan_execute_node):实现规划 → 执行 → 审查的三阶段流水线,每个阶段由独立的 LLM 节点驱动。

# ReAct 预设的内部结构
loop_body = Sequence(children=[
    AgentLLMNode(...),    # LLM 推理 + 工具调用
    ToolExecutor(...),    # 执行工具调用
    StateCondition(...),  # 检查 done 标志
])
root = LoopUntilSuccess(child=loop_body, max_iterations=10)

自定义节点

Jianmu 提供两种自定义节点方式:

  1. @node 装饰器:最快的函数转节点方式,函数接收当前状态,返回状态更新字典
  2. 继承 AsyncNode:重写 update_async() 实现完整的异步逻辑
@node
def my_node(state):
    return {"result": process(state.task)}

class MyAsyncNode(AsyncNode):
    async def update_async(self):
        result = await some_io()
        self.write_port("output", result)
        return Status.SUCCESS

组合节点与行为树原语

Jianmu 通过 jianmu.tree 模块重导出 py_trees 的全部组合原语:Sequence(顺序执行)、Selector(优先选择)、Parallel(并行执行)及其装饰器(Inverter、SuccessIsFailure 等)。此外提供 Jianmu 特有的 LoopUntilSuccess,支持带 abort 条件的重试循环。

第三层:能力模块 (Capability Modules)

能力模块层是 Jianmu 最丰富的子系统集合,采用 Protocol 协议驱动设计——每个模块定义抽象接口,支持多种实现,用户可自由替换。各模块之间保持松耦合,通过 RunContext 在运行时组装。

模块全景表

模块 目录 核心抽象 关键实现
模型接入 jianmu/model/ ModelProviderProtocol ModelClient → OpenAI Provider / LiteLLM Provider
工具系统 jianmu/tool/ Tool 基类 @tool 装饰器、ToolSet、ToolProvider、内建工具集
技能系统 jianmu/skill/ SkillRecord、SkillLoader SkillsCatalog(工作空间覆盖内置)、行为树技能 / Prompt 技能
Guard 防护 jianmu/guard/ CheckerProtocol、GuardProtocol GuardEnforcer + 四类检查器(ToolPolicy、RateLimit、Budget、Confirm)
执行沙箱 jianmu/execution/ SandboxRunnerProtocol ToolRunner → LocalSandbox / DockerSandbox
记忆系统 jianmu/memory/ CheckpointerProtocol、ContextBuilderProtocol FileCheckpointer、ContextBuilder、Mem0 长期记忆
消息系统 jianmu/message/ Message StateMessageStore、消息编码/保留策略
Swarm 多Agent jianmu/swarm/ AgentRole、AgentRuntimeProtocol AgentRuntime(邮箱路由、事件总线、生命周期)、AgentTeam 外观
MCP 集成 jianmu/mcp/ - MCPClient、MCPToolProvider、MCP Server
RAG 检索 jianmu/rag/ - Embedder、Retriever、Reranker、KnowledgeBase 流水线
遥测系统 jianmu/telemetry/ - TelemetryHub、多 Sink 输出、Span 追踪

模型接入模块

ModelClient 是统一的模型调用外观,封装了 provider 解析(按凭证可用性自动选择 OpenAI 或 LiteLLM)、重试与 fallback 策略、流式输出、以及遥测埋点。调用路径为:

ModelClient.invoke() → invoke_model() → provider.create_message()
                                              ↓
                                     telemetry span / events

工具系统模块

Tool 抽象基类定义了工具的执行契约:run() 方法实现核心逻辑,execute() 方法提供统一的调用路径(支持注入参数、沙箱委托)。ToolSet 聚合多个工具并生成 LLM function-calling schema。ToolProvider 协议支持动态工具发现(如 Swarm 工具、MCP 工具)。

Guard 防护模块

GuardEnforcer 组合多个检查器形成防护链,按序评估每个工具调用。检查器链默认包含:ToolPolicyChecker(白名单/黑名单)→ RateLimitChecker(频率限制)→ BudgetChecker(Token 预算)→ ConfirmChecker(人工审批)。遇到 DENY 立即阻断,CONFIRM 暂缓并等待审批。

执行沙箱模块

ToolRunner 是工具执行的外观,根据配置选择 LocalSandbox(直接在当前进程执行)或 DockerSandbox(在隔离容器中执行)。每次执行发出 execution.started → execution.completed / execution.failed 生命周期事件。

Swarm 多 Agent 模块

AgentRuntime 是多 Agent 运行时的核心实现,管理 Agent 主机的生命周期(spawn / kill / pause / resume / preempt),提供邮箱路由(SendMessage / WaitMessage 通信原语)、事件总线和快照持久化。AgentTeam 外观封装了 AgentRuntime 的构造和默认值解析。

层级间的数据流

整个架构的运行时数据流清晰分层:

sequenceDiagram
    participant U as 用户代码
    participant A as Agent 外观
    participant R as ReactiveRunner
    participant N as 行为树节点
    participant S as StateManager
    participant C as 能力模块

    U->>A: agent.run(input_data)
    A->>R: runner.run(input)
    R->>S: merge input_data
    loop 事件驱动 tick 循环
        R->>R: tick_signal.wait()
        R->>N: tree.tick() → update_async()
        N->>S: read_port() 读取状态
        N->>C: 调用能力模块 (model_client.invoke / tool.execute)
        C-->>N: 返回结果
        N->>S: write_port() 写入状态
        S-->>R: wake_up() 通知状态变化
        R->>R: tick_signal.set()
    end
    R-->>A: RunResult
    A-->>U: 最终结果

配置层的横切作用

配置系统(jianmu/config/)横切所有三层,由 jianmu.yaml、.env 和代码默认值三重来源合并,通过 get_config() 全局访问。JianmuConfig 包含模型默认值、运行时参数(max_fps、checkpoint 间隔)、路径配置、Prompt 模板、LLM 超参数默认值等。运行时引擎和节点在初始化时从配置中读取默认参数,允许用户在调用时显式覆盖。

阅读建议

本文建立了 Jianmu 三层架构的全局视图。建议按以下顺序深入各子系统:

能力模块各专题则可以在需要时分别查阅,详见导航目录中的"运行时能力模块"和"扩展与集成"分组。