跳转至

生命周期与类型状态

Agent 以生命周期状态为类型参数(Type-State Pattern):状态写泛型参数里, 迁移方法返回下一个状态,于是「没初始化就执行」「已终结还改提示」这类错误在静态检查阶段就报错, 而不是等到运行时炸。

状态

状态类在 agent_lifecycle.py 中定义,并以 Agent.T 的形式对外暴露:

标注 含义 可用操作
Agent[T.Uninit] 已构造未初始化(裸 Agent 的默认状态) initialize()、system()、instruct()、挂部件
Agent[T.Init] 已初始化 execute()、execute_command()、info() / get_choice() 等显示方法
Agent[T.Final] 已终结,不可再用 只有 finalize() 的幂等空操作
Agent[T.Alive] Uninit \| Init,仍可用 构建类方法 system() / instruct()
Agent[T.Any] 任意状态,用于收参数的函数签名 —
stateDiagram-v2
    [*] --> Uninit: Agent(...)
    Uninit --> Init: initialize()
    Init --> Final: finalize()
    Uninit --> Final: finalize()
    Final --> Final: finalize()(空操作)
    note right of Final: initialize() 报错 RuntimeError

必须重新绑定

迁移方法返回的就是同一个对象,但类型不同,所以要重新赋值:

agent = Agent()
agent = agent.initialize()      # Agent[T.Init]
agent = agent.finalize()        # Agent[T.Final]

不重新绑定的话静态类型会停在旧状态,检查能力就失效了。system() 与 instruct() 对状态是透明的 (泛型约束在 Agent[T.Alive] 上),它们返回 self,因此可以随意链式拼接,但接到 Final 上会报错。

from typing import reveal_type, TYPE_CHECKING

agent_u = Agent()
if TYPE_CHECKING: reveal_type(agent_u)      # Agent[Agent.T.Uninit]

agent_i = agent_u.initialize()
if TYPE_CHECKING: reveal_type(agent_i)      # Agent[Agent.T.Init]

agent_f = agent_i.finalize()
if TYPE_CHECKING: reveal_type(agent_f)      # Agent[Agent.T.Final]

# 静态检查会拦下这两处:
# agent_u.execute()   # Cannot access attribute "execute" for class "Agent[Agent.T.Uninit]"
# agent_f.system("hi")  # Cannot access attribute "system" for class "Agent[Agent.T.Final]"

with 语句

__enter__ 调用 initialize(),__exit__ 调用 finalize(),忘记收尾也不会漏掉解绑:

with Agent() as agent:
    result = agent.instruct("Hi~").execute()
    print(result.unwrap())

还有一层兜底:构造时注册了 weakref.finalize,被丢弃且已初始化的智能体在回收时自动终结, 显示层不会一直以为自己还挂着一个活着的智能体。

运行时同样有守卫

类型标注只在静态检查时生效,运行时也有对应的检查:

位置 行为
execute() / execute_command() 未初始化时抛 RuntimeError,提示调用 initialize() 或使用 with
initialize() 已初始化时直接返回自身(幂等);已终结时抛 RuntimeError
finalize() 已终结、或从未初始化的智能体上是空操作(只迁移状态,不触发钩子与解绑)
Agent.is_initialized(agent) / Agent.is_finalized(agent) TypeGuard 静态方法,用来在运行时收窄类型

is_initialized 之所以是静态方法而不是属性,是因为 Pylance 只接受至少带一个显式参数的自定义 TypeGuard。

这套设计挡住的四类错误

  1. 未初始化就执行:扩展没加载、显示层没绑定、工作区没准备、模型没探测。
  2. 终结后继续用:显示层已解绑,事件与回复会静默丢失。
  3. 重复初始化 / 忘记收尾:两个迁移方法都幂等,with 与 weakref.finalize 负责兜底。
  4. 变量类型过期:迁移方法返回新状态,逼你重新绑定,后续调用点的类型始终与现实一致。

派生时的状态

Agent.inherit(parent, ...) 返回 Agent[T.Uninit]——派生出来的子智能体需要自己 initialize(), 这样才能重放扩展、绑定显示层、安装压缩策略。派生细节见 子智能体派生。