create-seeflow

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

create-seeflow

create-seeflow

Turn a natural-language prompt into a registered, runnable SeeFlow flow under
<project>/.seeflow/<slug>/
. Orchestrate four sub-agents and bun scripts; never read the codebase directly.
将自然语言提示转换为已注册、可运行的SeeFlow流程,存储在
<project>/.seeflow/<slug>/
目录下。协调四个子代理和bun脚本;绝不直接读取代码库。

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 repo
Ask 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 (
    $PWD
    at invocation).
  • ~/.seeflow/config.json
    (optional; studio host:port, default
    http://localhost:4321
    ).
  • Existing
    <project>/.seeflow/<slug>/seeflow.json
    files, if any (multi-flow per project supported).
  • 用户完整的自然语言提示。
  • 项目根目录(调用时的
    $PWD
    )。
  • ~/.seeflow/config.json
    (可选;Studio主机:端口,默认
    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 failure
Each 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:
  1. 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.
  2. 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.

绝不模拟服务、伪造响应或仿真真实服务的返回结果。
脚本仅允许有两个用途:
  1. 触发真实服务——调用真实接口、生成真实文件、发布真实事件。仅允许虚构输入数据(测试用例体、示例文件);接收数据的服务必须是真实的。
  2. 读取真实资源状态——查询真实数据库、轮询真实队列深度、调用真实健康检查接口。绝不编造状态。
若所需服务未运行,立即停止并询问用户。一个存在真实缺口的流程,远胜于一个默默造假的流程。

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):
PatternWhat to look forUse instead
API endpointREST/gRPC/GraphQL endpoint that accepts the dataCall it
File-drop processorFile watcher / S3-event listenerDrop a fixture file into the watched path
Event/message producerPublisher service or CLI that writes to the queueTrigger the producer
Seed / fixture command
make seed
,
bun run seed
, ORM factory
Run the seed command
Webhook receiver
/webhooks/stripe
,
/events/github
POST a synthetic webhook body
Admin / backoffice APIInternal endpoint for creating recordsUse it
File-based importCSV/JSON/NDJSON import endpoint or CLIDrop a fixture or call the import endpoint
Examples:
  • Order pipeline needs an order in the DB → call
    POST /api/orders
    ; the API validates, emits events, writes the row.
  • 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
    POST /api/notify
    ; the producer publishes on your behalf.
  • Recommendation engine needs user-event data → fire a
    track
    event at the analytics endpoint.
If no higher-level path exists, document the reason in
rationale
and resort to a direct INSERT/PUBLISH.

在编写向数据库INSERT、向队列发布消息或向存储写入数据的play脚本前,需检查系统是否已有天然的数据录入路径。直接插入会绕过验证环节,以及流程本应展示的代码路径。
优先检查以下模式(可询问discoverer):
模式检查要点替代方案
API接口接收数据的REST/gRPC/GraphQL接口调用该接口
文件处理程序文件监视器/S3事件监听器将测试用例文件放入监听路径
事件/消息生产者向队列写入数据的发布服务或CLI触发生产者
种子/测试用例命令
make seed
bun run seed
、ORM工厂
运行种子命令
Webhook接收器
/webhooks/stripe
/events/github
POST合成的Webhook请求体
管理/后台API创建记录的内部接口使用该接口
基于文件的导入CSV/JSON/NDJSON导入接口或CLI放入测试用例文件或调用导入接口
示例:
  • 订单流程需要数据库中有订单记录 → 调用
    POST /api/orders
    ;API会验证数据、触发事件并写入数据库。
  • 数据仓库流程需要暂存行 → 将CSV文件放入监听的S3存储桶;文件处理程序会自动处理。
  • 通知系统需要队列消息 → 调用
    POST /api/notify
    ;生产者会代为发布消息。
  • 推荐引擎需要用户事件数据 → 向分析接口发送
    track
    事件。
若不存在更高级的路径,需在
rationale
中记录原因,再使用直接INSERT/PUBLISH操作。

Core rule — match the project's primary language

核心规则:匹配项目主语言

