create-seeflow
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesecreate-seeflow
create-seeflow
Turn a natural-language prompt into a registered, runnable SeeFlow flow under . Orchestrate four sub-agents and bun scripts; never read the codebase directly.
<project>/.seeflow/<slug>/将自然语言提示转换为已注册、可运行的SeeFlow流程,存储在目录下。协调四个子代理和bun脚本;绝不直接读取代码库。
<project>/.seeflow/<slug>/When to invoke
调用时机
In any project, just run:
/create-seeflow Create a flow showing how the order pipeline works
/create-seeflow Show how checkout works end to end
/create-seeflow Diagram our event-driven notification system
/create-seeflow Add another flow to this repoAsk for clarification only when the prompt is incoherent — never ask "what is your codebase?".
在任意项目中,只需运行:
/create-seeflow Create a flow showing how the order pipeline works
/create-seeflow Show how checkout works end to end
/create-seeflow Diagram our event-driven notification system
/create-seeflow Add another flow to this repo仅当提示语不连贯时才要求用户澄清——切勿询问“你的代码库是什么?”。
Inputs you have
可用输入
- The user's full natural-language prompt.
- The project root (at invocation).
$PWD - (optional; studio host:port, default
~/.seeflow/config.json).http://localhost:4321 - Existing files, if any (multi-flow per project supported).
<project>/.seeflow/<slug>/seeflow.json
- 用户完整的自然语言提示。
- 项目根目录(调用时的)。
$PWD - (可选;Studio主机:端口,默认
~/.seeflow/config.json)。http://localhost:4321 - 已有的文件(支持单个项目多流程)。
<project>/.seeflow/<slug>/seeflow.json
The pipeline
执行流程
Phase 0 — pre-flight: studio reachable?
Phase 1 — seeflow-discoverer → context brief (language + runtime + tests)
Phase 2 — seeflow-node-planner → node draft
Phase 3 — write skeleton seeflow.json (nodes only) → register → user reviews canvas → approval
Phase 4 — seeflow-play-designer ┐
seeflow-status-designer├ parallel → overlays
┘
Phase 5 — synthesize → validate-schema
Phase 6 — write script files → re-register full flow
Phase 7 — validate-end-to-end.ts → trigger APIs → verify via SSE (retry up to 2x) → print URL on success / retry-or-stop on failureEach phase is gated on the previous one.
Phase 0 — 预检:Studio是否可达?
Phase 1 — seeflow-discoverer → 上下文摘要(语言+运行时+测试)
Phase 2 — seeflow-node-planner → 节点草稿
Phase 3 — 编写骨架seeflow.json(仅包含节点)→ 注册 → 用户审阅画布 → 确认通过
Phase 4 — seeflow-play-designer ┐
seeflow-status-designer├ 并行执行 → 叠加层
┘
Phase 5 — 合成 → 验证Schema
Phase 6 — 编写脚本文件 → 重新注册完整流程
Phase 7 — validate-end-to-end.ts → 触发API → 通过SSE验证(最多重试2次)→ 成功则打印URL / 失败则选择重试或终止每个阶段都依赖前一阶段完成才能启动。
Core rule — no mocks, ever
核心规则:绝不使用模拟
NEVER mock a service, fake a response, or simulate what a real service returns.
Scripts have exactly two purposes:
- Trigger a real service — call a real endpoint, drop a real file, publish a real event. Only invented content allowed is input data (fixture body, sample file); the service receiving it must be real.
- Read real resource state — query a real DB, poll a real queue depth, call a real health endpoint. Never fabricate state.
If a required service is not running, stop and ask the user. A flow with one honest gap is better than one that silently lies.
绝不模拟服务、伪造响应或仿真真实服务的返回结果。
脚本仅允许有两个用途:
- 触发真实服务——调用真实接口、生成真实文件、发布真实事件。仅允许虚构输入数据(测试用例体、示例文件);接收数据的服务必须是真实的。
- 读取真实资源状态——查询真实数据库、轮询真实队列深度、调用真实健康检查接口。绝不编造状态。
若所需服务未运行,立即停止并询问用户。一个存在真实缺口的流程,远胜于一个默默造假的流程。
Core rule — see the bigger picture before inserting data
核心规则:插入数据前先审视全局
Before writing a play script that INSERTs into a DB, publishes to a queue, or writes to a store, check whether the system already has a natural data-entry path. Direct inserts bypass validation and the code paths the flow is meant to show.
Check these patterns first (ask the discoverer):
| Pattern | What to look for | Use instead |
|---|---|---|
| API endpoint | REST/gRPC/GraphQL endpoint that accepts the data | Call it |
| File-drop processor | File watcher / S3-event listener | Drop a fixture file into the watched path |
| Event/message producer | Publisher service or CLI that writes to the queue | Trigger the producer |
| Seed / fixture command | | Run the seed command |
| Webhook receiver | | POST a synthetic webhook body |
| Admin / backoffice API | Internal endpoint for creating records | Use it |
| File-based import | CSV/JSON/NDJSON import endpoint or CLI | Drop a fixture or call the import endpoint |
Examples:
- Order pipeline needs an order in the DB → call ; the API validates, emits events, writes the row.
POST /api/orders - Data-warehouse pipeline needs staging rows → drop a CSV into the watched S3 bucket; the file-processor picks it up.
- Notification system needs a queue message → call ; the producer publishes on your behalf.
POST /api/notify - Recommendation engine needs user-event data → fire a event at the analytics endpoint.
track
If no higher-level path exists, document the reason in and resort to a direct INSERT/PUBLISH.
rationale在编写向数据库INSERT、向队列发布消息或向存储写入数据的play脚本前,需检查系统是否已有天然的数据录入路径。直接插入会绕过验证环节,以及流程本应展示的代码路径。
优先检查以下模式(可询问discoverer):
| 模式 | 检查要点 | 替代方案 |
|---|---|---|
| API接口 | 接收数据的REST/gRPC/GraphQL接口 | 调用该接口 |
| 文件处理程序 | 文件监视器/S3事件监听器 | 将测试用例文件放入监听路径 |
| 事件/消息生产者 | 向队列写入数据的发布服务或CLI | 触发生产者 |
| 种子/测试用例命令 | | 运行种子命令 |
| Webhook接收器 | | POST合成的Webhook请求体 |
| 管理/后台API | 创建记录的内部接口 | 使用该接口 |
| 基于文件的导入 | CSV/JSON/NDJSON导入接口或CLI | 放入测试用例文件或调用导入接口 |
示例:
- 订单流程需要数据库中有订单记录 → 调用;API会验证数据、触发事件并写入数据库。
POST /api/orders - 数据仓库流程需要暂存行 → 将CSV文件放入监听的S3存储桶;文件处理程序会自动处理。
- 通知系统需要队列消息 → 调用;生产者会代为发布消息。
POST /api/notify - 推荐引擎需要用户事件数据 → 向分析接口发送事件。
track
若不存在更高级的路径,需在中记录原因,再使用直接INSERT/PUBLISH操作。
rationaleCore rule — match the project's primary language
核心规则:匹配项目主语言
Use from Phase 1 as the interpreter for every script. The project already has types, helpers, and clients in that language — reuse them.
runtimeProfile.primaryLanguage | | |
|---|---|---|
| | |
| | |
| | |
| | |
| | depends on build tool |
| | |
Examples:
TypeScript:
typescript
// .seeflow/checkout-flow/scripts/play-checkout.ts
import type { CartPayload } from "../../src/types";
const input: CartPayload = JSON.parse(await Bun.stdin.text());
const res = await fetch("http://localhost:3001/checkout", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify(input),
});
console.log(await res.json());Go:
go
// .seeflow/order-flow/scripts/play-order.go
package main
import ("encoding/json"; "fmt"; "net/http"; "bytes"; "os")
func main() {
var payload map[string]any
json.NewDecoder(os.Stdin).Decode(&payload)
body, _ := json.Marshal(payload)
res, _ := http.Post("http://localhost:8080/orders", "application/json", bytes.NewReader(body))
var out any; json.NewDecoder(res.Body).Decode(&out); fmt.Println(out)
}Fallback: Use / only when the project runtime can't execute scripts directly. Note the reason in .
bashpython3rationale使用Phase 1中得到的作为所有脚本的解释器。项目已包含该语言的类型定义、工具函数和客户端——直接复用即可。
runtimeProfile.primaryLanguage | | |
|---|---|---|
| | |
| | |
| | |
| | |
| | 取决于构建工具 |
| | |
示例:
TypeScript:
typescript
// .seeflow/checkout-flow/scripts/play-checkout.ts
import type { CartPayload } from "../../src/types";
const input: CartPayload = JSON.parse(await Bun.stdin.text());
const res = await fetch("http://localhost:3001/checkout", {
method: "POST", headers: { "Content-Type": "application/json" },
body: JSON.stringify(input),
});
console.log(await res.json());Go:
go
// .seeflow/order-flow/scripts/play-order.go
package main
import ("encoding/json"; "fmt"; "net/http"; "bytes"; "os")
func main() {
var payload map[string]any
json.NewDecoder(os.Stdin).Decode(&payload)
body, _ := json.Marshal(payload)
res, _ := http.Post("http://localhost:8080/orders", "application/json", bytes.NewReader(body))
var out any; json.NewDecoder(res.Body).Decode(&out); fmt.Println(out)
}备选方案: 仅当项目运行时无法直接执行脚本时,才使用/。需在中记录原因。
bashpython3rationalePhase 0 — pre-flight (studio reachable)
Phase 0 — 预检(Studio可达性)
Resolve studio URL: env var → port → .
SEEFLOW_STUDIO_URL~/.seeflow/config.jsonhttp://localhost:4321bash
curl --max-time 0.5 -fsS "$STUDIO_URL/health"On failure, check :
which seeflow- CLI found:
Studio not reachable at <url>. Start it with: npx tuongaz/seeflow start - CLI not found: or clone +
Studio not reachable at <url> and the seeflow CLI is not installed. Run: npx tuongaz/seeflow start.make dev
Do not retry. Do not auto-start. On success: continue to Phase 1.
解析Studio URL优先级:环境变量 → 端口 → 。
SEEFLOW_STUDIO_URL~/.seeflow/config.jsonhttp://localhost:4321bash
curl --max-time 0.5 -fsS "$STUDIO_URL/health"若检测失败,检查:
which seeflow- 找到CLI:
Studio无法在<url>访问。请运行以下命令启动:npx tuongaz/seeflow start - 未找到CLI: 或克隆仓库后执行
Studio无法在<url>访问,且seeflow CLI未安装。请运行:npx tuongaz/seeflow start。make dev
不重试,不自动启动。若检测成功:进入Phase 1。
General rule — parallelise sub-agents
通用规则:并行执行子代理
Whenever two or more tasks are independent, dispatch them as concurrent sub-agents in a single message. Serial execution is the exception, not the default.
只要两个或多个任务相互独立,就应在单个消息中并发调度子代理。串行执行是例外情况,而非默认规则。
After Phase 0 — list tasks
Phase 0之后:列出任务
Create a checklist before launching any sub-agent:
TaskCreate[ ] Phase 1 — Discover codebase (language, runtime, integration tests)
[ ] Phase 2 — Plan nodes & connectors
[ ] Phase 3 — Register skeleton flow (nodes only) — await user node review
[ ] Phase 4 — Design Play + Status scripts (parallel)
[ ] Phase 5 — Synthesize & validate schema
[ ] Phase 6 — Write script files & re-register full flow
[ ] Phase 7 — End-to-end validation (trigger APIs, verify via SSE)Mark each complete via immediately after it succeeds.
TaskUpdate在启动任何子代理前,创建检查清单:
TaskCreate[ ] Phase 1 — 发现代码库(语言、运行时、集成测试)
[ ] Phase 2 — 规划节点与连接器
[ ] Phase 3 — 注册骨架流程(仅包含节点)——等待用户审阅节点
[ ] Phase 4 — 设计Play + Status脚本(并行)
[ ] Phase 5 — 合成并验证Schema
[ ] Phase 6 — 编写脚本文件并重新注册完整流程
[ ] Phase 7 — 端到端验证(触发API,通过SSE验证)每个任务成功完成后,立即通过标记为已完成。
TaskUpdatePhase 1 — discover
Phase 1 — 发现
Launch with the user's prompt, project root, and any existing for the matching slug. Tools: (read-only).
seeflow-discovererseeflow.jsonRead, Grep, Glob, LS, BashDiscoverer must:
- Identify primary language + runtime ()
runtimeProfile - Find integration/e2e tests and extract their setup pattern (ports, base URLs, payload shapes)
Expected output (parseable JSON):
json
{
"userIntent": "…",
"audienceFraming": "…",
"scope": { "rootEntities": ["…"], "outOfScope": ["…"] },
"codePointers": [{ "path": "…", "why": "…" }],
"runtimeProfile": {
"primaryLanguage": "typescript",
"packageManager": "bun",
"devCommand": "bun run dev",
"testCommand": "bun test",
"servicePort": 3001,
"integrationTestDir": "tests/integration",
"integrationTestCommand": "bun test tests/integration",
"setupPattern": "Tests call http://localhost:3001 with JSON payloads after starting the server"
},
"existingFlow": null
}On unparseable output: retry once with the validation error. If still failing, surface and stop.
启动,传入用户提示、项目根目录以及匹配slug的现有文件。可使用工具:(仅只读操作)。
seeflow-discovererseeflow.jsonRead, Grep, Glob, LS, BashDiscoverer必须完成:
- 识别主语言+运行时()
runtimeProfile - 找到集成/端到端测试并提取其设置模式(端口、基础URL、请求体格式)
预期输出(可解析的JSON):
json
{
"userIntent": "…",
"audienceFraming": "…",
"scope": { "rootEntities": ["…"], "outOfScope": ["…"] },
"codePointers": [{ "path": "…", "why": "…" }],
"runtimeProfile": {
"primaryLanguage": "typescript",
"packageManager": "bun",
"devCommand": "bun run dev",
"testCommand": "bun test",
"servicePort": 3001,
"integrationTestDir": "tests/integration",
"integrationTestCommand": "bun test tests/integration",
"setupPattern": "Tests call http://localhost:3001 with JSON payloads after starting the server"
},
"existingFlow": null
}若输出无法解析:携带验证错误重试一次。若仍失败,直接告知用户并停止。
Phase 2 — plan nodes
Phase 2 — 规划节点
Launch with the context brief. No tools — pure reasoning. Two mandatory passes:
seeflow-node-planner- Resource nodes first — every DB, queue, event bus, cache, file store, and external SaaS touched by the flow gets its own .
stateNode - Abstraction rules — one node per service / workflow / worker / queue / DB (exceptions: independently-meaningful pipeline stages, fan-out consumers, branches).
- Connection limit — max 4 total connections (in + out) per node. When exceeded:
- Split if the node has distinct responsibilities.
- Duplicate a shared resource to break hub-and-spoke patterns.
Duplication for clarity — the "one node per service" default can be overridden when showing the same resource twice improves readability (e.g. a shared DB placed next to each service that uses it). Use same + ; unique with a descriptive suffix (, ).
kindnameid"orders-db-read""orders-db-write"Expected output:
json
{
"name": "…",
"slug": "…",
"nodes": [{ "id": "…", "type": "…", "data": {…}, "oneNodeRationale": "…" }],
"connectors": [{ "id": "…", "kind": "…", "source": "…", "target": "…" }]
}Retry budget: one retry on unparseable output, then surface and stop.
启动,传入上下文摘要。无需工具——纯逻辑推理。必须完成两轮检查:
seeflow-node-planner- 优先规划资源节点——流程涉及的每个数据库、队列、事件总线、缓存、文件存储和外部SaaS服务都需单独创建。
stateNode - 抽象规则——每个服务/工作流/ worker/队列/数据库对应一个节点(例外情况:独立有意义的流水线阶段、扇出消费者、分支流程)。
- 连接限制——每个节点最多4个总连接数(入站+出站)。若超出限制:
- 若节点有不同职责,则拆分节点。
- 复制共享资源以打破中心辐射模式。
为清晰性而复制——当重复展示同一资源能提升可读性时,可覆盖“一个服务对应一个节点”的默认规则(例如,将共享数据库放在每个使用它的服务旁边)。使用相同的 + ;使用带描述性后缀的唯一(如、)。
kindnameid"orders-db-read""orders-db-write"预期输出:
json
{
"name": "…",
"slug": "…",
"nodes": [{ "id": "…", "type": "…", "data": {…}, "oneNodeRationale": "…" }],
"connectors": [{ "id": "…", "kind": "…", "source": "…", "target": "…" }]
}重试限额:输出无法解析时重试一次,然后告知用户并停止。
Phase 3 — node review checkpoint
Phase 3 — 节点审阅检查点
Register a skeleton flow (nodes + connectors only, no scripts) so the user can review the canvas before any scripts are written.
Paths (used in this phase and Phase 6):
repoPath = $PWDflowDir = $PWD/.seeflow/<slug>flowPath = .seeflow/<slug>/seeflow.json
- Build skeleton JSON from node draft — omit ,
playAction,statusAction. KeepresetAction,version,name,nodes.connectors - then write to
mkdir -p $flowDir.$flowDir/seeflow-nodes.json - Validate:
On failure: fix field-level issues in-place (no re-run of node-planner), retry.bash
bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-nodes.json" - Write and register:
$flowDir/seeflow.jsonStash the returnedbashbun skills/create-seeflow/scripts/register.ts --path "$repoPath" --flow "$flowPath".id - Ask the user:
The nodes are live at. Does the layout look right? Any additions, removals, or renames before I write the scripts?
<url>
Wait for response.
- Approved → Phase 4.
- Changes requested → re-run node-planner with feedback, repeat Phase 3.
注册骨架流程(仅包含节点和连接器,无脚本),以便用户在编写任何脚本前审阅画布。
路径(本阶段和Phase 6使用):
repoPath = $PWDflowDir = $PWD/.seeflow/<slug>flowPath = .seeflow/<slug>/seeflow.json
- 根据节点草稿构建骨架JSON——省略、
playAction、statusAction。保留resetAction、version、name、nodes。connectors - 执行,然后写入
mkdir -p $flowDir。$flowDir/seeflow-nodes.json - 验证:
若失败:就地修复字段级问题(无需重新运行node-planner),重试。bash
bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-nodes.json" - 写入并注册:
$flowDir/seeflow.json保存返回的bashbun skills/create-seeflow/scripts/register.ts --path "$repoPath" --flow "$flowPath"。id - 询问用户:
节点已发布至。布局是否合理?在编写脚本前,是否需要添加、删除或重命名节点?
<url>
等待用户回复。
- 已批准 → 进入Phase 4。
- 要求修改 → 根据反馈重新运行node-planner,重复Phase 3。
Phase 4 — design Play + Status (parallel)
Phase 4 — 设计Play + Status(并行)
Launch and in parallel (single message, two calls). Both receive: context brief + node draft + edit target. Tools: .
seeflow-play-designerseeflow-status-designerTaskRead, Grep, Glob, LSseeflow-play-designerjson
{
"playOverlays": [{
"nodeId": "…",
"playAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/<name>.ts",
"input": {…}, "timeoutMs": 30000 },
"scriptBody": "…",
"validationSafe": true,
"rationale": "…"
}],
"newTriggerNodes": []
}seeflow-status-designerjson
{
"statusOverlays": [{
"nodeId": "…",
"statusAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/<name>.ts",
"maxLifetimeMs": 600000 },
"scriptBody": "…",
"rationale": "…"
}]
}Sample data — look before inventing. Priority:
- Integration/e2e test fixtures () — copy verbatim.
runtimeProfile.integrationTestDir - Seed / migration fixtures (,
seed.*,fixtures/, ORM factories).testdata/ - README / OpenAPI / Postman examples.
- Invent as last resort — note in .
rationale
newTriggerNodes并行启动和(单个消息,两次调用)。两者均接收:上下文摘要+节点草稿+编辑目标。可使用工具:。
seeflow-play-designerseeflow-status-designerTaskRead, Grep, Glob, LSseeflow-play-designerjson
{
"playOverlays": [{
"nodeId": "…",
"playAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/<name>.ts",
"input": {…}, "timeoutMs": 30000 },
"scriptBody": "…",
"validationSafe": true,
"rationale": "…"
}],
"newTriggerNodes": []
}seeflow-status-designerjson
{
"statusOverlays": [{
"nodeId": "…",
"statusAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/<name>.ts",
"maxLifetimeMs": 600000 },
"scriptBody": "…",
"rationale": "…"
}]
}示例数据:优先查找而非编造。优先级:
- 集成/端到端测试用例()——直接复制。
runtimeProfile.integrationTestDir - 种子/迁移测试用例(、
seed.*、fixtures/、ORM工厂)。testdata/ - README/OpenAPI/Postman示例。
- 最后才考虑编造——需在中记录。
rationale
当不存在天然触发器时,可注入合成源节点(文件上传、Webhook接收器)。
newTriggerNodesPhase 5 — synthesize + validate schema
Phase 5 — 合成 + 验证Schema
- Splice into
newTriggerNodes(add any required connectors).nodeDraft.nodes - Merge each overlay onto its target node's . Strip
data,validationSafe,rationale— orchestrator metadata, not schema fields. CollectscriptBodys wherenodeIdintovalidationSafe: false.unsafeNodeIds - Write merged flow to .
$flowDir/seeflow-draft.json - Validate:
bash
bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-draft.json"{"ok":true}{"ok":false,"issues":[…]}- Proceed to Phase 6 — node layout was approved in Phase 3.
- 插入到
newTriggerNodes中(添加所需的连接器)。nodeDraft.nodes - 合并每个叠加层到目标节点的中。移除
data、validationSafe、rationale——这些是编排器元数据,不属于Schema字段。将scriptBody的validationSafe: false收集到nodeId中。unsafeNodeIds - 写入合并后的流程到。
$flowDir/seeflow-draft.json - 验证:
bash
bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-draft.json"返回 → 继续。返回 → 将问题反馈给对应的设计器,重试。最多重试3次,然后直接告知用户并停止。
{"ok":true}{"ok":false,"issues":[…]}- 进入Phase 6——节点布局已在Phase 3获得批准。
Phase 6 — write script files + re-register full flow
Phase 6 — 编写脚本文件 + 重新注册完整流程
mkdir -p $flowDir/scripts $flowDir/state- Write files (overwriting the Phase 3 skeleton):
- — validated flow JSON with all actions.
$flowDir/seeflow.json - — one file per overlay
$flowDir/scripts/<name>.scriptBody.chmod +x - —
$flowDir/state/.gitignore.*
- Re-register:
bash
bun skills/create-seeflow/scripts/register.ts --path "$repoPath" --demo "$flowPath"Prints . Use the new for Phases 7 + 8.
{id, slug}idOn 400: show body, ask "fix-and-retry / stop". On other 4xx/5xx: show body, stop.
- 执行
mkdir -p $flowDir/scripts $flowDir/state - 写入文件(覆盖Phase 3的骨架文件):
- ——包含所有操作的已验证流程JSON。
$flowDir/seeflow.json - ——每个叠加层对应一个
$flowDir/scripts/<name>文件。执行scriptBody赋予执行权限。chmod +x - ——内容为
$flowDir/state/.gitignore。*
- 重新注册:
bash
bun skills/create-seeflow/scripts/register.ts --path "$repoPath" --demo "$flowPath"输出。使用新的进行Phase 7和后续操作。
{id, slug}id若返回400:展示响应体,询问用户“修复并重试 / 停止”。若返回其他4xx/5xx:展示响应体,停止操作。
Phase 7 — end-to-end validation
Phase 7 — 端到端验证
Must run. Do not skip or simulate.
bash
bun skills/create-seeflow/scripts/validate-end-to-end.ts <id> [--skip-nodes <id1>,<id2>]Pass when is non-empty (nodes that hit third-party services or charge money). Skipped nodes appear in and are not counted as failures.
--skip-nodesunsafeNodeIdsskipped[]The script:
- GETs (expects 200,
/api/demos/<id>).valid: true - Opens SSE at before triggering plays.
/api/events?demoId=<id> - POSTs for each safe play node; awaits response.
/api/demos/<id>/play/<nodeId> - Drains SSE for /
node:done/node:errorevents. SSE outcome takes precedence.node:status - Hard ceiling: ~2 minutes. Emits .
{ok, plays, statuses, skipped}
Interpret the JSON. On → print . Done. On :
ok: trueFlow "<name>" registered as <slug>. Open: $STUDIO_URL/d/<slug>ok: false- Identify failing nodes from /
plays[*].error.statuses[*].outcome - Propose a concrete fix ("play-checkout.ts: on port 3001 — start the app first").
ECONNREFUSED - Dispatch one sub-agent per failing script in parallel.
- Edit scripts in-place, re-run Phase 7 against the same . Max 2 retries, then ask
<id>.retry / stop
Never re-run in the fix-up loop.
register.ts必须执行,不得跳过或模拟。
bash
bun skills/create-seeflow/scripts/validate-end-to-end.ts <id> [--skip-nodes <id1>,<id2>]当非空时(涉及第三方服务或产生费用的节点),传入参数。被跳过的节点会出现在中,不计入失败。
unsafeNodeIds--skip-nodesskipped[]该脚本执行以下操作:
- GET请求(预期返回200,
/api/demos/<id>)。valid: true - 在触发play操作前,打开的SSE连接。
/api/events?demoId=<id> - 对每个安全的play节点POST请求;等待响应。
/api/demos/<id>/play/<nodeId> - 监听SSE的/
node:done/node:error事件。SSE结果优先级最高。node:status - 最长耗时:约2分钟。输出。
{ok, plays, statuses, skipped}
解析JSON结果。若 → 打印。操作完成。若:
ok: trueFlow "<name>"已注册为<slug>。访问地址:$STUDIO_URL/d/<slug>ok: false- 从/
plays[*].error中识别失败节点。statuses[*].outcome - 提出具体修复方案(例如“play-checkout.ts:端口3001连接被拒绝——请先启动应用”)。
- 并行为每个失败脚本调度一个子代理。
- 就地编辑脚本,使用相同的重新运行Phase 7。最多重试2次,然后询问用户“重试 / 停止”。
<id>
修复循环中不得重新运行。
register.tsError-handling table
错误处理表
| Failure | Response |
|---|---|
Studio | |
| Sub-agent unparseable output | Retry once with parse error; if still failing, surface and stop. |
| Schema validation fails (Phase 5) | Feed Zod issues back to relevant designer. Max 3 retries. |
| Register 400 (Phase 6) | Show body; ask "fix-and-retry / stop". |
| Register 4xx/5xx other | Show body; stop. |
Play | Edit scripts in-place; re-run Phase 7 (max 2 retries). Do NOT re-register. |
| Status SSE timeout 10s | Mark |
| Validation >2 min | |
Retry caps: Phase 5 schema → 3. Phase 7 fix-up → 2.
| 失败场景 | 响应方式 |
|---|---|
Studio | 执行 |
| 子代理输出无法解析 | 携带解析错误重试一次;若仍失败,告知用户并停止。 |
| Schema验证失败(Phase 5) | 将Zod错误反馈给对应的设计器。最多重试3次。 |
| 注册返回400(Phase 6) | 展示响应体;询问用户“修复并重试 / 停止”。 |
| 注册返回其他4xx/5xx | 展示响应体;停止操作。 |
Play返回 | 就地编辑脚本;重新运行Phase 7(最多重试2次)。不得重新注册。 |
| Status SSE超时10秒 | 标记为“未收到状态”;纳入修复流程或询问用户重试/停止。 |
| 验证耗时超过2分钟 | 返回 |
重试上限:Phase 5 Schema验证 → 3次。Phase 7修复 → 2次。
Schema cheatsheet
Schema速查表
Full schema: . Below covers ~95% of cases.
skills/create-seeflow/vendored/schema.ts完整Schema:。以下内容覆盖约95%的使用场景。
skills/create-seeflow/vendored/schema.tsFlow envelope
流程信封
json
{
"version": 1,
"name": "Checkout Flow",
"nodes": [ …NodeSchema… ],
"connectors": [ …ConnectorSchema… ],
"resetAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/reset.ts" }
}resetActionjson
{
"version": 1,
"name": "Checkout Flow",
"nodes": [ …NodeSchema… ],
"connectors": [ …ConnectorSchema… ],
"resetAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/reset.ts" }
}resetActionNode types
节点类型
playNode — has a clickable Play button. Required: , , , . Optional: , (≤ 15 words), .
namekindstateSourceplayActionstatusActiondescriptiondetailRULE — detail on important nodes: Every and that carries meaningful behaviour MUST include a field. renders as markdown — use it to explain what the node does, what it emits, why it matters, sample payloads, links to source files, or anything an audience member would ask. Decorative / entries are exempt.
playNodestateNodedetaildetailshapeNodeiconNodekindserviceendpointworkerworkflowqueuetopicbusdbstorecacheschedulerexternal-apitriggerjson
{
"id": "checkout-api", "type": "playNode", "position": { "x": 100, "y": 200 },
"data": {
"name": "POST /checkout", "kind": "service",
"stateSource": { "kind": "request" },
"playAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "checkout-flow/scripts/play-checkout.ts",
"input": { "items": [{"sku":"ABC","qty":1}] },
"timeoutMs": 30000 },
"description": "Receives a cart, creates an order.",
"detail": "Validates the cart, reserves stock, and publishes an `order.created` event.\n\n**Emits:** `order.created` → Order Worker\n\n**Source:** `src/routes/checkout.ts`"
}
}stateNode — no mandatory Play; audience watches but doesn't trigger. Same values.
kindjson
{
"id": "order-db", "type": "stateNode", "position": { "x": 600, "y": 200 },
"data": {
"name": "Orders DB", "kind": "db",
"stateSource": { "kind": "event" },
"statusAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "checkout-flow/scripts/status-orders.ts",
"maxLifetimeMs": 600000 },
"detail": "Postgres table `orders`. Rows land here after `order.created` is processed.\n\n**Schema:** `id`, `status`, `total`, `created_at`\n\n**Source:** `src/db/migrations/001_orders.sql`"
}
}shapeNode — decorative / illustrative. No actions or live state.
| Renders as | Best for |
|---|---|---|
| Cylinder | DB label (use |
| Server rack | On-premise server or compute |
| Person silhouette | Human actor / customer |
| Stack | Queue label (decorative) |
| Cloud outline | External SaaS |
| Box | Grouping boundary |
| Oval | Annotation |
| Sticky note | Callout |
| Plain text | Canvas label |
json
{ "id": "customer", "type": "shapeNode", "position": { "x": 0, "y": 200 },
"data": { "shape": "user", "name": "Customer" } }
{ "id": "stripe", "type": "shapeNode", "position": { "x": 800, "y": 200 },
"data": { "shape": "cloud", "name": "Stripe", "borderStyle": "dashed" } }
{ "id": "boundary", "type": "shapeNode", "position": { "x": 50, "y": 50 },
"data": { "shape": "rectangle", "name": "Internal services", "borderStyle": "dashed" } }iconNode — single Lucide glyph. Decorative only.
json
{ "id": "user-icon", "type": "iconNode", "position": { "x": 0, "y": 200 },
"data": { "icon": "User", "name": "Customer", "width": 64, "height": 64 } }htmlNode — escape-hatch for content no curated node covers: legends, data tables, rich annotations, custom UI widgets. Renderer fetches the HTML file, injects Tailwind Play CDN (utility classes work), then sanitises before painting (strips , , , attributes, URLs).
<script><style><iframe>on*=javascript:Required fields:
- — relative path under
htmlPath. No leading.seeflow/, no/. E.g....checkout-flow/legend.html
Optional styling fields (same as shapeNode):
, , , , , , , , , (caption below node), ,
widthheightbackgroundColorborderColorborderSizeborderStylecornerRadiusfontSizetextColornamedescriptiondetailDefault size: 320 × 200 px. Set / to override.
widthheightjson
{ "id": "legend", "type": "htmlNode", "position": { "x": 50, "y": 600 },
"data": {
"htmlPath": "checkout-flow/legend.html",
"width": 400, "height": 120,
"backgroundColor": "slate",
"cornerRadius": 8,
"name": "Legend"
}
}HTML file — write to . Tailwind classes work; no or (stripped by sanitiser). Use inline styles for anything Tailwind can't cover. See .
$flowDir/<name>.html<script><style>references/examples/html-node-example.htmlWhen NOT to use: If a with a label, an , or a covers the content, prefer those — they participate in theming and status updates automatically.
shapeNodeiconNodestateNodeimageNode — decorative image under .
.seeflow/json
{ "id": "logo", "type": "imageNode", "position": { "x": 0, "y": 0 },
"data": { "path": "checkout-flow/logo.png", "alt": "Stripe logo" } }playNode——带有可点击的Play按钮。必填字段:、、、。可选字段:、(≤15个单词)、。
namekindstateSourceplayActionstatusActiondescriptiondetail规则:重要节点需添加detail——每个承载有意义行为的和必须包含字段。以markdown格式渲染——用于解释节点功能、输出内容、重要性、示例请求体、源码链接,或任何受众可能询问的信息。装饰性的/无需添加。
playNodestateNodedetaildetailshapeNodeiconNodekindserviceendpointworkerworkflowqueuetopicbusdbstorecacheschedulerexternal-apitriggerjson
{
"id": "checkout-api", "type": "playNode", "position": { "x": 100, "y": 200 },
"data": {
"name": "POST /checkout", "kind": "service",
"stateSource": { "kind": "request" },
"playAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "checkout-flow/scripts/play-checkout.ts",
"input": { "items": [{"sku":"ABC","qty":1}] },
"timeoutMs": 30000 },
"description": "接收购物车,创建订单。",
"detail": "验证购物车、预留库存,并发布`order.created`事件。\n\n**输出:** `order.created` → 订单Worker\n\n**源码:** `src/routes/checkout.ts`"
}
}stateNode——无强制Play按钮;受众仅查看状态,不触发操作。可选值与playNode相同。
kindjson
{
"id": "order-db", "type": "stateNode", "position": { "x": 600, "y": 200 },
"data": {
"name": "Orders DB", "kind": "db",
"stateSource": { "kind": "event" },
"statusAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "checkout-flow/scripts/status-orders.ts",
"maxLifetimeMs": 600000 },
"detail": "Postgres表`orders`。`order.created`事件处理完成后,数据会写入此表。\n\n**Schema:** `id`、`status`、`total`、`created_at`\n\n**源码:** `src/db/migrations/001_orders.sql`"
}
}shapeNode——装饰/说明性节点。无操作或实时状态。
| 渲染样式 | 适用场景 |
|---|---|---|
| 圆柱体 | 数据库标签(监控时使用 |
| 服务器机架 | 本地服务器或计算资源 |
| 人物剪影 | 人类角色/客户 |
| 堆叠形状 | 队列标签(装饰用) |
| 云轮廓 | 外部SaaS服务 |
| 矩形框 | 分组边界 |
| 椭圆形 | 注释 |
| 便签纸 | 标注 |
| 纯文本 | 画布标签 |
json
{ "id": "customer", "type": "shapeNode", "position": { "x": 0, "y": 200 },
"data": { "shape": "user", "name": "Customer" } }
{ "id": "stripe", "type": "shapeNode", "position": { "x": 800, "y": 200 },
"data": { "shape": "cloud", "name": "Stripe", "borderStyle": "dashed" } }
{ "id": "boundary", "type": "shapeNode", "position": { "x": 50, "y": 50 },
"data": { "shape": "rectangle", "name": "Internal services", "borderStyle": "dashed" } }iconNode——单个Lucide图标。仅用于装饰。
json
{ "id": "user-icon", "type": "iconNode", "position": { "x": 0, "y": 200 },
"data": { "icon": "User", "name": "Customer", "width": 64, "height": 64 } }htmlNode——用于展示其他节点无法覆盖的内容:图例、数据表、富注释、自定义UI组件。渲染器会获取HTML文件,注入Tailwind Play CDN(工具类可正常使用),然后在渲染前进行清理(移除、、、属性、 URL)。
<script><style><iframe>on*=javascript:必填字段:
- ——
htmlPath下的相对路径。无前导.seeflow/,无/。例如..。checkout-flow/legend.html
可选样式字段(与shapeNode相同):
、、、、、、、、、(节点下方的标题)、、
widthheightbackgroundColorborderColorborderSizeborderStylecornerRadiusfontSizetextColornamedescriptiondetail默认尺寸: 320 × 200 px。可设置/覆盖默认值。
widthheightjson
{ "id": "legend", "type": "htmlNode", "position": { "x": 50, "y": 600 },
"data": {
"htmlPath": "checkout-flow/legend.html",
"width": 400, "height": 120,
"backgroundColor": "slate",
"cornerRadius": 8,
"name": "Legend"
}
}HTML文件——写入。Tailwind类可正常使用;不得包含或(会被清理器移除)。对于Tailwind无法覆盖的样式,使用内联样式。示例见。
$flowDir/<name>.html<script><style>references/examples/html-node-example.html不适用场景: 若(带标签)、或可覆盖内容,优先使用这些节点——它们会自动适配主题和状态更新。
shapeNodeiconNodestateNodeimageNode——下的装饰性图片。
.seeflow/json
{ "id": "logo", "type": "imageNode", "position": { "x": 0, "y": 0 },
"data": { "path": "checkout-flow/logo.png", "alt": "Stripe logo" } }Connectors
连接器
Required: , , , .
idsourcetargetkindjson
{ "id": "c1", "kind": "http", "source": "checkout-api", "target": "payments",
"method": "POST", "url": "/charge", "label": "POST /charge" }
{ "id": "c2", "kind": "event", "source": "checkout-api", "target": "shipping-worker",
"eventName": "order.created" }
{ "id": "c3", "kind": "queue", "source": "checkout-api", "target": "fulfil-queue",
"queueName": "fulfilment-jobs" }
{ "id": "c4", "kind": "default", "source": "user-icon", "target": "checkout-api",
"label": "clicks checkout" }Optional visual fields (all kinds): (), (), (), , , , , / ( / ).
stylesolid|dashed|dotteddirectionforward|backward|both|nonepathcurve|stepcolorborderSizefontSizelabelsourceHandletargetHandler|bt|l必填字段:、、、。
idsourcetargetkindjson
{ "id": "c1", "kind": "http", "source": "checkout-api", "target": "payments",
"method": "POST", "url": "/charge", "label": "POST /charge" }
{ "id": "c2", "kind": "event", "source": "checkout-api", "target": "shipping-worker",
"eventName": "order.created" }
{ "id": "c3", "kind": "queue", "source": "checkout-api", "target": "fulfil-queue",
"queueName": "fulfilment-jobs" }
{ "id": "c4", "kind": "default", "source": "user-icon", "target": "checkout-api",
"label": "clicks checkout" }可选视觉字段(所有类型):()、()、()、、、、、/( / )。
stylesolid|dashed|dotteddirectionforward|backward|both|nonepathcurve|stepcolorborderSizefontSizelabelsourceHandletargetHandler|bt|lstateSource
stateSourcestateSource
stateSourcejson
{ "kind": "request" } // triggered by an explicit click/call
{ "kind": "event" } // fires reactively (consumer, worker, DB, watcher)json
{ "kind": "request" } // 由显式点击/调用触发
{ "kind": "event" } // 响应式触发(消费者、worker、数据库、监视器)playAction
/ statusAction
/ resetAction
playActionstatusActionresetActionplayAction
/ statusAction
/ resetAction
playActionstatusActionresetActionjson
{ "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/<file>.ts", "input": {…optional…},
"timeoutMs": 30000 }- — relative under
scriptPath. No leading slash, no.seeflow/... - — must match
interpreter. Values:runtimeProfile.primaryLanguage,bun,go,python3,node.bash - (playAction) — JSON-serialised, piped to stdin.
input - (playAction; max 600 000) — be generous:
timeoutMs- Simple HTTP call → 15 000 ms.
- Go / Rust (compile on first run) → 60 000–120 000 ms.
- Java / Kotlin (JVM startup) → 120 000 ms minimum.
- DB seeding / migrations → 60 000 ms minimum.
- (statusAction; max 3 600 000) — default 600 000; bump to 1 800 000 for long async flows.
maxLifetimeMs
json
{ "kind": "script", "interpreter": "bun", "args": ["run"],
"scriptPath": "<slug>/scripts/<file>.ts", "input": {…可选…},
"timeoutMs": 30000 }- ——
scriptPath下的相对路径。无前导斜杠,无.seeflow/。.. - ——必须匹配
interpreter。可选值:runtimeProfile.primaryLanguage、bun、go、python3、node。bash - (playAction)——JSON序列化后,通过标准输入传递。
input - (playAction;最大600000)——设置足够长的时间:
timeoutMs- 简单HTTP请求 → 15000 ms。
- Go/Rust(首次运行需编译) → 60000–120000 ms。
- Java/Kotlin(JVM启动) → 至少120000 ms。
- 数据库初始化/迁移 → 至少60000 ms。
- (statusAction;最大3600000)——默认600000;对于长异步流程,可提升至1800000。
maxLifetimeMs
StatusReport
(stdout line shape)
StatusReportStatusReport
(标准输出行格式)
StatusReportjson
{ "state": "ok|warn|error|pending", "summary": "…(≤120)…",
"detail": "…(≤2000)…", "data": {…free…}, "ts": 1700000000000 }Malformed lines are silently dropped. Emit one full JSON object per line.
json
{ "state": "ok|warn|error|pending", "summary": "…(≤120字符)…",
"detail": "…(≤2000字符)…", "data": {…自定义…}, "ts": 1700000000000 }格式错误的行会被静默丢弃。每行输出一个完整的JSON对象。
Sub-agent reference
子代理参考
| Agent | Tools | Used for |
|---|---|---|
| | Phase 1: explore codebase, return context brief |
| none (pure reasoning) | Phase 2: pick nodes + connectors |
| | Phase 4: design playActions + script bodies |
| | Phase 4: design statusActions + script bodies |
Full prompts + worked examples in .
skills/create-seeflow/agents/<agent>.md| 代理 | 可用工具 | 用途 |
|---|---|---|
| | Phase 1:探索代码库,返回上下文摘要 |
| 无(纯逻辑推理) | Phase 2:选择节点和连接器 |
| | Phase 4:设计playActions和脚本内容 |
| | Phase 4:设计statusActions和脚本内容 |
完整提示语和示例见。
skills/create-seeflow/agents/<agent>.mdStudio API touchpoints
Studio API接口
| Endpoint | Method | Phase | Body |
|---|---|---|---|
| GET | 0 | — |
| POST | 3, 6 | |
| GET | 7 | — |
| POST | 7 | — |
| GET (SSE) | 7 | — |
| DELETE | rollback only | — |
Never invent endpoints. Surface anything outside this table to the user.
| 接口 | 请求方法 | 阶段 | 请求体 |
|---|---|---|---|
| GET | 0 | — |
| POST | 3, 6 | |
| GET | 7 | — |
| POST | 7 | — |
| GET (SSE) | 7 | — |
| DELETE | 仅回滚时使用 | — |
不得自行编造接口。若遇到不在此列表中的接口,直接告知用户。