Author(s): yoiken
Originally published on Towards AI.
Build a zero-cost web automation pipeline with OpenRouter, OpenClaw, and MediaUse
I’ve become less interested in whether a cheaper model can “browse the web” and more interested in whether it can run a boring workflow correctly every morning.
That’s a different problem.
Most low-cost or free LLMs fail at web automation because the model has to do too much at once. It has to understand the goal, inspect the page, decide where to click, recover from layout changes, parse the result and then write something useful. One weak link ruins the whole race.
The solution is simple: don’t ask the free model to operate the browser.
Use the free model as a dispatcher. Let MediaUse take over the browser’s work through site plugins. The model calls semantic commands such as “Get Hacker News Top Stories” or “Read this Reddit thread.” MediaUse turns those commands into static browser actions and returns structured JSON.
In this article, I will create a daily pipeline that:
- Uses OpenClaw for free with OpenRouter
openrouter/owl-alphaModel as orchestrator. - MediaUse uses hacker news skills to find today’s tech stories.
- MediaUse uses Reddit skills to collect user responses.
- MediaUse uses ChatGPT skills to convert research into Medium drafts.
- Saves the article draft locally.
- Runs daily around 10:00 am.
The result is a low-cost agent that does not rely on the frontier model for every step. Free model plans and routes. MediaUse operates the web. chatgpt is optional and is only used at the end because I want the final write to be nice.
If you want the strict “zero API spend” version, skip the chatgpt step and ask owl-alpha To write drafts from collected JSON. If you already have access to ChatGPT through the web UI, the MediaUse ChatGPT skill can use that browser workflow instead of sending a paid API call.
Current Alert: OpenRouter Lists openrouter/owl-alpha Free during its current availability window, with tool support and a large reference window. Availability of a free model is subject to change, so check the model page before relying on it in production.
Why does this work better than “LLM, please browse the web”
A typical browser agent has to reason over pixels and HTML. Not a site plugin.
MediaUse skills package website actions into predictable commands. Hacker News skills have commands like the following:
mediause hackernews get top --limit 20 --json
mediause hackernews read item --id --depth 2 --replies 20 --max-length 2000 --json Reddit skills have commands like the following:
mediause reddit search posts --query "open source AI agent" --subreddit "LocalLLaMA" --sort relevance --time day --limit 10 --json
mediause reddit read item --post-id --sort top --limit 30 --depth 3 --max-length 3000 --json LLM doesn’t need to know where the Reddit search box is. There is no need to scroll through nested comments. It just calls for operation.
That’s the whole trick.
Lower-quality models often struggle when the task is open-ended. They perform much better when the space of action is small, named and structured. MediaUse gives them that little action space.
line pipe
Here is the workflow I use:
10:00 AM
|
v
OpenClaw wakes up the workflow
|
v
OpenRouter owl-alpha chooses the plan
|
v
MediaUse Hacker News skill fetches today's top tech stories
|
v
MediaUse Reddit skill searches for matching user reactions
|
v
Research JSON is normalized into one brief
|
v
MediaUse ChatGPT skill writes a Medium draft
|
v
Draft is saved to ./drafts/YYYY-MM-DD-medium-draft.md
Step 1: Install and configure MediaUse
On Windows, install or update the MediaUse CLI:
powershell -C "iwr https://release.mediause.dev/install.ps1 -UseBasicParsing | iex"
mediause --versionConfigure your MediaUse key:
mediause manage key --json Install site plugins:
mediause plugin add hackernews --json
mediause plugin add reddit --json
mediause plugin add chatgpt --jsonBind accounts:
mediause auth list --json# Hacker News supports guest read workflows.
mediause use account hackernews:guest --policy balanced --json# Reddit usually works best in visible mode.
mediause use account reddit:--policy balanced --show --json # ChatGPT needs your account context if you use it for writing.
mediause use account chatgpt:--policy balanced --json
mediause auth health --json

