Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions web/app/flows/flow-examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ export const flowExamples = [
"title": "Draft the reply. Let a human decide.",
"description": "Draft a response to a support thread, get approval, and reply in Slack.",
"filename": "support-triage.flow.ts",
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n message: string;\n channel: string;\n threadTs: string;\n approver: string;\n};\n\nexport default flow<Input>(\n \"support-triage\",\n { budget: \"$5/run\" },\n async (f, input) => {\n await f.agent(\"triage\", {\n task: `Classify this request: ${input.message}. ` +\n \"Write the category and urgency to triage.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s triage.md` });\n\n await f.agent(\"writer\", {\n task: `Read triage.md and draft a reply to: ` +\n `${input.message}. Write only the reply to reply.md.`,\n }).gate({ type: \"subprocess_gate\", command: `test -s reply.md` });\n\n const reply = await f.run(\"cat reply.md\");\n // f.human is declared but not yet executed by the SDK (flows#400) \u2014 this\n // shows the intended approval gate, not a runnable one, until it lands.\n const approved = await f.human(\n `Send this reply?\\n\\n${reply}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n // Send only after a human approves.\n await f.slack.reply(input.channel, input.threadTs, reply);\n f.done(\"success\");\n },\n);"
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n message: string;\n channel: string;\n threadTs: string;\n approver: string;\n};\n\nexport default flow<Input>(\n \"support-triage\",\n { budget: \"$5/run\" },\n async (f, input) => {\n await f.agent(\"triage\", {\n task: `Classify this request: ${input.message}. ` +\n \"Write the category and urgency to triage.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s triage.md` });\n\n await f.agent(\"writer\", {\n task: `Read triage.md and draft a reply to: ` +\n `${input.message}. Write only the reply to reply.md.`,\n }).gate({ type: \"subprocess_gate\", command: `test -s reply.md` });\n\n const reply = await f.run(\"cat reply.md\");\n const approved = await f.human(\n `Send this reply?\\n\\n${reply}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n // Send only after a human approves.\n await f.slack.reply(input.channel, input.threadTs, reply);\n f.done(\"success\");\n },\n);"
},
{
"id": "content-pipeline",
"label": "Content publishing",
"title": "Put a fact-check between draft and publish.",
"description": "Research, draft, and check a post before a human approves sharing it in Slack.",
"filename": "content-pipeline.flow.ts",
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n topic: string;\n channel: string;\n approver: string;\n};\n\nexport default flow<Input>(\n \"content-pipeline\",\n { budget: \"$5/run\" },\n async (f, input) => {\n await f.agent(\"researcher\", {\n task: `Research ${input.topic}. Cite your sources. ` +\n \"Write research.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s research.md` });\n\n await f.agent(\"writer\", {\n task: \"Use research.md to write post.md. \" +\n \"Keep the source links with each claim.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s post.md` });\n\n await f.agent(\"fact-checker\", {\n task: \"Check post.md against its sources. \" +\n \"Write checked.passed only if all claims hold up.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s checked.passed` });\n\n const post = await f.run(\"cat post.md\");\n // f.human is declared but not yet executed by the SDK (flows#400) \u2014 this\n // shows the intended approval gate, not a runnable one, until it lands.\n const approved = await f.human(\n `Publish this post?\\n\\n${post}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n await f.slack.post(input.channel, post);\n f.done(\"success\");\n },\n);"
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n topic: string;\n channel: string;\n approver: string;\n};\n\nexport default flow<Input>(\n \"content-pipeline\",\n { budget: \"$5/run\" },\n async (f, input) => {\n await f.agent(\"researcher\", {\n task: `Research ${input.topic}. Cite your sources. ` +\n \"Write research.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s research.md` });\n\n await f.agent(\"writer\", {\n task: \"Use research.md to write post.md. \" +\n \"Keep the source links with each claim.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s post.md` });\n\n await f.agent(\"fact-checker\", {\n task: \"Check post.md against its sources. \" +\n \"Write checked.passed only if all claims hold up.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s checked.passed` });\n\n const post = await f.run(\"cat post.md\");\n const approved = await f.human(\n `Publish this post?\\n\\n${post}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n await f.slack.post(input.channel, post);\n f.done(\"success\");\n },\n);"
},
{
"id": "repo-migration",
Expand All @@ -45,7 +45,7 @@ export const flowExamples = [
"title": "Turn a voicemail into a callback brief.",
"description": "Use a transcript to prepare the callback, then send the approved brief to a teammate.",
"filename": "voicemail-follow-up.flow.ts",
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n transcript: string;\n approver: string;\n callbackOwner: string;\n};\n\nexport default flow<Input>(\n \"voicemail-follow-up\",\n { budget: \"$5/run\" },\n async (f, input) => {\n await f.agent(\"triage\", {\n task: `Read this voicemail: ${input.transcript}. ` +\n \"Identify urgency and the caller's request. \" +\n \"Write triage.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s triage.md` });\n\n await f.agent(\"callback-writer\", {\n task: \"Read triage.md. Prepare a callback brief \" +\n \"with the questions we need to answer. \" +\n \"Write callback.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s callback.md` });\n\n const brief = await f.run(\"cat callback.md\");\n // f.human is declared but not yet executed by the SDK (flows#400) \u2014 this\n // shows the intended approval gate, not a runnable one, until it lands.\n const approved = await f.human(\n `Ready for a callback?\\n\\n${brief}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n await f.slack.dm(input.callbackOwner, brief);\n f.done(\"success\");\n },\n);"
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n transcript: string;\n approver: string;\n callbackOwner: string;\n};\n\nexport default flow<Input>(\n \"voicemail-follow-up\",\n { budget: \"$5/run\" },\n async (f, input) => {\n await f.agent(\"triage\", {\n task: `Read this voicemail: ${input.transcript}. ` +\n \"Identify urgency and the caller's request. \" +\n \"Write triage.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s triage.md` });\n\n await f.agent(\"callback-writer\", {\n task: \"Read triage.md. Prepare a callback brief \" +\n \"with the questions we need to answer. \" +\n \"Write callback.md.\",\n }).gate({ type: \"subprocess_gate\", command: `test -s callback.md` });\n\n const brief = await f.run(\"cat callback.md\");\n const approved = await f.human(\n `Ready for a callback?\\n\\n${brief}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n await f.slack.dm(input.callbackOwner, brief);\n f.done(\"success\");\n },\n);"
},
{
"id": "research-report",
Expand All @@ -61,7 +61,7 @@ export const flowExamples = [
"title": "Choose what the summarizer gets to see.",
"description": "Select the fields needed for the task before putting a record into the agent prompt.",
"filename": "redacted-summary.flow.ts",
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n record: { category: string; status: string; email: string };\n approver: string;\n};\n\nexport default flow<Input>(\n \"redacted-summary\",\n { budget: \"$5/run\" },\n async (f, input) => {\n // Select fields in code before building the prompt.\n // The email address is excluded from this input.\n const selected = {\n category: input.record.category,\n status: input.record.status,\n };\n\n await f.agent(\"summarizer\", {\n task: `Summarize this record: ` +\n `${JSON.stringify(selected)}. Write summary.md.`,\n }).gate({ type: \"subprocess_gate\", command: `test -s summary.md` });\n\n const summary = await f.run(\"cat summary.md\");\n // f.human is declared but not yet executed by the SDK (flows#400) \u2014 this\n // shows the intended approval gate, not a runnable one, until it lands.\n const approved = await f.human(\n `Review this summary before sharing:\\n\\n${summary}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n f.done(\"success\");\n },\n);"
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = {\n record: { category: string; status: string; email: string };\n approver: string;\n};\n\nexport default flow<Input>(\n \"redacted-summary\",\n { budget: \"$5/run\" },\n async (f, input) => {\n // Select fields in code before building the prompt.\n // The email address is excluded from this input.\n const selected = {\n category: input.record.category,\n status: input.record.status,\n };\n\n await f.agent(\"summarizer\", {\n task: `Summarize this record: ` +\n `${JSON.stringify(selected)}. Write summary.md.`,\n }).gate({ type: \"subprocess_gate\", command: `test -s summary.md` });\n\n const summary = await f.run(\"cat summary.md\");\n const approved = await f.human(\n `Review this summary before sharing:\\n\\n${summary}`,\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n\n f.done(\"success\");\n },\n);"
},
{
"id": "ci-repair",
Expand All @@ -77,7 +77,7 @@ export const flowExamples = [
"title": "Send each issue to the right specialist.",
"description": "Route bugs to an implementer and documentation requests to a writer. Ask a human when the category is uncertain.",
"filename": "issue-routing.flow.ts",
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = { issue: string; approver: string };\n\nexport default flow<Input>(\"issue-routing\", async (f, input) => {\n const classification = await f.agent(\"router\", {\n cli: \"claude\",\n task: `Classify this issue: ${input.issue}. ` +\n \"Return only bugfix, docs, or uncertain as your summary. \" +\n \"Choose uncertain if the request is ambiguous.\",\n });\n let route = classification.summary.trim().toLowerCase();\n\n // Unknown output never silently selects a specialist.\n if (route !== \"bugfix\" && route !== \"docs\") {\n // f.human is declared but not yet executed by the SDK (flows#400) \u2014 this\n // shows the intended approval gate, not a runnable one, until it lands.\n const approved = await f.human(\n `Needs manual triage: ${input.issue}\\n` +\n \"Route this to the bugfix specialist?\",\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n route = \"bugfix\";\n }\n\n if (route === \"bugfix\") {\n await f.agent(\"implementer\", {\n cli: \"codex\",\n task: `Fix this issue and add regression coverage: ${input.issue}`,\n });\n await f.run(\"npm test\");\n } else {\n await f.agent(\"docs-writer\", {\n cli: \"claude\",\n task: `Update the documentation for: ${input.issue}. ` +\n \"Check examples against the implementation.\",\n });\n }\n f.done(\"success\");\n});"
"code": "import { flow } from \"@relayflows/surface\";\n\ntype Input = { issue: string; approver: string };\n\nexport default flow<Input>(\"issue-routing\", async (f, input) => {\n const classification = await f.agent(\"router\", {\n cli: \"claude\",\n task: `Classify this issue: ${input.issue}. ` +\n \"Return only bugfix, docs, or uncertain as your summary. \" +\n \"Choose uncertain if the request is ambiguous.\",\n });\n let route = classification.summary.trim().toLowerCase();\n\n // Unknown output never silently selects a specialist.\n if (route !== \"bugfix\" && route !== \"docs\") {\n const approved = await f.human(\n `Needs manual triage: ${input.issue}\\n` +\n \"Route this to the bugfix specialist?\",\n { to: input.approver },\n );\n if (!approved) return f.done(\"declined\");\n route = \"bugfix\";\n }\n\n if (route === \"bugfix\") {\n await f.agent(\"implementer\", {\n cli: \"codex\",\n task: `Fix this issue and add regression coverage: ${input.issue}`,\n });\n await f.run(\"npm test\");\n } else {\n await f.agent(\"docs-writer\", {\n cli: \"claude\",\n task: `Update the documentation for: ${input.issue}. ` +\n \"Check examples against the implementation.\",\n });\n }\n f.done(\"success\");\n});"
},
{
"id": "competing-implementations",
Expand Down
Loading
Loading