Use
runtimeProfile.primaryLanguage
from Phase 1 as the interpreter for every script. The project already has types, helpers, and clients in that language — reuse them.
primaryLanguage
interpreter
args
typescript
/
javascript
bun
["run"]
go
go
["run"]
python
python3
["-u"]
ruby
ruby
[]
java
/
kotlin
kotlinc
or
java
depends on build tool
rust
cargo
["script"]
(if available)
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
bash
/
python3
only when the project runtime can't execute scripts directly. Note the reason in
rationale
.

使用Phase 1中得到的
runtimeProfile.primaryLanguage
作为所有脚本的解释器。项目已包含该语言的类型定义、工具函数和客户端——直接复用即可。
primaryLanguage
interpreter
args
typescript
/
javascript
bun
["run"]
go
go
["run"]
python
python3
["-u"]
ruby
ruby
[]
java
/
kotlin
kotlinc
java
取决于构建工具
rust
cargo
["script"]
(若可用)
示例:
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)
}
备选方案: 仅当项目运行时无法直接执行脚本时,才使用
bash
/
python3
。需在
rationale
中记录原因。

Phase 0 — pre-flight (studio reachable)

Phase 0 — 预检(Studio可达性)

Resolve studio URL:
SEEFLOW_STUDIO_URL
env var →
~/.seeflow/config.json
port →
http://localhost:4321
.
bash
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:
    Studio not reachable at <url> and the seeflow CLI is not installed. Run: npx tuongaz/seeflow start
    or clone +
    make dev
    .
Do not retry. Do not auto-start. On success: continue to Phase 1.

解析Studio URL优先级:
SEEFLOW_STUDIO_URL
环境变量 →
~/.seeflow/config.json
端口 →
http://localhost:4321
bash
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
TaskCreate
checklist before launching any sub-agent:
[ ] 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
TaskUpdate
immediately after it succeeds.

在启动任何子代理前,创建
TaskCreate
检查清单:
[ ] Phase 1 — 发现代码库(语言、运行时、集成测试)
[ ] Phase 2 — 规划节点与连接器
[ ] Phase 3 — 注册骨架流程(仅包含节点)——等待用户审阅节点
[ ] Phase 4 — 设计Play + Status脚本(并行)
[ ] Phase 5 — 合成并验证Schema
[ ] Phase 6 — 编写脚本文件并重新注册完整流程
[ ] Phase 7 — 端到端验证(触发API,通过SSE验证)
每个任务成功完成后,立即通过
TaskUpdate
标记为已完成。

Phase 1 — discover

Phase 1 — 发现

Launch
seeflow-discoverer
with the user's prompt, project root, and any existing
seeflow.json
for the matching slug. Tools:
Read, Grep, Glob, LS, Bash
(read-only).
Discoverer 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.

