Xun 概览¶
Xun 是一个迷你 LLM 智能体(agent)框架:核心代码约 4100 行(src/xun/*.py,绝大多数为手写),带完整类型注解,Python 3.12+(PEP 695 语法)。它把「模型 + 工具 + 显示层」三件事拆开,用极少的 API 提供一个可运行、可扩展、可嵌入的智能体执行循环。
一句话概括设计目标:用普通函数当工具,用类型系统约束生命周期,用显示层隔离 IO。
主要功能¶
| 功能 | 说明 | 详情 |
|---|---|---|
| 函数即工具 | 普通 Python 函数(含类型注解与 docstring)自动生成 JSON Schema 注册为工具,无需装饰器或基类 | 工具系统 |
| 执行循环 | 流式模型调用 → 工具调用 → 结果回填,直到某一轮不再调用工具;支持 pydantic 结构化输出 | Agent 初始化与执行 |
| 四种会话入口 | xun 终端、xuns Web 服务、xunc 容器、xunx 多用户复用服务 |
安装与入口 |
| 显示层抽象 | 控制台 / Web / 静默三种内置实现,自定义只需实现两个方法 | 显示层与 Web 服务 |
| 子智能体 | agent_run / agent_run_parallel 两个内置工具,支持自定义 getter、深度限制、级联取消 |
子智能体与取消 |
| 会话自动压缩 | 先回收旧工具结果,仍超标再转摘要压缩,可递归再压 | 会话与自动压缩 |
| 钩子与会话命令 | 16 个生命周期钩子(多数参数可就地修改);/help、/compact、/policy 等会话命令 |
钩子与会话命令 |
| 扩展系统 | 把 .py 丢进 extensions/ 目录,每个智能体初始化时自动生效 |
扩展系统 |
| 权限策略 | 写操作确认 + 写允许列表 + 命令允许列表 + LLM 风险评估 | 工具系统 |
最主要的设计特点¶
1. 最小表面积的执行核心¶
setup_agent() 返回一个已初始化的智能体,三行代码即可跑通:
from xun import setup_agent
agent = setup_agent(default_tools=True)
print(agent.instruct("What is 2 + 3?").execute().unwrap())
execute() 永远返回 Result,不会抛异常(KeyboardInterrupt 与 CancelledError 除外)。工具函数也只需 return 普通可 JSON 序列化的值或 raise,框架自动包装成 Result。
2. Type-State:把生命周期错误提前到静态检查¶
Agent 对生命周期状态做泛型参数:Agent[T.Uninit] → Agent[T.Init] → Agent[T.Final]。未 initialize() 就 execute()、已 finalize() 还继续用,都会在静态检查阶段被拒绝。详见 Type-State 模式。
3. 执行与显示彻底解耦¶
智能体内部一律通过 display_event() / info() / warning() / error() / get_choice() 输出,具体落地由 DisplayAbstract 决定:同一套逻辑可以是终端文本、Web 聊天事件流,或者完全静默(NullDisplay)。
4. 协作式取消,父取消级联子¶
取消令牌 ChainedEvent 可以挂在父智能体的令牌之下;执行循环在每一步、每个流式增量、每个工具调用前检查。长时间运行的工具自行调用 ctx.agent.check_cancel() 即可获得同样的能力。
5. 扩展是「可信代码」¶
$XUN_HOME/extensions/ 下的源文件在每个智能体初始化时按名称顺序加载,入口固定为 setup_extension(ctx);导入或初始化失败只告警不阻断——像 shell 的 rc 文件一样,简单但拥有完整进程权限。
6. 分级压缩而非一次性截断¶
超阈值时先做廉价的旧工具结果回收(可用 extract_compacted_tool_result 取回原文),仍然超标才升级为一次摘要压缩;摘要之后仍超标则继续再压(默认最多再压 2 次,每轮保留量减半),逐步收敛。
架构一览¶
flowchart TB
ENTRY["会话入口<br/>xun · xuns · xunc · xunx"] --> CORE["Agent 核心<br/>执行循环 + 类型状态 + 钩子"]
CFG["配置与扩展<br/>config.json · extensions"] --> CORE
CORE --> TOOLBOX["工具箱<br/>内置工具 + 子智能体"]
CORE --> CONV["会话<br/>消息历史 + 自动压缩"]
CORE --> DISPLAY["显示层<br/>控制台 · Web · 静默"]
一次 execute() 的时序:
sequenceDiagram
participant U as 调用方
participant A as Agent
participant M as 模型
participant T as 工具
U->>A: instruct("...")
U->>A: execute(schema=None, max_iterations=512)
loop 每一轮迭代
A->>A: check_cancel, before_execution_step(触发自动压缩)
A->>M: chat.completions.create(stream=True)
M-->>A: 文本增量 / 推理增量 / 工具调用
A->>T: call_tool(name, arguments)
T-->>A: Result 结果
A->>A: 写入 assistant 消息与 tool 结果
end
A-->>U: Result[str 或 BaseModel, ErrorInfo]
阅读路径建议¶
本文档对应的版本见页脚标注(站点构建时由 mkdocs.yml 的语言配置注入)。