Step 2: Configure OpenClaw to use OpenRouter Owl Alpha
Create an OpenRouter API key, then set it in your shell:
$env:OPENROUTER_API_KEY = "" Use openrouter/owl-alpha As a model for orchestration agents. The exact OpenClaw configuration size may vary depending on your version, but the important part is the provider, base URL, and model:
provider: openrouter
base_url: https://openrouter.ai/api/v1
model: openrouter/owl-alpha
api_key_env: OPENROUTER_API_KEY
temperature: 0.2You can sanity-check the model directly from OpenRouter’s OpenAI-compliant API:
$body = @{
model = "openrouter/owl-alpha"
messages = @(
@{
role = "user"
content = "Return a JSON plan for collecting today's developer news."
}
)
response_format = @{ type = "json_object" }
} | ConvertTo-Json -Depth 10Invoke-RestMethod `
-Uri "https://openrouter.ai/api/v1/chat/completions" `
-Method Post `
-Headers @{
Authorization = "Bearer $env:OPENROUTER_API_KEY"
"Content-Type" = "application/json"
} `
-Body $body
Step 3: Give the agent a brief prompt
Signal matters. Don’t ask models to be creative with workflow. Tell it to call a small set of commands and produce a strict output.
Use this as a system prompt for the OpenClaw workflow:
You are a daily technical research dispatcher.Your job is to collect material for one Medium article draft.Rules:
- Use MediaUse commands only for website data collection.
- Prefer structured JSON outputs.
- Do not browse manually.
- Do not invent article facts.
- Keep the final research bundle under 12,000 words.
- Stop if a site returns a risk prompt, captcha, or account challenge.Workflow:
1. Get today's top Hacker News stories.
2. Select 3 to 5 stories about projects, developer tools, AI infrastructure, open source, or software engineering.
3. Read each selected HN item with comments.
4. For each selected story, search Reddit for matching discussion.
5. Read the most relevant Reddit thread when available.
6. Build a research bundle with:
- title
- source URL
- why it matters
- HN discussion summary
- Reddit user feedback summary
- notable disagreement
- possible article angle
7. Send the research bundle to ChatGPT through the MediaUse ChatGPT skill to draft a Medium article.
8. Save the draft as Markdown.
This is where a free model becomes useful. It is not being asked to perform delicate web interactions. This is selecting from a menu.
Step 4: Collect Hacker News Stories
Start with the Hacker News guest reference:
mediause use account hackernews:guest --policy balanced --json
mediause hackernews get top --limit 30 --json | Out-File .runhn-top.json -Encoding utf8Then read the selected formula:
mediause hackernews read item --id --limit 50 --depth 3 --replies 30 --max-length 4000 --json |
Out-File .runhn-.json -Encoding utf8 For example, the agent may decide that a new open source developer tool is worth covering because there is a lively argument in the HN thread about whether it solves a real problem or just wraps up existing tooling.
That disagreement is useful. A good article requires friction.
Step 5: Collect Reddit Responses
For each selected story, search Reddit:
mediause use account reddit: --policy balanced --show --json
mediause auth health --json mediause reddit search posts `
--query "" `
--sort relevance `
--time day `
--limit 10 `
--json |
Out-File .runreddit-search-.json -Encoding utf8 Then read the strongest matching formula:
mediause reddit read item `
--post-id `
--sort top `
--limit 50 `
--depth 3 `
--replies 30 `
--max-length 5000 `
--json |
Out-File .runreddit-.json -Encoding utf8 I like Reddit for this move because it gives a different kind of signal than hacker news. HN is often better for technical criticism. Reddit is better suited for user frustrations, adoption stories, jokes, and “I tried it and it broke on my machine” comments.