启动
seeflow-discoverer
,传入用户提示、项目根目录以及匹配slug的现有
seeflow.json
文件。可使用工具:
Read, Grep, Glob, LS, Bash
(仅只读操作)。
Discoverer必须完成:
  • 识别主语言+运行时(
    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
seeflow-node-planner
with the context brief. No tools — pure reasoning. Two mandatory passes:
  • 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
kind
+
name
; unique
id
with a descriptive suffix (
"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个总连接数(入站+出站)。若超出限制:
    • 若节点有不同职责,则拆分节点。
    • 复制共享资源以打破中心辐射模式。
为清晰性而复制——当重复展示同一资源能提升可读性时,可覆盖“一个服务对应一个节点”的默认规则(例如,将共享数据库放在每个使用它的服务旁边)。使用相同的
kind
+
name
;使用带描述性后缀的唯一
id
(如
"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 = $PWD
  • flowDir = $PWD/.seeflow/<slug>
  • flowPath = .seeflow/<slug>/seeflow.json
  1. Build skeleton JSON from node draft — omit
    playAction
    ,
    statusAction
    ,
    resetAction
    . Keep
    version
    ,
    name
    ,
    nodes
    ,
    connectors
    .
  2. mkdir -p $flowDir
    then write to
    $flowDir/seeflow-nodes.json
    .
  3. Validate:
    bash
    bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-nodes.json"
    On failure: fix field-level issues in-place (no re-run of node-planner), retry.
  4. Write
    $flowDir/seeflow.json
    and register:
    bash
    bun skills/create-seeflow/scripts/register.ts --path "$repoPath" --flow "$flowPath"
    Stash the returned
    id
    .
  5. Ask the user:
    The nodes are live at
    <url>
    . Does the layout look right? Any additions, removals, or renames before I write the scripts?
Wait for response.
  • Approved → Phase 4.
  • Changes requested → re-run node-planner with feedback, repeat Phase 3.

注册骨架流程(仅包含节点和连接器,无脚本),以便用户在编写任何脚本前审阅画布。
路径(本阶段和Phase 6使用):
  • repoPath = $PWD
  • flowDir = $PWD/.seeflow/<slug>
  • flowPath = .seeflow/<slug>/seeflow.json
  1. 根据节点草稿构建骨架JSON——省略
    playAction
    statusAction
    resetAction
    。保留
    version
    name
    nodes
    connectors
  2. 执行
    mkdir -p $flowDir
    ,然后写入
    $flowDir/seeflow-nodes.json
  3. 验证:
    bash
    bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-nodes.json"
    若失败:就地修复字段级问题(无需重新运行node-planner),重试。
  4. 写入
    $flowDir/seeflow.json
    并注册:
    bash
    bun skills/create-seeflow/scripts/register.ts --path "$repoPath" --flow "$flowPath"
    保存返回的
    id
  5. 询问用户:
    节点已发布至
    <url>
    。布局是否合理?在编写脚本前,是否需要添加、删除或重命名节点?
等待用户回复。
  • 已批准 → 进入Phase 4。
  • 要求修改 → 根据反馈重新运行node-planner,重复Phase 3。

Phase 4 — design Play + Status (parallel)

Phase 4 — 设计Play + Status(并行)

Launch
seeflow-play-designer
and
seeflow-status-designer
in parallel (single message, two
Task
calls). Both receive: context brief + node draft + edit target. Tools:
Read, Grep, Glob, LS
.
seeflow-play-designer
returns:
json
{
  "playOverlays": [{
    "nodeId": "…",
    "playAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
                    "scriptPath": "<slug>/scripts/<name>.ts",
                    "input": {}, "timeoutMs": 30000 },
    "scriptBody": "…",
    "validationSafe": true,
    "rationale": "…"
  }],
  "newTriggerNodes": []
}
seeflow-status-designer
returns:
json
{
  "statusOverlays": [{
    "nodeId": "…",
    "statusAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
                      "scriptPath": "<slug>/scripts/<name>.ts",
                      "maxLifetimeMs": 600000 },
    "scriptBody": "…",
    "rationale": "…"
  }]
}
Sample data — look before inventing. Priority:
  1. Integration/e2e test fixtures (
    runtimeProfile.integrationTestDir
    ) — copy verbatim.
  2. Seed / migration fixtures (
    seed.*
    ,
    fixtures/
    ,
    testdata/
    , ORM factories).
  3. README / OpenAPI / Postman examples.
  4. Invent as last resort — note in
    rationale
    .
newTriggerNodes
may inject synthetic source nodes (file-drop, webhook receiver) when no natural trigger exists.

并行启动
seeflow-play-designer
seeflow-status-designer
(单个消息,两次
Task
调用)。两者均接收:上下文摘要+节点草稿+编辑目标。可使用工具:
Read, Grep, Glob, LS
seeflow-play-designer
返回:
json
{
  "playOverlays": [{
    "nodeId": "…",
    "playAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
                    "scriptPath": "<slug>/scripts/<name>.ts",
                    "input": {}, "timeoutMs": 30000 },
    "scriptBody": "…",
    "validationSafe": true,
    "rationale": "…"
  }],
  "newTriggerNodes": []
}
seeflow-status-designer
返回:
json
{
  "statusOverlays": [{
    "nodeId": "…",
    "statusAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
                      "scriptPath": "<slug>/scripts/<name>.ts",
                      "maxLifetimeMs": 600000 },
    "scriptBody": "…",
    "rationale": "…"
  }]
}
示例数据:优先查找而非编造。优先级:
  1. 集成/端到端测试用例(
    runtimeProfile.integrationTestDir
    )——直接复制。
  2. 种子/迁移测试用例(
    seed.*
    fixtures/
    testdata/
    、ORM工厂)。
  3. README/OpenAPI/Postman示例。
  4. 最后才考虑编造——需在
    rationale
    中记录。
当不存在天然触发器时,
newTriggerNodes
可注入合成源节点(文件上传、Webhook接收器)。

