I don't submit my Medium articles anymore — an agent does it (recipe inside, partially redacted)
One command publishes my markdown to Medium: ##auto web, a do/while loop with a hard token budget, and a judge that won't accept a draft.
Publishing an article to Medium is fifteen minutes of the least interesting work in writing: open the editor, retype the title, paste the body, fix the headings the paste broke, rebuild the code blocks, add tags, click publish, copy the URL.
I don't do any of that anymore. I run one command in my terminal:
##auto web run halilagin-medium ./marketing/articles/my-article.md
and go make coffee. A browser agent opens my own Chrome profile, parses the markdown, types the story into Medium's editor, verifies the rendered result against the source, publishes, and writes the live URL into a results file. If it runs out of budget mid-way, it stops gracefully — Medium autosaves, so it reports the draft URL and what's left. A second pass finishes the draft instead of creating a duplicate.
This post shows the actual recipe file that does it — .rysh/automations/webs/halilagin-medium.md — with most of the body redacted. What I'm keeping public is the part I think matters: the YAML frontmatter and the loop engineering. That's where the difference between "an agent that usually works" and "an agent I trust with my account" lives.
One markdown file is the whole automation
In rysh, ##auto web runs a recipe: a single markdown file with YAML frontmatter (the contract: profile, entry URL, args, loop budgets) and a prose body (the instructions the agent follows in the browser). No framework, no pipeline YAML sprawl, no orchestration service. The file lives in the repo, which means the automation is reviewable and versioned like any other code.
One-time setup — and this is a hard rule, not a convenience:
##web headless login halilagin-medium https://medium.com/
opens a persistent browser profile where I log in to Medium by hand, once. The agent never sees credentials, never types a password, and — as you'll see in the recipe — is explicitly ordered to stop dead at any sign-in wall or captcha and report, not "solve" it.
The recipe, partially redacted
Here is the file. The frontmatter is verbatim and complete. The body — a couple hundred lines of hard-won Medium editor mechanics — is redacted down to its skeleton, with two safety rules left intact on purpose.
---
description: Publish a local markdown article to medium.com on halilagin's
account. Takes the article file path as the arg, strips YAML frontmatter and
maps it to Medium's native fields, writes the body into the Medium story
editor using its actual editing quirks, publishes, and saves the published
URL. Requires a persistent, pre-authenticated browser profile - log in once
by hand via ##web headless login halilagin-medium https://medium.com/.
web_profile: halilagin-medium # persistent, pre-authenticated browser profile
url: https://medium.com/new-story
args: [article_path] # run as: ##auto web run halilagin-medium /path/to/article.md
output_dir: halilagin-medium/results
loop:
do: # one publishing session
interval: 50
max_iterations: 150
max_duration: 7m
auto_continue: true
model: claude-sonnet-5 # mechanical typing/verification legs: Sonnet seat
# (Opus here made every round bill at flagship rates
# — ~$4/article observed 2026-07-19; the until-judge
# keeps the Opus default for the fulfillment decision)
budget:
size: 2b # 2 "books" = 400k tokens (a clean publish uses ~0.6b)
watch:
takeover_when: 90 # at 90% consumed, switch to the wrap-up leg
takeover_prompt: >
The publishing budget is used up - stop now. Medium autosaves as you
type, so the story should exist as a DRAFT: report the draft URL,
what remains to be done (formatting, tags, the publish click), and
save that status to the results file. Do NOT publish a half-written
article.
while: # the OUTER loop - retry sessions until published
enabled: true
max_iterations: 5
max_duration: 40m
budget: 10b # TOTAL across passes: 10b / 5 passes = 2b each
prompts:
until: >
The results file for this run contains a PUBLISHED story URL for the
article at {{args}} - the story is live on the profile, not a draft.
iterate_with: >
Continue the interrupted publish of {{args}}. Check the profile's
stories and drafts FIRST: if the draft already exists, open it, finish
the remaining formatting/verification, and publish THAT draft - never
create a duplicate story. If it was already published, just save the
published URL to the results file and stop.
---
You are publishing a local markdown article to Medium as halilagin.
The article file path is: {{args}}
If {{args}} is empty, ask me for the article path and stop - do not guess.
## Steps
1. Read the article from the local file at {{args}}…
[REDACTED — frontmatter→Medium field mapping, the block model
(heading/paragraph/bullet/quote/code) built BEFORE any typing]
2. Check login. …If instead you see a sign-in page, a captcha, or an
unexpected wall: STOP immediately and report it - never attempt to
log in or solve a captcha yourself.
3. Write the story - Medium editor mechanics
[REDACTED — ~150 lines of lab-verified editor quirks: the title
keystroke rule, the paste-position rule that prevents title merge,
heading shortcuts, code-block cursor traps, list/quote/link mechanics]
4. Verify before publishing.
[REDACTED — the rendered-story-vs-parsed-blocks diff checklist]
5. Publish. …never touch any social-sharing option in the publish
dialog or afterwards… Publishing the Medium story is the entire job;
sharing anywhere else is out of scope and forbidden.
6. Save the result. [REDACTED — results-file format]
## Cost discipline
[REDACTED — screenshot milestones, the share-modal escape, one-attempt
rules for tags and cosmetic blemishes]
## Rules
[REDACTED — one story per run, no duplicate publishes, touch nothing
else on the account: no follows, claps, comments, or settings]
Why redact? Two honest reasons. The editor mechanics are weeks of trial-and-error against one specific editor — they're the part of the recipe with actual craft in it, and they'd also go stale the day Medium ships a redesign. The loop engineering is the part that transfers to your automations, so that's the part you get in full.
Read the loop like an engineer
The frontmatter is a do/while loop with hard budgets — the same pattern I wrote about in loop engineering and pages, books, and shelves. A "book" is 200k tokens — a budget you can say out loud.
The do is one attempt, and it's allowed to fail. One publishing session gets 2 books, 150 iterations, 7 minutes — whichever runs out first. At 90% budget the takeover_when leg fires, and look at what the takeover prompt does: it doesn't try harder. It converts the failure into a resumable artifact — "report the draft URL, list what remains, do NOT publish a half-written article." Graceful degradation is written into the prompt, not hoped for.
The while is the guarantee. Up to 5 sessions, 40 minutes, 10 books total. The until judge is deliberately picky: not "did you try", not "does a draft exist" — a PUBLISHED story URL, live on the profile, not a draft. And iterate_with re-grounds every retry in reality: check the drafts first, finish the existing one, never create a duplicate. That single line is the difference between a retry loop and a duplicate-story generator. (Honesty note: the judge is an LLM signal, not a proof — which is exactly why it's pointed at a verifiable artifact, a URL in a results file, rather than at the agent's self-assessment.)
The model: line is a receipt, not a flex. The comment is from a real run: with the flagship model driving every mechanical typing round, one article cost ~$4 to publish. Moving the do-loop to a Sonnet seat — while keeping the stronger model as the until-judge for the fulfillment decision — is the boring, correct fix. A clean publish now uses ~0.6 of its 2-book budget. Budget your loops like you budget anything else: cheap labor for typing, expensive judgment for deciding.
What the agent is not allowed to do
The two lines I refused to redact are the ethics of the thing. The agent never logs in and never solves captchas — a wall means stop and report. And it never touches sharing: no auto-posts to X or LinkedIn, no claps, no follows, no comments. It automates the typing of my own article into my own account, and nothing else. If you build recipes like this, build that boundary in — engagement is a human's job.
Everything here runs on Claude with my own Anthropic key, on my machine, against my own Chrome profile. Rysh is self-hostable; the recipe is a file in my repo.
Rysh is early, and we're building it with design partners — hands-on access, a direct line to the founders, your workflow shaping the roadmap. If you want your own publish-while-you-make-coffee loop: become a design partner →
More in this series: Loop engineering: do/while for AI agents · ##auto web: autonomous browser recipes in one markdown file · Grounded resumption