术语表¶
这一页是 flower 文档的术语基准。同一个东西在全站只有一个叫法,中英对照在这里定死 —— 翻译版本也照这张表走。
每条给三样东西:这个词指什么、它在代码里是什么、它不是什么。第三样往往最有用, 因为多数误解来自把一个词当成了另一个。
框架与运行¶
长程¶
long-horizon
一次运行跨越数小时到数天、跨越多次会话、跨越进程重启,而不是一问一答。flower 的所有机制都是 为了让这种运行不半途散架。
实测参照:HT001 连续跑了 10.4 小时。
运行¶
run
一次 Runtime 从开始到结束的完整过程。一次运行内部可以有多个步骤、多个会话, 可以中断后接续。运行的记录落在 runs/manifest.json 和 runs/sessions.db。
不是:一次 API 调用,也不是一个会话。
会话¶
session
模型侧的一条上下文。有自己的 session_id,可以 resume、可以 fork。一次运行可能烧掉 好几条会话 —— 每次换代就换一条新的。
步骤¶
step · Step
流程里的一个可执行单元。拿到一个上下文字典,跑一个 agent,把结果写回字典。 Step 是一个类,见 Python API。
流程¶
workflow · Workflow
按顺序串起来的一组步骤,外加步骤之间怎么传状态、什么时候提前退出。
框架不提供现成流程
flower 只提供机制。流程是你写的。见设计流程。
角色¶
角色是 flower 对 agent 的分工。每个角色 = 一段注入的规则文本 + 一组工具 + 一组 hook。 五个角色都是工厂函数,见 Python API。
协调者¶
coordinator · coordinator()
主线程上那个 agent。它拆解任务、派活、读报告、做决策,但不动手 —— 拿不到 Write / Edit。基础工具是 Agent、TodoWrite、Read (roles.py:27),但那不是最终清单,还会按参数往上加三种:glance=True(默认)加一个 受限的 Bash(只够 git status / ls 这类看一眼就完的命令,由 delegate_guard 把关); 给了提问通道加 inbox 和 ask;手下执行者带了 WebFetch / WebSearch 的话, 这两个也会被并进来 —— allowed_tools 是会话级的,不并的话 subagent 自己调用时 会卡在没人回应的权限审批上(roles.py:513-526)。
角色设定是"一个会用 Claude Code 的人",不是执行者。
不是:一个更聪明的 agent。它和执行者默认用同一个模型档次,省的是上下文,不是模型。
执行者¶
worker · worker()
真正干活的 subagent:写代码、跑测试、查资料。工具是 Read Write Edit Bash Glob Grep WebFetch WebSearch。
回话格式被规则文本约束成四段 —— 结论 / 依据 / 产出 / 未验证,不超过 30 行, 禁止贴文件内容、命令输出、日志和 diff 原文。
确认者¶
clarifier · clarify()
动手之前把需求问清楚的角色。它不做事,只提问,问到清楚为止(没有轮数上限), 最后输出一份需求确认书。见前置确认。
判定者¶
judge · judge()
判"做完了没有"的角色。它做两件事之一:开跑前设定目标(产出目标 + 判定清单), 或者每一轮结束后判定这一轮(产出判定)。见目标看守。
关键:判定者判的是产出物,不是源码。
HT001 里栽过一次:验收标准写的是"在 macOS 终端直接运行",交付的产物 file 一跑是 ELF 64-bit LSB pie executable, ARM aarch64, GNU/Linux,判定却是通过。
两点要说清楚,否则这个例子会被误读:
- 那次判错的不是目标看守 —— HT001 还没有这个机制,判错的是协调者自发派的审计员。
- 默认配置的判定者大概率也会漏掉它。
judge()默认can_run=False,工具只有Read/Glob/Grep—— 它跑不了file,只会去读Makefile看到确实有 Darwin 分支, 然后判达成。
真正管用的是 HT002:判定者开了 judge_can_run,自己跑 file 和 lsof 去看现场,明确避开了这个坑。所以"判产出物"这句话,要靠 can_run=True 才落得了地。
旁路顾问¶
oracle · oracle()
一条只读旁路。运行还在跑的时候,你可以问它"现在到哪了",它看一眼最近事件和工作台 再回答。它说的话不会进入那次运行的上下文 —— 问了不影响运行,答完即弃。
subagent¶
Claude Agent SDK 的概念:主 agent 通过 Agent 工具派出去的子 agent。它有自己的一条 transcript,工具调用和试错都记在那条上,主线程只收到最终报告。
这是 flower 省上下文的第一层,也是省得最多的一层。见上下文经济学。
四个机制¶
前置确认¶
clarify
动手之前先把需求问清楚,冻结成一份需求确认书,再开始执行。 挡的是"做出来不是想要的"。见前置确认。
需求确认书¶
brief · Brief
确认者问完之后产出的文书,恰好四段。后续步骤读它,不再重新猜需求。
不要和任务书混。需求确认书是"人想要什么",任务书是"这个 subagent 这次干什么"。
任务书¶
task brief
协调者派活时写给执行者的那段话。只写这次任务专属的东西 —— 对方已经知道的纪律不要复述。
实测:8/8 份任务书都在复述对方已知的纪律,最短一份 521 字符里只有约 120 字符是任务专属的, 一轮白占约 4.8k 永久上下文。
目标看守¶
goal guard
判定者在每轮结束后独立判定目标达成没有,没达成就打回去接着做。 挡的是"说做完了其实没做完"。见目标看守。
判定¶
verdict · Verdict
判定者一轮判定的结果,恰好三段:结论 / 理由 / 未通过。
结论有三种,ACHIEVED(达成)、NOT_YET(没到)、UNREACHABLE(这个环境验不了)。 后两种是不同的结论 —— "这里没法验"绝对不判通过。
接续¶
continuity
同一个目录再跑一次,自动接上上一次的进度 —— 进程被杀、机器重启也一样。 挡的是"跑几小时崩了从头再来"。见接续。
不要和换代混:接续是跨进程接上一次运行;换代是同一次运行内部换一条新会话。
换代¶
handoff
上下文快满的时候,让当前会话写一份人能读、能改的交接书,然后开一条新会话接手。 挡的是"上下文满了被压成一段摘要"。见换代。
不是 compact。见压缩。
交接书¶
handoff document · Handoff
换代时写的文书,五段:doing(在做什么)、decided(定了什么)、deadends(走不通的路)、 next(下一步)、scene(现场)。
只有 doing 和 next 是必填的 —— 硬性要求"走不通的路"非空会逼模型编造。
压缩¶
compact
Claude Code 的原生做法:上下文满了,把前面的对话总结成一段摘要。
flower 不用它,用换代代替。区别在于:摘要是模型生成的、不可读不可改、丢什么你不知道; 交接书是结构化的、落盘的、你能打开改一行再让它接着跑。
上下文管理¶
主线程¶
main thread
协调者所在的那条会话上下文。它是唯一贯穿整次运行的上下文,所以最需要省。
代码里判定主线程的方式:hook 数据里没有 agent_id。subagent 的 hook 带 agent_id。
工作台¶
workbench · Workbench
落盘的工作目录,三个子目录:
| 目录 | 放什么 |
|---|---|
scripts/ | 要跑第二次的脚本,首行写 # desc: 一句话 |
artifacts/ | 超过 2000 字符的长产出 |
notes/ | 关键决策,一个决策一个文件 |
INDEX.md 是这三个目录的索引,注入到 system prompt 里,所以 agent 每轮都知道手上有什么。
两个入口,两个默认位置
工作台放在哪取决于怎么创建它,这一点容易踩:
| 创建方式 | 工作台根目录 |
|---|---|
Workbench(workspace) —— 也是 starter_flow() / wake_state() 走的路 | <工作区>/.flower |
Runtime(workbench=True) | <run_dir>/workbench(默认 runs/workbench) |
命令行走的是前者,所以 flower 跑出来的是 .flower/;但 Python 里直接 Runtime(workbench=True) 拿到的是 runs/workbench。要指定位置就传一个建好的 Workbench 实例,别依赖默认值。
索引 subagent 继承不到
索引走会话级的 system_prompt.append,subagent 拿不到。所以"长产出写 artifacts/" 这条规矩必须由协调者在任务书里转述 —— 那是唯一通道。
落盘¶
spill
工具结果超过阈值(默认 4000 字符)时,PostToolUse hook 把它写到 <工作台根目录>/spill/,上下文里只留一行路径。
路径跟着工作台走,不是写死的 —— 只有工作台在默认位置 <工作区>/.flower 时,它才正好是 .flower/spill/。开了隔离、工作台被 home= 指到仓库外时, spill 也跟着挪出去。
当场就剪,不是等上下文满了再回头压缩。
一次性命令¶
ephemeral command
结果会过期、没有留存价值的命令 —— ls、git status、ps 这类。它们的结果不进持久化的 会话记录。判断"能不能放行主线程跑一眼"和"结果会不会被裁掉",用的是同一个函数, 所以两个集合永远相等。
裁剪¶
trim · TrimmingSessionStore
resume 之前重写要喂回模型的那份消息(一次性命令的结果、超长工具输出)。
它只覆盖 load():SQLite 里的原文始终不动,裁掉的只是这次 resume 送进上下文的那一份。 所以裁剪是可逆的 —— 换个策略再 resume 一次,拿到的又是完整记录。
剪除¶
prune · PruningSessionStore
把错误消息挡在上下文外面。断网重试期间产生的一堆报错不该占 resume 之后的上下文。
不要和裁剪混:裁剪按体积和价值丢,剪除按"是不是错误"丢。
运行时¶
隔离¶
isolation
标记过的角色自动分到独立的 git worktree,由 hook 强制,不靠提示词。 并行改同一个仓库时不打架。
开隔离就要把工作台挪出仓库
开 worktree 隔离时,工作台必须用 home= 指到仓库外,否则被隔离的 agent 写不进共享 checkout。
韧性¶
resilience · Resilience
断网时挂着等而不是失败退出:DNS + TCP 探针盯着,网络恢复后 resume 续跑。 等待期间产生的错误消息由剪除挡在上下文外。
血缘¶
lineage · Lineage
跨进程记录"这次运行由哪条会话 fork 而来",落在 lineage.json。接续靠它找到上次跑到哪。
不要和运行清单混 —— 那是 runs/manifest.json,记的是每次运行的账目。
运行清单¶
run manifest · runs/manifest.json
每次运行的账目记录:花了多少钱、跑了多久、上下文多大。案例页里的数字都能在这里复算。
唤醒¶
wake · wake_state()
起跑之前的只读探测:看看这个工作区是不是已经有需求确认书和目标了, 从而决定这次是全新开始还是接续。一个字节都不写。
wake_state() 是工作台位置的唯一定义处 —— 驱动程序想知道确认书在哪也得走它。 自己拼路径拼错了不会报错,只会静默失效。
事件¶
event · Event
SDK 的消息流被压平成的稳定结构。交互层只认 Event,不 import 任何 SDK 类型 —— 这是换 UI 不用改核心的边界。
交互层¶
interaction layer
人和运行之间的那层 UI。默认是终端,可以换成 Web、TUI、HTTP,或者全自动无人值守。 见换交互层。
会话存储¶
session store · SessionStore
会话消息的持久化后端。默认 SqliteSessionStore 写到 runs/sessions.db, 可以套上裁剪和剪除两层包装。
预算¶
budget · max_budget_usd
一次运行的花费上限,超了就停。长程运行没有这个会很贵 —— HT001 花了 $171.62。
可移植性¶
可移植¶
portable
换一台机器,行为一致。做法是 setting_sources=[] —— 不读宿主机的 ~/.claude/, 也不读项目的 .claude/。领域能力靠 plugin 随仓库走,凭证靠 .env 自带。
代价:凭证必须自带,不会自动继承宿主机配置。
叠加¶
append
领域指令追加在 Claude Code 原生系统提示词之后,而不是替换它:
所以专门化不以损失通用能力为代价。
plugin¶
跟着仓库走的领域能力包。通过 plugins=[local] 加载,目录里可以放 skills/、agents/、 hooks/、.mcp.json。见部署。