Phase 5 — synthesize + validate schema

Phase 5 — 合成 + 验证Schema

  1. Splice
    newTriggerNodes
    into
    nodeDraft.nodes
    (add any required connectors).
  2. Merge each overlay onto its target node's
    data
    . Strip
    validationSafe
    ,
    rationale
    ,
    scriptBody
    — orchestrator metadata, not schema fields. Collect
    nodeId
    s where
    validationSafe: false
    into
    unsafeNodeIds
    .
  3. Write merged flow to
    $flowDir/seeflow-draft.json
    .
  4. Validate:
bash
bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-draft.json"
{"ok":true}
→ continue.
{"ok":false,"issues":[…]}
→ feed issues back to the relevant designer, retry. Max 3 retries, then surface verbatim and stop.
  1. Proceed to Phase 6 — node layout was approved in Phase 3.

  1. 插入
    newTriggerNodes
    nodeDraft.nodes
    中(添加所需的连接器)。
  2. 合并每个叠加层到目标节点的
    data
    中。移除
    validationSafe
    rationale
    scriptBody
    ——这些是编排器元数据,不属于Schema字段。将
    validationSafe: false
    nodeId
    收集到
    unsafeNodeIds
    中。
  3. 写入合并后的流程到
    $flowDir/seeflow-draft.json
  4. 验证:
bash
bun skills/create-seeflow/scripts/validate-schema.ts "$flowDir/seeflow-draft.json"
返回
{"ok":true}
→ 继续。返回
{"ok":false,"issues":[…]}
→ 将问题反馈给对应的设计器,重试。最多重试3次,然后直接告知用户并停止。
  1. 进入Phase 6——节点布局已在Phase 3获得批准。

Phase 6 — write script files + re-register full flow

Phase 6 — 编写脚本文件 + 重新注册完整流程

  1. mkdir -p $flowDir/scripts $flowDir/state
  2. Write files (overwriting the Phase 3 skeleton):
    • $flowDir/seeflow.json
      — validated flow JSON with all actions.
    • $flowDir/scripts/<name>
      — one file per overlay
      scriptBody
      .
      chmod +x
      .
    • $flowDir/state/.gitignore
      *
      .
  3. Re-register:
bash
bun skills/create-seeflow/scripts/register.ts --path "$repoPath" --demo "$flowPath"
Prints
{id, slug}
. Use the new
id
for Phases 7 + 8.
On 400: show body, ask "fix-and-retry / stop". On other 4xx/5xx: show body, stop.

  1. 执行
    mkdir -p $flowDir/scripts $flowDir/state
  2. 写入文件(覆盖Phase 3的骨架文件):
    • $flowDir/seeflow.json
      ——包含所有操作的已验证流程JSON。
    • $flowDir/scripts/<name>
      ——每个叠加层对应一个
      scriptBody
      文件。执行
      chmod +x
      赋予执行权限。
    • $flowDir/state/.gitignore
      ——内容为
      *
  3. 重新注册:
bash
bun skills/create-seeflow/scripts/register.ts --path "$repoPath" --demo "$flowPath"
输出
{id, slug}
。使用新的
id
进行Phase 7和后续操作。
若返回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
--skip-nodes
when
unsafeNodeIds
is non-empty (nodes that hit third-party services or charge money). Skipped nodes appear in
skipped[]
and are not counted as failures.
The script:
  • GETs
    /api/demos/<id>
    (expects 200,
    valid: true
    ).
  • Opens SSE at
    /api/events?demoId=<id>
    before triggering plays.
  • POSTs
    /api/demos/<id>/play/<nodeId>
    for each safe play node; awaits response.
  • Drains SSE for
    node:done
    /
    node:error
    /
    node:status
    events. SSE outcome takes precedence.
  • Hard ceiling: ~2 minutes. Emits
    {ok, plays, statuses, skipped}
    .
