Upsonic 是什么 · 全景与阅读地图
30 秒导读: Upsonic 是一个 Python 的自主 agent 框架(
pyproject.toml里自称 "Agent Framework For Fintech")。你只用两个东西——Agent(谁来干)和Task(干什么)——调一次print_do/do就能跑起来。它的价值不在"调用模型",而在把一次运行拆成一条 24 步的可插拔管线:记 忆、系统提示、工具、安全策略、模型调用、可靠性校验、落库,每一步各司其职。本页是全库的门厅:先讲清它是什么、大概怎么转,再给一张"该读哪一章"的地图。
1. 这是什么(零基础也能懂)
一句话定义。 Upsonic 是一个用 Python 写 AI agent 的框架:你声明一个任务,交给一个 agent,它自己去调用大模型、(必要时)调用工具、把结果整理好还给你。
解决谁的什么问题。 假设你想让一个 AI "分析服务器日志、找出异常模式",或者"分析当前市场行情"。你不想手写"拼 prompt → 调 OpenAI → 解析返回 → 再调一次工具 → 校验结果"这一整套胶水代码。Upsonic 把这套胶水固化成一条标准管线,你只描述"要做什么",剩下的流程它替你跑完。
它对外提供的能力(顶层导出)。 包只在顶层暴露少数几个类,其余都要从子模块导入——这份"白名单"本身就是最好的功能清单:
| 顶层类 | 白话职责 | 相关章 |
|---|---|---|
Agent(别名 Clanker) | 传统 agent:一次任务→一次(多轮工具)应答 | 01 |
AutonomousAgent | 自主 agent:在受限工作区里持续用文件/shell 工具干活 | 06 |
Task | 一次要做的事的声明式描述 | 01 |
Team | 多智能体协作与委派 | 代码地图 → team/ |
Graph | 把多个任务/agent 串成有向流程 | 代码地图 → graph/ |
KnowledgeBase | RAG / 文档知识库 | 代码地图 → knowledge_base/ |
Chat / Direct / Simulation / RalphLoop | 会话封装 / 裸模型直调 / 仿真 / 自主开发循环 | 06 |
真源码:这份白名单在 src/upsonic/__init__.py:145-159(__all__),且通过 __getattr__(src/upsonic/__init__.py:105-143)惰性加载——用到哪个类才 import 哪个,避免一上来就拖入重依赖。
用起来什么样(最小可用示例)
传统 agent —— 建 Agent、建 Task、print_do 触发(源自 README):
from upsonic import Agent, Task
agent = Agent(model="anthropic/claude-sonnet-4-5", name="Stock Analyst Agent")
task = Task(description="Analyze the current market trends")
agent.print_do(task) # 跑一次并把结果打印出来
自主 agent —— 只多给一个 workspace,所有文件/shell 操作被限制在这个目录内(源自 README):
from upsonic import AutonomousAgent, Task
agent = AutonomousAgent(
model="anthropic/claude-sonnet-4-5",
workspace="/path/to/logs", # 文件/shell 操作只能落在这里,路径穿越与危险命令被拦
)
task = Task("Analyze server logs and detect anomaly patterns")
agent.print_do(task)
两段代码的形状一模一样:建 agent → 建 task → 一个动词触发。这就是 Upsonic 想给你的直觉。
触发动词有四个变体,区别只在"同步/异步"和"是否打印":
| 方法 | 同步/异步 | 是否打印结果 | 源码 |
|---|---|---|---|
do | 同步 | 否(返回内容) | src/upsonic/agent/agent.py:4074 |
print_do | 同步 | 是 | src/upsonic/agent/agent.py:4129 |
do_async | 异步 | 否 | src/upsonic/agent/agent.py:3649 |
print_do_async | 异步 | 是 | src/upsonic/agent/agent.py:4176 |
同步版其实是异步版的薄封装:do 把字符串转成 Task 后,直接把 do_async(...) 丢进一个常驻后台事件循环里跑(src/upsonic/agent/agent.py:4118-4127,走 _run_in_bg_loop,见 agent.py:37)。所以真正的主线只有一条:do_async。
一句话直觉。 把 Upsonic 想成"声明式 Task + 可插拔管线":Task 只说"做什么"(像一张工单),Agent 不亲自写流程,而是把这张工单送上一条固定的 24 步流水线(Pipeline),流水线每一站负责一件事,跑到终点就有结果。你能替换/开关某些站(记忆、可靠性、安全),但不用重写主流程。
2. 顶层全景(它大概怎么转)
怎么读这张图: 从上到下是一次 do_async 的数据流。Agent 是门面,真正干活的是中间那条 Pipeline;管线在需要时向右侧的三个横向子系统(模型层 / 工具 / 安全 & 记忆)借力。
你的代码
Agent(...).print_do(Task(...))
│
▼
┌───────────────┐ 同步→异步的唯一入口
│ do / print_do │──► do_async() agent.py:3649
└───────────────┘ │ 建 run_id、开 OTel span、推 usage scope
▼
_do_async_pipeline() agent.py:3898
│ 按 timeout/streaming 选管线,交给 PipelineManager
▼
┌──────────────────────────────────────────┐
│ 24 步 Pipeline(主线) │ _create_direct_pipeline_steps
│ 初始化 → 存储 → 缓存 → 选模型 → 装工具 │ agent.py:4650-4675
│ → 载记忆 → 拼系统提示 → 建上下文(RAG) │
│ → 用户策略 → 拼消息 → ★调模型 → 处理响应 │
│ → 反思 → 可靠性校验 → agent 策略 → 落库 │
└───────┬───────────────┬──────────────┬────┘
│ │ │
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌──────────────────┐
│ 模型层 │ │ 工具系统 │ │ 安全 / 记忆 / 存储 │
│ 20+ 家 │ │ 自定义/MCP │ │ Policy / Memory │
│ infer_ │ │ /HITL/编排 │ │ / Storage │
│ model() │ │ │ │ │
└───────────┘ └───────────┘ └──────────────────┘
models/ tools/ safety_engine/
memory/ storage/
部件一句话职责:
| 部件 | 干什么 | 在哪(目录/符号) |
|---|---|---|
Agent / Clanker | 门面:持有配置,暴露 do/print_do,不亲自写流程 | src/upsonic/agent/agent.py:150(class Agent),agent.py:5424(Clanker = Agent) |
Task | 声明式工单:描述、工具、响应格式、上下文、运行态 | src/upsonic/tasks/tasks.py:21(class Task) |
do_async | 真正的运行入口:建 run_id、开 OTel、推 usage 作用域,再委派管线 | src/upsonic/agent/agent.py:3649 |
_do_async_pipeline | 按 timeout/partial_on_timeout 选"直连/流式/带超时"三种管线之一 | src/upsonic/agent/agent.py:3898 |
PipelineManager | 顺序执行步骤列表,支持从某一步 resume(HITL) | src/upsonic/agent/pipeline/manager.py:41,execute 在 :230 |
24 步 steps | 一次运行被拆成的原子站点,各司其职 | src/upsonic/agent/agent.py:4650-4675 |
| 模型层 | 把 "provider/model" 字符串解析成可调用模型对象 | src/upsonic/models/__init__.py:2064(infer_model) |
主线走一遍(高层,不进代码)
- 你调
agent.print_do(task)—— 同步入口把字符串转成Task,把工作丢给do_async。 do_async为这次运行发一个run_id、开一个 OpenTelemetry span、把 agent/task 的用量作用域压栈,然后调_do_async_pipeline(agent.py:3819)。_do_async_pipeline看参数选管线:没超时走直连管线(24 步),要"超时返回已生成的部分"就走流式管线(agent.py:3911-4009)。PipelineManager.execute从start_step_index开始,逐站执行。第 14 站ModelExecutionStep才真正调模型;其前是准备(记忆/提示/工具/策略),其后是收尾(响应处理/反思/可靠性/落库)。- 终点把结果写进
AgentRunOutput;do_async收尾时打印指标、弹出作用域,把内容(或完整 output)还给你。
想看这 24 步逐站讲清楚,去 02 一次运行如何跑完 24 步管线。
一个易错点: 直连管线是 24 步(索引 0–23,
agent.py:4650-4675),流式管线是 22 步(_create_streaming_pipeline_steps,agent.py:4724-4747,用StreamModelExecutionStep等替换掉直连版的若干步)。全景图与本页所说"24 步"均指默认的直连管线。
3. 阅读地图(该按什么顺序读)
本页是 Layer 0(这是什么)+ Layer 1(顶层全景)。再往下,每个子系统各有一章,按"由浅入深"排:
- 先建立主抽象的直觉 → 01-agent-and-task.md:
Agent与Task各自装了什么、边界在哪。读完你才知道那张工单和那个门面里到底有什么字段。 - 再读主线(核心,务必读) → 02-execution-pipeline.md:24 步管线逐站讲,
PipelineManager怎么调度、HITL 怎么从中间 resume。这是整个框架价值密度最高的一章。 - 然后按需下钻横向子系统:
- 模型怎么来 → 03-model-layer.md(
infer_model如何把字符串变成 20+ 家 provider 的可调用模型)。 - 手脚怎么长 → 04-tools-system.md(自定义
@tool、MCP、人在环 HITL、工具编排)。 - 护栏怎么设 → 05-safety-engine.md(
Policy/Rule/Action,用户侧与 agent 侧两道策略)。
- 模型怎么来 → 03-model-layer.md(
- 最后看自主形态 → 06-autonomous-and-ralph.md:
AutonomousAgent的受限工作区与RalphLoop自主开发循环。
如果你只有 10 分钟: 读本页 + 02 的管线总表即可讲清"Upsonic 是做什么的、核心原理是什么"。
4. 全库代码地图(导航索引)
按"先主线、后子系统"排。优先用符号名 grep(比行号抗上游漂移)。前 8 行是本组各章深讲的主题;后半是本页不展开、但你迟早会碰到的相邻子系统,作为广度索引点名指向对应目录。
4.1 主线与两个主抽象(本组各章深讲)
| 主题 | 文件路径 | 符号名 |
|---|---|---|
| 顶层公共导出(白名单 + 惰性加载) | src/upsonic/__init__.py | __all__、__getattr__、_lazy_import |
| Agent 门面(主 agent 类) | src/upsonic/agent/agent.py | class Agent、Clanker = Agent |
| 同步触发(薄封装) | src/upsonic/agent/agent.py | do、print_do、_run_in_bg_loop |
| 异步主入口 | src/upsonic/agent/agent.py | do_async |
| 选管线并执行 | src/upsonic/agent/agent.py | _do_async_pipeline |
| 24 步 / 22 步管线装配 | src/upsonic/agent/agent.py | _create_direct_pipeline_steps、_create_streaming_pipeline_steps |
| 管线调度器 | src/upsonic/agent/pipeline/manager.py | class PipelineManager、execute、execute_stream |
| 单步基类 | src/upsonic/agent/pipeline/step.py | PipelineStep、execute、execute_stream |
| 任务工单 | src/upsonic/tasks/tasks.py | class Task |
| 裸模型直调门面 | src/upsonic/direct.py | class Direct |
4.2 横向子系统(对应各深入章)
| 子系统 | 目录 | 入口符号 / 说明 | 章 |
|---|---|---|---|
| 模型层(20+ provider) | src/upsonic/models/ | infer_model(__init__.py)、model_registry.py、各家 openai.py/anthropic.py… | 03 |
| 工具系统 | src/upsonic/tools/ | @tool(README 示例)、MCP、编排 | 04 |
| 安全引擎 | src/upsonic/safety_engine/ | policies/、base/、models.py、llm/ | 05 |
| 自主 agent | src/upsonic/agent/autonomous_agent/ | autonomous_agent.py、filesystem_toolkit.py、shell_toolkit.py | 06 |
| Ralph 自主开发循环 | src/upsonic/ralph/ | loop.py、phases/、state/、config.py | 06 |
4.3 本页未展开的相邻子系统(广度索引,点名指向目录)
这些子系统在全景图右侧被管线"借力",但本组不各自开章深讲。需要时按目录进去看:
| 相邻子系统 | 目录 | 一句话 |
|---|---|---|