面向 LLM agent 系统的可嵌入自优化框架。
selfloop 接到一个已有的宿主项目上,自动发现它的可修改资产(prompt、skill、
tool policy、workflow、eval template、memory),把宿主当黑盒运行,基于错误信号
做 taxonomy 归因,用真实 LLM 生成节点级修改,先在沙箱里验证,通过后才写回
——并保留快照,支持一条命令回滚。
整个闭环由 slo 命令行驱动,每次运行都可审计、可复现。框架只依赖 Python 标准库。
- 它解决什么问题
- 核心特性
- 工作原理
- 安装
- 快速上手
- 配置(slo.yaml)
- LLM 配置
- 安全模式
- CLI 命令
- Python API
- 项目结构
- 测试
- 技术栈
- 安全与信任边界
- 参考文献
- 当前状态与边界
人工维护 prompt 和 agent 配置很难规模化:错误只能逐条修补,改 prompt 往往整段重写 (回归风险高),缺少结构化验证,历史经验散落在个人脑子里。多数"自动调优"工具又把 整个 prompt 当一团文本重写,既不可定位、也不可审计。
selfloop 把 badcase → 归因 → 反思 → 编辑 → 验证 → 发布 做成一个可复用的引擎,
通过一份很小的接入契约挂到任意宿主项目上,而不是逼宿主改造成某个固定的 agent 框架。
- 低介入接入:一份
slo.yaml加一条运行命令(或一份已有输出)即可,简单路径下宿主项目零改动。 - 多资产优化:能改
prompt、skill、tool_policy、workflow、rule_config、eval_template,不只是 prompt。 - 黑盒运行:通过命令模板运行宿主,框架从不导入宿主业务代码。
- taxonomy-first 归因:先把错误归类成失败模式,再决定改哪类资产。
- 真实 LLM 在环:归因、反思(Critic → Editor → Verifier)、评估都默认由 LLM 驱动,每一处都有确定性的启发式回退。
- 语义记忆:经验以 Markdown 落盘,按 embedding 余弦相似度检索(无 embedding 时回退到 grep / 关键词)。
- 节点级补丁:修改插入到目标节点附近,而不是盲目追加到文件末尾。
- 沙箱 + 回滚:每次写回前先在复制出的沙箱里验证,并生成快照用于回滚。
- 可审计的运行历史:每次 run 持久化到
.slo/runs/,事后可查看、diff、发布、回滚。 - 优雅降级:LLM 网关不可达时,闭环自动走启发式路径继续运行。
- 零运行时依赖:纯标准库,不引入任何第三方包。
宿主输出 + 错误信号(+ 可选 trace)
│
▼
AdaptiveDataAdapter 归一化 JSONL / JSON / CSV / TSV / 纯文本
│
▼
EmbeddedErrorAnalyzer LLM taxonomy 分类(正则回退)
│ → ArtifactErrorPattern(失败模式)
▼
ArtifactRuleTree 把宿主资产切成可寻址节点
│
▼
MarkdownGrepMemoryBackend 语义召回历史经验(embedding → grep)
│
▼
EmbeddedReflector Critic → Editor → Verifier
│ LLM 写出、节点定向的修改(模板回退)
▼
候选补丁 Candidate
│
▼
SafetyController 复制 → 沙箱打补丁 → 跑宿主 → 门禁
│
▼
LLMJudgeEvaluator 按失败模式给输出打分(启发式回退)
│
▼
写回 + 快照 + 记忆 lesson + 结构化报告
python3 -m venv .venv
.venv/bin/python -m pip install -e '.[dev]'会安装 slo 命令行(入口在 pyproject.toml 声明)。
仓库自带一个故意带缺陷的样板宿主项目:
examples/embedded_multi_agent。它默认是 dry_run,
所以第一次运行是安全、可审查的,不会立即写回。
# 1. 校验接入契约
.venv/bin/slo doctor --strict --config examples/embedded_multi_agent/slo.yaml
# 2. 生成一次可审查的 run(dry_run 不写回)
.venv/bin/slo auto --config examples/embedded_multi_agent/slo.yaml
# 3. 查看 / diff / 发布 / 回滚某一次 run
.venv/bin/slo history --config examples/embedded_multi_agent/slo.yaml
.venv/bin/slo show-run --config examples/embedded_multi_agent/slo.yaml <run_id>
.venv/bin/slo diff-run --config examples/embedded_multi_agent/slo.yaml <run_id>
.venv/bin/slo apply-run --config examples/embedded_multi_agent/slo.yaml <run_id>
.venv/bin/slo rollback-run --config examples/embedded_multi_agent/slo.yaml <run_id>runner 模式(由框架运行宿主):
project:
root: .
name: my-agent-project
runner:
command: "python run_agent.py --input {input_file} --output {output_file}"
timeout: 600 # 可选;单次宿主运行超时秒数(默认 600)
data:
cases: data/cases.jsonl
error_signals: data/errors.jsonl
traces: data/traces.jsonl # 可选;提供 agent/tool 轨迹可做更强归因
artifacts:
auto_discover: true
safety:
mode: dry_run
min_evaluation_score: 0.5 # 可选;写回前的质量门槛
adapters:
path: host_plugin:get_adapters # 可选;高级宿主才需要outputs-only 模式(你提供已有输出,框架不运行宿主):
project:
root: .
name: my-agent-project
data:
outputs: data/outputs.jsonl
error_signals: data/errors.jsonl
artifacts:
auto_discover: true
safety:
mode: dry_runoutputs-only 模式可以生成候选和 diff,但因为没有沙箱运行做验证,
只支持 dry_run / manual_review,不能自动写回。
框架默认开启真实 LLM,对接 OpenAI 兼容的 chat-completions 接口。
网关地址和 API key 没有内置默认值,必须通过环境变量或 .env 文件提供。
最简单的方式是复制示例文件并填入自己的配置:
cp .env.example .env
# 然后编辑 .env,填入 SLO_LLM_BASE_URL 和 SLO_LLM_API_KEY.env 已在 .gitignore 中忽略,绝不会提交;框架启动时用内置的 stdlib 加载器
自动读取它(不依赖 python-dotenv)。真实环境变量优先级高于 .env。
| 变量 | 用途 |
|---|---|
SLO_LLM_BASE_URL |
chat / embeddings base URL(必填,无默认) |
SLO_LLM_API_KEY |
Bearer token(必填,无默认) |
SLO_LLM_MODEL |
chat 模型(默认 qwen3.6-plus) |
SLO_LLM_EMBEDDING_MODEL |
embedding 模型(默认 bge-m3) |
SLO_LLM_ENABLE_THINKING |
true/false |
SLO_LLM_TEMPERATURE |
采样温度(默认 0.2) |
SLO_LLM_TIMEOUT |
单次请求超时秒数(默认 60) |
SLO_LLM_DISABLED |
设为 1 强制走纯启发式路径 |
每个 LLM 调用都是 best-effort:一旦失败(无 key、网络异常、返回无法解析),
对应环节自动回退到确定性启发式,闭环不会卡住。测试套件设置 SLO_LLM_DISABLED=1
以保证离线、确定性运行。
| 模式 | 行为 |
|---|---|
dry_run |
生成候选、沙箱验证、保存报告。不写回。 |
manual_review |
同 dry_run;面向人工 / 外部发布流程。 |
auto_with_rollback |
沙箱验证且评估门槛通过后写回,并生成回滚快照。 |
| 命令 | 说明 |
|---|---|
slo init |
生成起步 slo.yaml。 |
slo doctor [--strict] |
校验接入契约;--strict 下有 warning 即返回非 0。 |
slo scan |
打印发现的资产。 |
slo run |
运行宿主一次并打印结果。 |
slo auto |
跑完整闭环,并把报告存到 .slo/runs/。 |
slo history |
列出已保存的 run。 |
slo show-run <id> |
打印某次 run 报告。 |
slo diff-run <id> |
打印该 run 将应用的 unified diff。 |
slo apply-run <id> |
重新验证并发布一次已审查的 run。 |
slo rollback-run <id> |
用该 run 的快照回滚宿主。 |
slo rollback <rollback_id> |
用原始快照 id 回滚。 |
from selfloop import EmbeddedConfig, OptimizerAgent
config = EmbeddedConfig.load("slo.yaml")
report = OptimizerAgent(config).auto()
print(report.status) # validated / applied / evaluation_failed / ...复杂宿主可以通过 EmbeddedAdapters 注入自定义的 scanner / runner / evaluator /
artifact writer;也可以按层导入,例如
from selfloop.reasoning import EmbeddedReflector。
.
├── pyproject.toml # 打包 + slo 入口
├── README.md
├── LICENSE
├── reference_architecture.md # 中文参考架构文档
├── .env.example # LLM 网关配置模板(复制为 .env 使用)
├── selfloop/ # 可导入的包(import selfloop),按职责分层:
│ ├── foundation/ # 数据模型、配置、扩展点 adapters
│ ├── llm/ # LLM provider(best-effort,可降级)
│ ├── discovery/ # 资产扫描、节点寻址、数据接入
│ ├── reasoning/ # 归因、反思、评估、记忆
│ ├── execution/ # 黑盒运行、补丁应用、沙箱与回滚
│ ├── pipeline/ # OptimizerAgent、运行历史、插件加载
│ └── cli.py # slo 命令入口
├── examples/
│ ├── embedded_multi_agent/ # 带缺陷的样板宿主(multi-agent 演示)
│ └── dialogue_to_config/ # 第二个样板宿主(对话 → 配置)
└── tests/ # 测试套件
每一层都有自己的 __init__.py 导出,既能从顶层
from selfloop import OptimizerAgent 使用,也能按层导入
from selfloop.reasoning import EmbeddedReflector。
.venv/bin/python -m pytest -q测试默认离线运行(SLO_LLM_DISABLED=1),并通过 CLI 把两个样板宿主项目端到端跑一遍
(doctor → auto → diff-run → apply-run → rollback-run)。
- 语言:Python ≥ 3.9。
- 运行时依赖:零。整个框架只用 Python 标准库(
pyproject.toml的dependencies = [])。 - LLM 传输:用
urllib.request直连 OpenAI 兼容的/v1/chat/completions与/v1/embeddings——不依赖任何 SDK,响应有大小上限。 - 配置解析:内置极小的 YAML 子集解析器(不依赖 PyYAML),同时支持 JSON,数值字段有类型校验。
- 资产寻址:基于正则的 Markdown / YAML 节点切分(
discovery/artifact_tree.py)。 - 记忆:Markdown 文件 + embedding 余弦相似度(
bge-m3),并有rg/ grep 与纯 Python 关键词的多级回退。 - 沙箱:
shutil.copytree+subprocess(带超时)隔离运行宿主,验证后自动清理。 - 测试:
pytest。
这一点对使用很重要:
runner.command会被当作子进程执行,adapters.path会被importlib导入并执行其模块顶层代码。两者都来自宿主项目自己的slo.yaml。因此 不要对你不信任的仓库运行slo——这等价于运行该仓库配置的命令 / 代码。- 框架只把宿主当黑盒:不导入宿主业务代码(adapter 插件除外,那是宿主主动声明的扩展点)。
- 写回前必须经过沙箱验证;回滚会校验快照路径不会逃逸出项目根目录。
- 子进程运行有超时(
runner.timeout,默认 600s),网关响应有大小上限,文件读取对非 UTF-8 与 IO 错误做了容错——单个坏文件或挂起的命令不会让整个流程崩溃。 - 密钥只从环境变量 /
.env读取,仓库里没有任何硬编码网关地址或 key;.env已被忽略。
selfloop 是这些方法的工程化适配,不是论文复现。下面标注每个思想在代码里的落点。
- ACE(Agentic Context Engineering)——Critic → Editor → Verifier,增量 grow-and-refine。→
selfloop/reasoning/reflection.py。 - MemAPO——成功策略记忆 + 错误模式记忆。→
selfloop/reasoning/memory.py(embedding 语义检索 + grep / 关键词回退)。 - ProTeGi / APO——先产出"文本梯度"再编辑。→
TextGradient(selfloop/foundation/models.py),Critic 阶段产出。 - TextGrad——把反馈抽象成可传播的文本梯度对象。→
TextGradient数据结构,"先梯度后编辑"链路。 - ETGPO——taxonomy-first,先归类再优先修高频失败。→
selfloop/reasoning/analysis.py(fingerprint 显式含 taxonomy)。 - OPRO / GEPA——多候选搜索 + Pareto 选择。→ 列为后续方向,尚未实现。
各方法只吸收了与本项目目标相关的部分;完整的 context curation、computation graph、 candidate pool、beam search、bandit ranking 等均不在当前范围内。
完整的架构走读见 reference_architecture.md。
已实现并有测试覆盖:
- 低介入
slo.yaml接入、自动资产扫描、多格式数据接入。 - 黑盒运行、taxonomy-first 归因、节点级补丁。
- 真实 LLM 归因 / 反思 / 评估,embedding 语义记忆,且都带启发式回退。
- 沙箱验证、评估门禁、写回、回滚快照、run history、CLI。
尚未实现:
- 多候选搜索 / candidate-pool 排序(OPRO / GEPA 风格)。
- 比"行 / heading / key 级插入"更细的 AST 结构化编辑。
- 长驻服务模式与线上监控 / 自动熔断。
MIT,见 LICENSE。