Interpret the JSON. On
ok: true
→ print
Flow "<name>" registered as <slug>. Open: $STUDIO_URL/d/<slug>
. Done. On
ok: false
:
  1. Identify failing nodes from
    plays[*].error
    /
    statuses[*].outcome
    .
  2. Propose a concrete fix ("play-checkout.ts:
    ECONNREFUSED
    on port 3001 — start the app first").
  3. Dispatch one sub-agent per failing script in parallel.
  4. Edit scripts in-place, re-run Phase 7 against the same
    <id>
    . Max 2 retries, then ask
    retry / stop
    .
Never re-run
register.ts
in the fix-up loop.

必须执行,不得跳过或模拟。
bash
bun skills/create-seeflow/scripts/validate-end-to-end.ts <id> [--skip-nodes <id1>,<id2>]
unsafeNodeIds
非空时(涉及第三方服务或产生费用的节点),传入
--skip-nodes
参数。被跳过的节点会出现在
skipped[]
中,不计入失败。
该脚本执行以下操作:
  • GET请求
    /api/demos/<id>
    (预期返回200,
    valid: true
    )。
  • 在触发play操作前,打开
    /api/events?demoId=<id>
    的SSE连接。
  • 对每个安全的play节点POST请求
    /api/demos/<id>/play/<nodeId>
    ;等待响应。
  • 监听SSE的
    node:done
    /
    node:error
    /
    node:status
    事件。SSE结果优先级最高。
  • 最长耗时:约2分钟。输出
    {ok, plays, statuses, skipped}
解析JSON结果。若
ok: true
→ 打印
Flow "<name>"已注册为<slug>。访问地址:$STUDIO_URL/d/<slug>
。操作完成。若
ok: false
  1. plays[*].error
    /
    statuses[*].outcome
    中识别失败节点。
  2. 提出具体修复方案(例如“play-checkout.ts:端口3001连接被拒绝——请先启动应用”)。
  3. 并行为每个失败脚本调度一个子代理。
  4. 就地编辑脚本,使用相同的
    <id>
    重新运行Phase 7。最多重试2次,然后询问用户“重试 / 停止”。
修复循环中不得重新运行
register.ts

Error-handling table

错误处理表

FailureResponse
Studio
/health
fails
which seeflow
→ if found:
seeflow start
; if not:
npx tuongaz/seeflow
or clone +
make dev
. No retry.
Sub-agent unparseable outputRetry 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 otherShow body; stop.
Play
{error: "…"}
(Phase 7)
Edit scripts in-place; re-run Phase 7 (max 2 retries). Do NOT re-register.
Status SSE timeout 10sMark
no status received
; include in fix-up or ask retry/stop.
Validation >2 min
ok:false
; treat as failure → fix-up path.
Retry caps: Phase 5 schema → 3. Phase 7 fix-up → 2.

失败场景响应方式
Studio
/health
请求失败
执行
which seeflow
→ 若找到CLI:提示
seeflow start
;若未找到:提示
npx tuongaz/seeflow
或克隆仓库后执行
make dev
。不重试。
子代理输出无法解析携带解析错误重试一次;若仍失败,告知用户并停止。
Schema验证失败(Phase 5)将Zod错误反馈给对应的设计器。最多重试3次。
注册返回400(Phase 6)展示响应体;询问用户“修复并重试 / 停止”。
注册返回其他4xx/5xx展示响应体;停止操作。
Play返回
{error: "…"}
(Phase 7)
就地编辑脚本;重新运行Phase 7(最多重试2次)。不得重新注册。
Status SSE超时10秒标记为“未收到状态”;纳入修复流程或询问用户重试/停止。
验证耗时超过2分钟返回
ok:false
;视为失败 → 进入修复流程。
重试上限:Phase 5 Schema验证 → 3次。Phase 7修复 → 2次

Schema cheatsheet

Schema速查表

Full schema:
skills/create-seeflow/vendored/schema.ts
. Below covers ~95% of cases.
完整Schema:
skills/create-seeflow/vendored/schema.ts
。以下内容覆盖约95%的使用场景。

Flow envelope

流程信封

json
{
  "version": 1,
  "name": "Checkout Flow",
  "nodes": [ …NodeSchema… ],
  "connectors": [ …ConnectorSchema… ],
  "resetAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
                   "scriptPath": "<slug>/scripts/reset.ts" }
}
resetAction
is optional — include only if the app has a "wipe state" entrypoint.
json
{
  "version": 1,
  "name": "Checkout Flow",
  "nodes": [ …NodeSchema… ],
  "connectors": [ …ConnectorSchema… ],
  "resetAction": { "kind": "script", "interpreter": "bun", "args": ["run"],
                   "scriptPath": "<slug>/scripts/reset.ts" }
}
resetAction
为可选字段——仅当应用有“清除状态”入口时才添加。