Step 6: Normalize the Research Bundle
Agents should convert raw JSON files into a compact research file before soliciting drafts.
Here is the shape I use:
{
"date": "2026-06-08",
"article_goal": "Explain one practical developer trend from today's discussions.",
"stories": (
{
"title": "Example project title",
"source": "https://news.ycombinator.com/item?id=00000000",
"project_url": "https://example.com",
"why_it_matters": "Short factual reason this story is worth covering.",
"hn_summary": (
"What HN users liked.",
"What HN users questioned.",
"Any useful technical detail."
),
"reddit_summary": (
"What Reddit users tried.",
"Common complaint or praise.",
"Any adoption signal."
),
"disagreement": "The most interesting tension between the two communities.",
"article_angle": "A specific angle for a Medium article."
}
)
}The important part is not the exact schema. The important thing is that the drafting model receives organized evidence rather than a pile of observations.
Step 7: Ask ChatGPT to write a Medium draft
You can skip this step if you want everything to be handled by the free OpenRouter model. I put it because the orchestration model and the writing model do not have to be the same.
The free model is good enough for sending commands. For the final article, I want strong writing.
Use ChatGPT skills:
mediause use account chatgpt: --policy balanced --json
mediause auth health --json $research = Get-Content .runresearch-bundle.json -Raw
$prompt = @"
Write a Medium article draft from the research bundle below.Style:
- English.
- Technical teaching tone.
- Concrete examples over abstract claims.
- No hype.
- No invented facts.
- Include a clear title.
- Include image placeholders where screenshots or diagrams would help.
- Include code blocks when they explain the workflow better than prose.Research bundle:
$research
"@mediause chatgpt chat ask --prompt $prompt --timeout 120 --new true --json |
Out-File .runchatgpt-draft-response.json -Encoding utf8mediause chatgpt chat read --markdown true --json |
Out-File .drafts$(Get-Date -Format yyyy-MM-dd)-medium-draft.md -Encoding utf8
Step 8: Put It Together Into a Script
Here is a simple PowerShell version. Consider this a starting point, not a complete production script.
$ErrorActionPreference = "Stop"$date = Get-Date -Format "yyyy-MM-dd"
$root = "C:automationdaily-tech-brief"
$runDir = Join-Path $root "run$date"
$draftDir = Join-Path $root "drafts"New-Item -ItemType Directory -Force -Path $runDir | Out-Null
New-Item -ItemType Directory -Force -Path $draftDir | Out-Null# Keep MediaUse current.
powershell -C "iwr https://release.mediause.dev/install.ps1 -UseBasicParsing | iex"# Hacker News collection.
mediause use account hackernews:guest --policy balanced --json
mediause hackernews get top --limit 30 --json |
Out-File (Join-Path $runDir "hn-top.json") -Encoding utf8# Ask the orchestrator to select stories and return item IDs.
# This can be an OpenClaw task using openrouter/owl-alpha.
openclaw run .promptsselect-stories.txt `
--input (Join-Path $runDir "hn-top.json") `
--output (Join-Path $runDir "selected-stories.json")$selected = Get-Content (Join-Path $runDir "selected-stories.json") -Raw | ConvertFrom-Jsonforeach ($story in $selected.stories) {
mediause hackernews read item `
--id $story.item_id `
--limit 50 `
--depth 3 `
--replies 30 `
--max-length 4000 `
--json |
Out-File (Join-Path $runDir "hn-$($story.item_id).json") -Encoding utf8
}# Reddit collection.
mediause use account reddit:--policy balanced --show --json foreach ($story in $selected.stories) {
mediause auth health --json
$slug = ($story.title -replace "(^a-zA-Z0-9)+", "-").Trim("-").ToLower() mediause reddit search posts `
--query $story.title `
--sort relevance `
--time day `
--limit 10 `
--json |
Out-File (Join-Path $runDir "reddit-search-$slug.json") -Encoding utf8
}# Build one research bundle from the collected JSON.
openclaw run .promptsbuild-research-bundle.txt `
--input $runDir `
--output (Join-Path $runDir "research-bundle.json")# Draft with ChatGPT through MediaUse.
mediause use account chatgpt:--policy balanced --json $research = Get-Content (Join-Path $runDir "research-bundle.json") -Raw
mediause auth health --json
$draftPrompt = @"
Write a Medium article draft from this research bundle.Requirements:
- English
- Practical technical teaching style
- Use code blocks where useful
- Add image placeholders where screenshots should be inserted
- Do not invent facts
- Keep the article publishable after a human edit$research
"@mediause chatgpt chat ask --prompt $draftPrompt --timeout 120 --new true --json |
Out-File (Join-Path $runDir "chatgpt-draft-response.json") -Encoding utf8mediause chatgpt chat read --markdown true --json |
Out-File (Join-Path $draftDir "$date-medium-draft.md") -Encoding utf8
The two OpenClaw prompt files can remain small.
select-stories.txt: :
Read the Hacker News top stories JSON.Return JSON only:
{
"stories": (
{
"item_id": "HN item id",
"title": "story title",
"reason": "why this is relevant to developers or technology readers"
}
)
}Select 3 to 5 stories about developer tools, AI infrastructure, open source projects, programming, cybersecurity, or startup engineering.
Do not select generic politics, finance, or culture stories unless they directly affect software builders.
build-research-bundle.txt: :
Read all JSON files in the run folder.Create one research bundle for a Medium article.
Return JSON only.For each story, include:
- title
- original URL if available
- HN source URL
- Reddit source URL if available
- factual summary
- HN discussion summary
- Reddit user feedback summary
- strongest disagreement
- suggested article angleDo not invent facts. If Reddit has no matching discussion, set reddit_summary to () and explain that no strong Reddit signal was found.
Step 9: Schedule it for 10:00 am
Use OpenClaw’s cron scheduler directly. This keeps the entire workflow in the agent layer instead of splitting the orchestration between OpenGL and the operating system.
Create workflow file like daily-medium-draft.openclaw.yaml: :
name: daily-medium-draft
description: Collect HN and Reddit signals, then create a Medium draft through MediaUse.schedule:
cron: "0 10 * * *"
timezone: "America/Vancouver"model:
provider: openrouter
base_url: https://openrouter.ai/api/v1
model: openrouter/owl-alpha
api_key_env: OPENROUTER_API_KEYrun:
command: powershell.exe
args:
- "-ExecutionPolicy"
- "Bypass"
- "-File"
- "C:\automation\daily-tech-brief\daily-medium-draft.ps1"
Then register or run the workflow with OpenClaw:
openclaw cron add .daily-medium-draft.openclaw.yaml
openclaw cron listIf your OpenClaw version uses a different cron command name, keep the same schedule expression and point the task to the same script. The important thing is that OpenClaw owns the timing, model configuration, and workflow entry point.

what does the daily output look like
Every morning, you should get a folder like this:
drafts/
2026-06-08-medium-draft.mdrun/
2026-06-08/
hn-top.json
selected-stories.json
hn-44123456.json
hn-44123591.json
reddit-search-example-project.json
research-bundle.json
chatgpt-draft-response.jsonThe draft is not for self-publishing. I wouldn’t automate that part.
The correct workflow is this: let the system collect, summarize, and draft while you do something else. Then spend 20 minutes editing the piece yourself. Eliminate weak claims. Add your opinion. Check link. Replace image placeholders with screenshots.
This still saves most of the work.
Why does MediaUse matter here?
The interesting thing is not that a free model can call the API. This may have been possible for some time.
Interestingly, MediaUse reduces browser tasks to a static site-specific command set.
This is a big thing for a weak model. It no longer has to solve “How do I use Reddit today?” It just has to decide:
{
"tool": "mediause reddit search posts",
"query": "the project name",
"sort": "relevance",
"time": "day",
"limit": 10
}This is a very simple logical problem.
You can think of mediause skills as the operational layer between LLM intent and dirty websites. The site plugin handles repeatable workflows. LLM handles the routing and synthesis.
For automation, that division is usually better than giving the entire job to an expensive model.
cost and quality
This setup keeps expensive parts small.
The free OpenRouter model handles:
- Selection of stories.
- Select search terms.
- Building a research bundle.
- Routing the workflow.
MediaUsage Handle:
- Hacker News Recovery.
- Reddit search and thread reading.
- ChatGPT browser interaction.
- Structured command output.
chatgpt handle:
If you remove the ChatGPT step, the entire workflow can run on free model estimation and MediaUse site operations. If you keep ChatGPT, you’re only paying for the part where model quality matters most, or you’re using your existing browser account through MediaUse.
This is the practical version of “zero cost”: don’t spend premium model tokens on web mechanics.
The part I won’t automate
I will not automatically publish the results on Medium.
Daily draft is useful. A daily unattended publishing pipeline is how you post a credible summary of something that was inaccurate, out of date, or based on a joke comment.
Have a human editing step. It’s faster than writing from scratch and it protects your reputation.
Automation should give you:
- Candidate Subject.
- Community reactions.
- A structured research brief.
- A publishable first draft.
You still decide what should be published.
final thoughts
The best use of free models is not to replace better models. It’s giving them work they can do reliably.
A low-cost model can be a perfectly good dispatcher when the devices around it are stable. MediaUse makes the web side static. OpenClaw gives you a scheduler and agent loops. ChatGPT, if you choose to use it, handles the write passes.
That combination is enough to see a draft every morning that has sources, user feedback, and a real angle.
Not bad for a workflow where the weakest models never have to click a button.
Published via Towards AI