Managed Workflows: Describe the Job, Read the Plan, Keep the Program
There is a particular kind of work that never quite justifies learning to code, and never quite stops being annoying.
Every Monday you pull last week's raw footage into an album. You transcribe the interviews. You cut the three obvious highlights. You drop a summary in Slack. It takes ninety minutes, most of it waiting, and you have done it forty times. It is not hard. It is not interesting. It is exactly the shape of thing a script should do — and writing that script means learning an API, reading docs, and maintaining something you'll touch twice a year.
Today we're shipping Managed Workflows. You describe that job in plain language. 5AM writes you a Python program that drives the 5am CLI — the same CLI you'd type by hand. You read a plan before any code exists, edit the code once it does, and then either download the file and run it wherever you like, or hand it to us to run in the cloud.
The important word in all of that is program. Not a saved chain of blocks. Not a prompt you re-run and hope. A file, on your disk, that you can read.
Describe it
Start at /workflows with a sentence or a paragraph. The vaguer version works, it just produces more questions:
Every Monday, take everything uploaded to "Raw — This Week", transcribe anything longer than two minutes, pull the best 30-second highlight out of each interview, and give me a CSV of what it found. Post a one-line summary to my Slack webhook.
Nothing is generated yet. The first thing that comes back is a plan.
Read the plan before you read the code
This is the part we'd argue hardest for. The plan is a structured artifact — steps, inputs, outputs, the CLI commands it intends to use, the account permissions it will need — plus two sections that matter more than the rest:
Assumptions. What it decided when your description didn't say. "'Longer than two minutes' is measured on the source duration, not the transcript." "'Best highlight' means the highest-scoring segment from media highlight, one per video."
Open questions. What it genuinely could not infer. "Should already-transcribed videos be skipped, or re-transcribed?"
Each assumption has a fix link and each open question an answer link. Both quote the item into a note, and re-planning carries that note as a revision rather than a fresh roll of the dice — so correcting one detail doesn't re-decide the nine you were happy with. That distinction sounds small and isn't: a bare "regenerate" button on a mostly-right plan is worse than useless.
Reviewing a plan takes thirty seconds. Reviewing two hundred lines of generated Python takes considerably longer, and by then you're anchored on what it wrote rather than on what you wanted.
Then it writes the program
Approve the plan and you get code. Real, boring, readable code:
def transcribe_videos(album: str, out_dir: Path) -> list[dict]:
"""Transcribe every video in `album`, one .srt per item."""
# `media list` returns a JSON array at the top level, not an object.
items = run(["5am", "media", "list", "--album", album, "--type", "video"])
results = []
for item in items:
srt = out_dir / f"{item['id']}.srt"
if srt.exists(): # re-runs must not redo work
continue
run([
"5am", "media", "transcribe", item["id"],
"--format", "srt", "--output", str(srt),
])
results.append({"id": item["id"], "file_name": item.get("fileName"), "srt": srt})
return results
It shells out to 5am through one run() helper that always passes an argument list, checks the exit code and parses stdout. That's the whole trick, and it's why this works: the CLI already does uploads, transcription, clipping, semantic search, album management and generation. The generated program is glue, and glue is the thing language models are genuinely good at writing.
It also means you can read it. If you have ever typed 5am media list --album "Raw" you can audit this program, and if you haven't, the plan told you what it was going to do in English first.
Edit it like code, not like a prompt
The editor is a real editor. Click the gutter next to any line to leave a note — "skip anything already transcribed" — stack up as many as you like, add a general instruction, and hit Apply changes. One round in, a revised file out, notes cleared. No chat transcript, no assistant turn, no scrolling back through six messages to find the version that worked.
Every version is kept. So is the note that replaced it.
Two gates, asking different questions
Generated code that drives a CLI against your real media library deserves more than a vibe check, so there are two of them, and they are deliberately not the same check twice.
The validator asks: is this allowed? It's a static pass, no model involved. An import allowlist. Patterns that block credential access and unbounded deletion. And — the one that fires most often — every 5am command in the program is checked against a dump of what the CLI actually has. 5am media frobnicate doesn't reach you. Neither does a plausible-looking --parallel flag on a command that has no such thing.
The review asks: is this a good idea? A second model, on a higher tier than the one that wrote the code, prompted adversarially and told to assume the program is wrong. It reads for the things a regex structurally cannot see:
- deleting the source file before confirming the upload landed;
- looping a media list with no pagination, so a large album silently processes the first page and reports success;
- re-transcoding everything on every run because nothing checks what already exists;
- a retry loop with no ceiling.
Critical findings block a cloud run. You can override — an LLM reviewer will sometimes be wrong, and a gate with no door is a gate people learn to route around — but the override is recorded on the run, so "was this flagged?" stays answerable months later.
And when the review finds something, Fix these turns its findings straight into line notes and runs them back through the editor. Read it, fix it, re-review. That loop is the product.
Run it: yours, or ours
Download it. GET /workflows/:id/bundle gives you workflow.py, a requirements.txt with exactly the packages it imports, and a README. pip install -r requirements.txt, then python3 workflow.py. It needs the 5am CLI on PATH and nothing else. Put it in cron. Put it in your CI. Put it in a repo. It is a normal Python file and we have no further opinions about it.
Downloading is ungated — it needs no plan at all, and a lapsed subscription doesn't take your program away with it. We think that's the only defensible default: you asked for the file, the file is yours.
Or let us run it. On Ultra, press Run. The program executes in an isolated container with a live log pane — the actual stdout of the actual program, streaming, not a progress bar. Files it saves with 5am workflow artifact put report.csv --label "Weekly rollup" land in an artifact hub you can read in the browser, and the run's full log is archived there when it finishes, including when it finishes badly.
If your plan declares inputs, they become a form. A workflow with an --album input is a workflow you can point at a different album on Tuesday without editing anything.
Credits, plainly
Cloud runs are metered in run-minutes. One credit is one minute on the standard machine; small is ×0.5, large is ×2.5. Minutes rather than dollars, because "how many runs do I get?" should have an answer that doesn't move when a cloud provider changes a price.
Before a run starts we reserve its worst case — the full timeout at that machine's rate — and show you the number. When it finishes we release the hold and charge the actual duration. A runaway program therefore costs exactly the ceiling you already agreed to, which is the reason we can offer that review override at all.
Ultra includes 1,000 credits a month — about sixteen hours of standard compute, or a half-hour run every day. Top-ups are 500 for $19, 2,000 for $59, or 10,000 for $249, and they live in Settings → Billing next to a meter showing your balance, what's reserved by runs in flight, and the month's usage.
What a workflow can reach — and what it can't
Worth being precise, because this is your account.
A cloud run gets its own credential: a token minted for that run alone, scoped to the permissions the plan declared, never admin, and revoked when the run ends. It is not your personal token and it does not outlive the job.
The container holds nothing else. No storage credentials — artifact uploads go through short-lived signed URLs whose paths we build server-side. No other user's anything. No access to our infrastructure. Its service account has zero permissions, deliberately.
Network access is open, and that's a choice rather than an oversight: "post to my Slack webhook" is most of the point. Which means the honest ceiling is this — a workflow can do to your library what you could do yourself from the CLI, and it can talk to the internet. That's the correct ceiling for your own automation, it's why the plan shows you the permissions before you approve it, and it's why the review reads for exfiltration.
One consequence worth stating out loud: this model holds because the program is yours. A shared workflow — one person running another person's code — is a different problem, and we'd rather rethink it properly than quietly extend this.
From a Playground session
Playground is where you work out what to do. Workflows is where it becomes repeatable.
When a Playground session reaches a synthesis, its header offers Create Workflow. The originating question and the conclusion travel to /workflows as a prefilled description — along with the session's artifacts, so the planner can see the contact sheet or the spreadsheet the conversation actually produced.
It prefills; it never auto-creates. A session often concludes a strategy rather than a pipeline, and deciding which part of it is automatable is a judgment call that belongs to you.
Getting started
- Open
/workflowsand describe something you do repeatedly. Boring and specific beats clever and vague. - Read the plan. Use the fix and answer links — that's what they're for.
- Generate, then actually read the code. Annotate anything that looks wrong.
- Review it. Fix what it finds.
- Download the bundle and run it locally, or press Run on Ultra.
Planning and generating need any paid plan and your own Gemini API key. Cloud execution needs Ultra.
The pitch, in one line: you shouldn't have to choose between a rigid no-code builder and learning to write API clients. You should be able to describe the job, read what was planned, keep the program, and run it wherever you want.
Managed Workflows is available now. Questions, or a pipeline you can't get to plan properly? We'd like to hear about it — the plans that fail are the ones that make the next version better.