Node types

节点类型

playNode — has a clickable Play button. Required:
name
,
kind
,
stateSource
,
playAction
. Optional:
statusAction
,
description
(≤ 15 words),
detail
.
RULE — detail on important nodes: Every
playNode
and
stateNode
that carries meaningful behaviour MUST include a
detail
field.
detail
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
shapeNode
/
iconNode
entries are exempt.
kind
:
service
,
endpoint
,
worker
,
workflow
,
queue
,
topic
,
bus
,
db
,
store
,
cache
,
scheduler
,
external-api
,
trigger
.
json
{
  "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
kind
values.
json
{
  "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.
shape
Renders asBest for
database
CylinderDB label (use
stateNode
when monitoring)
server
Server rackOn-premise server or compute
user
Person silhouetteHuman actor / customer
queue
StackQueue label (decorative)
cloud
Cloud outlineExternal SaaS
rectangle
BoxGrouping boundary
ellipse
OvalAnnotation
sticky
Sticky noteCallout
text
Plain textCanvas 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
<script>
,
<style>
,
<iframe>
,
on*=
attributes,
javascript:
URLs).
Required fields:
  • htmlPath
    — relative path under
    .seeflow/
    . No leading
    /
    , no
    ..
    . E.g.
    checkout-flow/legend.html
    .
Optional styling fields (same as shapeNode):
width
,
height
,
backgroundColor
,
borderColor
,
borderSize
,
borderStyle
,
cornerRadius
,
fontSize
,
textColor
,
name
(caption below node),
description
,
detail
Default size: 320 × 200 px. Set
width
/
height
to override.
json
{ "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
$flowDir/<name>.html
. Tailwind classes work; no
<script>
or
<style>
(stripped by sanitiser). Use inline styles for anything Tailwind can't cover. See
references/examples/html-node-example.html
.
When NOT to use: If a
shapeNode
with a label, an
iconNode
, or a
stateNode
covers the content, prefer those — they participate in theming and status updates automatically.
imageNode — 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按钮。必填字段:
name
kind
stateSource
playAction
。可选字段:
statusAction
description
(≤15个单词)、
detail
规则:重要节点需添加detail——每个承载有意义行为的
playNode
stateNode
必须包含
detail
字段。
detail
markdown格式渲染——用于解释节点功能、输出内容、重要性、示例请求体、源码链接,或任何受众可能询问的信息。装饰性的
shapeNode
/
iconNode
无需添加。
kind
可选值:
service
endpoint
worker
workflow
queue
topic
bus
db
store
cache
scheduler
external-api
trigger
json
{
  "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按钮;受众仅查看状态,不触发操作。
kind
可选值与playNode相同。
json
{
  "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——装饰/说明性节点。无操作或实时状态。
shape
渲染样式适用场景
database
圆柱体数据库标签(监控时使用
stateNode
server
服务器机架本地服务器或计算资源
user
人物剪影人类角色/客户
queue
堆叠形状队列标签(装饰用)
cloud
云轮廓外部SaaS服务
rectangle
矩形框分组边界
ellipse
椭圆形注释
sticky
便签纸标注
text
纯文本画布标签
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(工具类可正常使用),然后在渲染前进行清理(移除
<script>
<style>
<iframe>
on*=
属性、
javascript:
URL)。
必填字段:
  • htmlPath
    ——
    .seeflow/
    下的相对路径。无前导
    /
    ,无
    ..
    。例如
    checkout-flow/legend.html
可选样式字段(与shapeNode相同):
width
height
backgroundColor
borderColor
borderSize
borderStyle
cornerRadius
fontSize
textColor
name
(节点下方的标题)、
description
detail
默认尺寸: 320 × 200 px。可设置
width
/
height
覆盖默认值。
json
{ "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文件——写入
$flowDir/<name>.html
。Tailwind类可正常使用;不得包含
<script>
<style>
(会被清理器移除)。对于Tailwind无法覆盖的样式,使用内联样式。示例见
references/examples/html-node-example.html
不适用场景:
shapeNode
(带标签)、
iconNode
stateNode
可覆盖内容,优先使用这些节点——它们会自动适配主题和状态更新。
imageNode——
.seeflow/
下的装饰性图片。
json
{ "id": "logo", "type": "imageNode", "position": { "x": 0, "y": 0 },
  "data": { "path": "checkout-flow/logo.png", "alt": "Stripe logo" } }

Connectors

连接器

Required:
id
,
source
,
target
,
kind
.
json
{ "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):
style
(
solid|dashed|dotted
),
direction
(
forward|backward|both|none
),
path
(
curve|step
),
color
,
borderSize
,
fontSize
,
label
,
sourceHandle
/
targetHandle
(
r|b
/
t|l
).
必填字段:
id
source
target
kind
json
{ "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" }
可选视觉字段(所有类型):
style
solid|dashed|dotted
)、
direction
forward|backward|both|none
)、
path
curve|step
)、
color
borderSize
fontSize
label
sourceHandle
/
targetHandle
r|b
/
t|l
)。

stateSource

stateSource

json
{ "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

playAction
/
statusAction
/
resetAction

json
{ "kind": "script", "interpreter": "bun", "args": ["run"],
  "scriptPath": "<slug>/scripts/<file>.ts", "input": {…optional…},
  "timeoutMs": 30000 }
  • scriptPath
    — relative under
    .seeflow/
    . No leading slash, no
    ..
    .
  • interpreter
    — must match
    runtimeProfile.primaryLanguage
    . Values:
    bun
    ,
    go
    ,
    python3
    ,
    node
    ,
    bash
    .
  • input
    (playAction) — JSON-serialised, piped to stdin.
  • timeoutMs
    (playAction; max 600 000) — be generous:
    • 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.
  • maxLifetimeMs
    (statusAction; max 3 600 000) — default 600 000; bump to 1 800 000 for long async flows.
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
  • input
    (playAction)——JSON序列化后,通过标准输入传递。
  • timeoutMs
    (playAction;最大600000)——设置足够长的时间:
    • 简单HTTP请求 → 15000 ms。
    • Go/Rust(首次运行需编译) → 60000–120000 ms。
    • Java/Kotlin(JVM启动) → 至少120000 ms。
    • 数据库初始化/迁移 → 至少60000 ms。
  • maxLifetimeMs
    (statusAction;最大3600000)——默认600000;对于长异步流程,可提升至1800000。

StatusReport
(stdout line shape)

StatusReport
(标准输出行格式)

json
{ "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

子代理参考

AgentToolsUsed for
seeflow-discoverer
Read, Grep, Glob, LS, Bash
(read-only)
Phase 1: explore codebase, return context brief
seeflow-node-planner
none (pure reasoning)Phase 2: pick nodes + connectors
seeflow-play-designer
Read, Grep, Glob, LS
Phase 4: design playActions + script bodies
seeflow-status-designer
Read, Grep, Glob, LS
Phase 4: design statusActions + script bodies
Full prompts + worked examples in
skills/create-seeflow/agents/<agent>.md
.
代理可用工具用途
seeflow-discoverer
Read, Grep, Glob, LS, Bash
(仅只读操作)
Phase 1:探索代码库,返回上下文摘要
seeflow-node-planner
无(纯逻辑推理)Phase 2:选择节点和连接器
seeflow-play-designer
Read, Grep, Glob, LS
Phase 4:设计playActions和脚本内容
seeflow-status-designer
Read, Grep, Glob, LS
Phase 4:设计statusActions和脚本内容
完整提示语和示例见
skills/create-seeflow/agents/<agent>.md

Studio API touchpoints

Studio API接口

EndpointMethodPhaseBody
/health
GET0
/api/demos/register
POST3, 6
{name, repoPath, demoPath}
/api/demos/:id
GET7
/api/demos/:id/play/:nodeId
POST7
/api/events?demoId=:id
GET (SSE)7
/api/demos/:id
DELETErollback only
Never invent endpoints. Surface anything outside this table to the user.
接口请求方法阶段请求体
/health
GET0
/api/demos/register
POST3, 6
{name, repoPath, demoPath}
/api/demos/:id
GET7
/api/demos/:id/play/:nodeId
POST7
/api/events?demoId=:id
GET (SSE)7
/api/demos/:id
DELETE仅回滚时使用
不得自行编造接口。若遇到不在此列表中的接口,直接告知用户。