Originally published on flowrunner.ai. I run FlowRunner, so this is our product. The workflows are Raymond Camden's, used with his permission.
Every demo on this page starts from a real Pipedream workflow and ends as a working, tested FlowRunner flow. We show the files that went in, what the builder made from them, what still needed a person, like reconnecting accounts or picking the right spreadsheet, and where the result differs from the original.
Pipedream workflows come out in one of two formats, and the builder reads both. If your project used GitHub Sync, your repo already holds each workflow as a workflow.yaml file with one code file per step. Otherwise, Pipedream's Export Workflows tool gives you a ZIP with one JSON file per workflow. Each demo says which format it started from. For the shutdown dates, what the export leaves out, and where each Pipedream piece lands in FlowRunner, see our Pipedream migration guide.
We add conversions as we do them. If you'd like yours converted, send us your files and we'll do it for free. With your permission, it goes on this page with anything identifying removed.
How the conversion works
FlowRunner's Prompt to Flow works through an MCP server. Add it to Claude, ChatGPT, Claude Code, Codex, or Cursor, sign in to your FlowRunner account, paste in a workflow's files, and ask for the same thing as a FlowRunner flow. In Claude Code that's one command:
claude mcp add --transport http flowrunner https://app.flowrunner.ai/mcp The builder reads the triggers, steps, code, and branches in the file and builds the flow in your workspace. It rewrites Python steps in JavaScript, and it asks about anything the file can't tell it.
What it can't do is bring your credentials across. Neither format carries connected accounts or secrets, and neither carries your data stores, so every conversion ends with a short list of things to finish by hand. Each demo below shows that list as the builder gave it.
A moderated guestbook, in three workflows
Raymond Camden ran the guestbook on his site with three Pipedream workflows, and he keeps them public in his General-Pipedream-Stuff repo. Thanks to Raymond for letting us use them. Together they make a small moderation loop: a visitor's entry lands in a Google Sheet, Raymond gets an email with an approve link, and the site only shows entries he approved.
The input for all three was his GitHub Sync files, exactly as they sit in the repo: each workflow's workflow.yaml plus one JavaScript file per code step. Each conversion started with the same request, followed by the files:
Rebuild this Pipedream workflow as a FlowRunner flow. It comes from Pipedream's GitHub Sync: workflow.yaml lists the trigger and the steps in order, and the source of each code step follows it. Keep the same behavior. Before you build, tell me anything you can't map one to one, and ask me about anything the files don't say (for example the trigger's schedule or URL, which GitHub Sync doesn't record).
Because the request asks for it, the builder listed what it couldn't map one to one and asked its questions before building anything. All three flows were then connected to a test spreadsheet and a Gmail account and tested end to end.
1. Add Guestbook Entry
A visitor's form posts a name and a comment. The workflow checks both are there, adds a row to the sheet with Approved set to FALSE, and emails Raymond the entry with a "Click to Approve" link. (Original files)
schema: workflow/2022.04 name: Add Guestbook Entry settings: error_notification: true triggers: - id: hi_mJH1wmn steps: - namespace: validate runtime: nodejs20.x uses: "./validate/entry.js" - namespace: add_single_row runtime: nodejs20.x uses: google_sheets-add-single-row@2.1.2 props: googleSheets: authProvisionId: apn_DphexA sheetId: __lv: label: Guestbook value: 1RLspI8iuC-Ng8Fco8zV-ynpxdPLm7MgoXm5jnlo0Tpk sheetName: __lv: label: Sheet1 value: Sheet1 hasHeaders: 'Yes' col_0000: "{{steps.trigger.event.body.name.replace(/<.*?>/g,'')}}" col_0001: "{{steps.trigger.event.body.comment.replace(/<.*?>/g,'')}}" col_0002: "{{Date.now()}}" col_0003: 'FALSE' - namespace: create_email_body runtime: nodejs20.x uses: "./create_email_body/entry.js" - namespace: send_email_to_self runtime: nodejs20.x uses: email-send-email-to-self@0.4.4 props: subject: New Guestbook Entry text: "{{steps.create_email_body.$return_value}}" html: "{{steps.create_email_body.$return_value}}" | Pipedream | FlowRunner |
|---|---|
| HTTP trigger | External Callback. The posted JSON body becomes the trigger data. |
validate code step, which ends the run with $.flow.exit | A Condition: name and comment both present. The No branch has nothing after it, so the run ends there. |
Code inside the column fields (strip HTML tags, Date.now()) | A small Custom Cloud Code step that prepares the row. FlowRunner fields take references to earlier results, not code. |
| Google Sheets, Add Single Row | Google Sheets, Add Row. It returns the range the row landed in, which the approve link needs. |
create_email_body code step | Custom Cloud Code, with Raymond's HTML almost unchanged. |
The APPROVE_GB environment variable | The Approve flow's address, written into the email code step. |
| Email, Send Email To Self | Gmail, Send Email, addressed to the owner. |
The two code steps carry Raymond's logic over. The first holds what Pipedream ran inside the column fields: stripping HTML tags from the name and comment, and the Date.now() timestamp.
The second is Raymond's email HTML, with the approve flow's address passed in where his code read the APPROVE_GB variable, and the row's range taken from the Add Row step.
Left to finish by hand: connect Google Sheets and Gmail, pick the spreadsheet, set the address the email goes to, and start the flow.
Tested: a test entry added the row, with Approved set to FALSE, and the email arrived with a working approve link.
Notes: the builder replaced the validation code with a Condition block, which shows on the canvas instead of hiding in code. Pipedream's Send Email To Self needed no setup; on FlowRunner the email goes through your own email account, so you connect one.
2. Approve Guestbook Entry
The approve link in the email opens this workflow with the new row's range in the address. It sets that row's Approved cell to TRUE, and the entry shows up on the site. (Original files)
| Pipedream | FlowRunner |
|---|---|
| HTTP trigger | External Callback. The range in the link becomes the trigger data. |
The cell expression range.split(':').pop() in the Update Cell step | A one-line Custom Cloud Code step that picks the Approved cell, for example D5. |
| Google Sheets, Update Cell | Google Sheets, Update Cell by A1, set to TRUE. |
| A code step that redirects the browser to the guestbook page | Not reproduced. See the notes. |
Raymond's one-line cell expression became a one-line code step, and its result feeds the Google Sheets block's cell address.
Left to finish by hand: connect Google Sheets and pick the spreadsheet, then start the flow.
Tested: clicking the approve link in the test email set that row's Approved cell to TRUE.
Notes: Raymond's last step sends the browser back to his guestbook page with a redirect. Our version doesn't, so the browser shows FlowRunner's run ID instead of the guestbook page.
3. Get Guestbook Entries
The guestbook page calls this workflow to get the approved entries. It reads the sheet, keeps the approved rows, and answers with them as JSON. (Original files)
| Pipedream | FlowRunner |
|---|---|
HTTP trigger plus a $.respond step that answers the caller | A flow with no trigger block that ends in Return Result, called through the blocking Call Flow API, so the caller gets the answer in the same request. |
Google Sheets, Get Values in Range (A2:D10000) | Google Sheets, Get Rows. Rows come back keyed by the header names instead of by position, with no row cap. |
filter_and_map code step | Custom Cloud Code that reads the columns by name and returns name, comment, and date for each approved row. |
return_approved code step ($.respond with JSON) | Return Result, content type JSON. |
Because the rows now come back keyed by their headers, the filter reads r.Approved and r.Name where Raymond's code read a[3] and a[0].
Left to finish by hand: connect Google Sheets and pick the spreadsheet, then start the flow.
Tested: the call returned exactly what Raymond's workflow returns, the approved entries as a JSON array:
[{"name":"Ada","comment":"Hello from the test","date":"1791494504814"}] Notes: this is the one workflow whose trigger changed shape. A Pipedream HTTP trigger can answer its caller directly; on FlowRunner, a flow that answers its caller is called through the blocking API instead. The calling address includes your workspace key, so call it from a server and pass the key in a header rather than from the visitor's browser.









