Skip to content

Infotrend-Inc/Blog-Agent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Blog-Agent

A multi-agent blog-writing pipeline built on OpenCode. You give it a one-line brief, and a team of four specialist agents researches, writes, fact-checks, and proofreads it, then hands you a publish-ready draft.

It powers Dana's Blog, a blog for small-business owners. The whole point is to produce on-brand, fully-sourced posts without a human babysitting each step, while keeping a human in control of the one thing that matters most: hitting publish.

Contents


1. What it does

Writing a good blog post is really four jobs: find the facts, write the prose, check the facts, and polish the voice. Blog-Agent gives each job to a dedicated agent and wires them into a fixed pipeline:

     Your brief
         │
         ▼
  ┌──────────────┐
  │    editor    │  reads the brief, assigns a slug, runs each step in order
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │  researcher  │ → research/<slug>.md     (sourced notes)
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │  copywriter  │ → drafts/<slug>.md       (the draft)
  └──────┬───────┘
         ▼
  ┌──────────────┐
  │  proofreader │ → for_review/<slug>.md   (proofed and fact-checked)
  └──────┬───────┘
         ▼
  Dana reviews and publishes  (human-in-the-loop)

The agents stop at for_review/<slug>.md. Nothing is published automatically. A human reviews the draft and then decides whether to publish it or not. That final call is always a human-in-the-loop step.

2. The agents

Four agents, each with one job and only the access that job needs.

The editor is the one you talk to. It runs at a low temperature (controls the creativity) because it is making decisions, not writing prose. It reads your brief, settles on a slug (common name), and orchestrates the process (researcher first, then copywriter, then proofreader), checking each result before the end of each step. It has no web access and writes no files at all. Coordinating the others is its entire job.

The researcher is the only agent allowed online. It can both search the web and fetch pages. It also runs at a low temperature, so it stays close to its sources. It writes its findings to research/<slug>.md and nowhere else: one claim per line, each backed by a real source URL. If it cannot find a source for something, the claim does not make the cut.

The copywriter turns those notes into an actual post. It runs at higher temperature, so the prose reads like a person wrote it. It has no web access and works only from the researcher's notes, so it cannot add a "fact" that nobody checked. When it wants to say something the notes do not cover, it leaves a <!-- NEEDS SOURCE: ... --> marker instead of inventing. It writes the draft to drafts/<slug>.md only.

The proofreader is the last gate. It runs at the lowest temperature, because its job is to follow the rules (Author's voice) strictly. It has no web access. It cleans up grammar and voice, then checks every claim in the draft against the notes. Anything unsupported gets flagged with an <!-- UNSUPPORTED --> marker rather than being quietly fixed. The clean version lands in for_review/<slug>.md, ready for human review.

The full instructions for each agent live in .opencode/agents/.

Tip

Not familiar with multi-agent systems? The OpenCode agent documentation is a good starting point before diving into the agent definitions under .opencode/agents/.

3. Design principles

This repo acts as an example of a reliable agent systems.

  • Least privilege, enforced. opencode.json denies everything project-wide (edit, bash, webfetch, websearch, external_directory), and each agent gets granted only what it needs. Only the researcher can access the web. The copywriter cannot touch the web, the proofreader cannot rewrite the draft, and the editor cannot write any file at all. A misstep in one agent cannot corrupt another's work.
  • One slug per run means traceability. The editor derives a single <slug> from the brief (for example, "How to winterize your café" becomes winterize-your-cafe) and passes it to every specialist. All three artifacts share that slug, so each run is self-contained and runs should not overwrite each other (slug collisions are possible when asking the exact same topic).
  • Facts stay separate from prose. The researcher produces sourced facts, the copywriter may use only those facts (and flags gaps with <!-- NEEDS SOURCE: ... --> rather than inventing), and the proofreader verifies that every claim maps back to a note, flagging unsupported ones with <!-- UNSUPPORTED -->. No agent gets to make things up.
  • A human always publishes. The pipeline ends at for_review/<slug>.md. The agents have no tools to publish and are instructed never to try.
  • Prompt-injection defense. The researcher treats fetched web pages as data to summarize, never as instructions to follow.

4. House style

Every agent follows the house style defined in AGENTS.md, the single source of truth for all agents. The essentials:

  • Voice: short sentences, active voice, second person ("you"), one idea per paragraph, and concrete examples over abstractions.
  • Structure: 500-700 words, with a title, a one-sentence summary, and 3-5 sections.
  • Sourcing: every factual claim must map to a source in research/<slug>.md. No statistics, prices, dates, or quotes that are not in the notes.
  • Spelling: US English throughout.

For a broader introduction to content style principles, the Google Developer Documentation Style Guide and Mailchimp Content Style Guide are useful references.

5. Project structure

Blog-Agent/
├── AGENTS.md                 # House style, pipeline spec, and definition of done (shared by all agents)
├── opencode.json             # Project config: deny-by-default permissions and the agent roster
├── .opencode/
│   ├── agents/
│   │   ├── editor.md         # Primary orchestrator
│   │   ├── researcher.md     # Sourced-notes specialist
│   │   ├── copywriter.md     # Draft writer
│   │   └── proofreader.md    # Proof and fact-check
│   └── package.json          # @opencode-ai/plugin (dev-only helper, unused here)
├── research/                 # researcher output     (gitignored)
├── drafts/                   # copywriter output     (gitignored)
└── for_review/               # proofreader output    (gitignored)  ← Dana reviews this

The output folders (research/, drafts/, for_review/) each contain a .gitkeep file so Git tracks the empty directories and the folder structure exists after a fresh clone. A .gitignore entry prevents the actual artifacts from being committed, so local runs stay off the remote repo by default.

If you fork this repo and want to keep an audit trail of every run, remove or edit the relevant .gitignore entries to allow those files to be committed.

6. Prerequisites

  • npm (required to install OpenCode; installing Node.js will bring npm along).
  • OpenCode installed (the opencode CLI).
  • An OpenRouter account with an API key and some credits. Every agent's model is referenced as openrouter/..., so the pipeline routes through OpenRouter.

Note

OpenRouter provides a unified API gateway to a wide range of hosted language models. Learn more about how OpenRouter routing works.

7. Setup

7.1. Install OpenCode

macOS / Linux — use Homebrew (recommended) or the install script:

# Homebrew (recommended for macOS/Linux)
brew install opencode

# or use the install script
curl -fsSL https://opencode.ai/install | bash

Windows — the curl script does not run on Windows. Use npm or winget instead:

# npm (recommended if Node.js is already installed)
npm install -g opencode-ai

# winget
winget install opencode

All platforms — npm works everywhere if you already have Node.js:

npm install -g opencode-ai

Homebrew and other methods are listed on the OpenCode download page.

Confirm it worked:

opencode --version

7.2. Get the project

Clone the repository and move into it:

git clone https://github.com/Infotrend-Inc/Blog-Agent.git
cd Blog-Agent

7.3. Get an OpenRouter API key

We chose OpenRouter because one API key gives us access to a wide range of models from many providers. We can swap models without changing our credentials.

Note

OpenRouter is not required. OpenCode supports 75+ providers (including Anthropic, OpenAI, Google, Amazon Bedrock, Azure, Groq, and local models via Ollama or LM Studio), so we can use an alternative if preferred:

  • Sign in with opencode auth login (see section 7.4).
  • Run opencode models to obtain the list of available models
  • change the model field in the agent files under .opencode/agents/.

See the OpenCode providers docs for the full list and setup details.

  1. Sign up at openrouter.ai.
  2. Create an API key (it looks like sk-xxxxxx...).
  3. Add credits to your account. A typical run costs under $0.20 with the default models.

7.4. Give OpenCode your key

You have two options. Pick one.

Option A: an environment variable. OpenCode reads OPENROUTER_API_KEY automatically.

macOS / Linux:

export OPENROUTER_API_KEY="<your-openrouter-key>"

Add that line to your ~/.bashrc or ~/.zshrc so it persists across sessions.

To set it for a single run instead, prefix the command:

OPENROUTER_API_KEY="<your-openrouter-key>" opencode

Windows (PowerShell):

$env:OPENROUTER_API_KEY = "<your-openrouter-key>"

To persist it across sessions on Windows, use setx or add it via "System Properties → Environment Variables":

setx OPENROUTER_API_KEY "<your-openrouter-key>"

Option B: interactive login. Store the key on disk once:

opencode auth login

Choose OpenRouter and paste your key. OpenCode saves it to:

  • Linux: ~/.local/share/opencode/auth.json
  • macOS: ~/Library/Application Support/opencode/auth.json
  • Windows: %APPDATA%\opencode\auth.json

You can list configured providers any time with opencode auth list.

When you run opencode auth login, it shows a searchable list of providers (not just OpenRouter). You can use this to discover and switch to other supported providers.

Warning

If you see an "Incorrect API key" error after setup, your key may have been stored under the wrong provider. Re-run opencode auth login, make sure you select OpenRouter, and paste the key again.

To see which models are available from your configured providers, run:

opencode models

7.5. Run it

From the project root (the folder where README.md is located):

opencode

OpenCode reads opencode.json and loads the four agents. If you see a model or authentication error here, your OpenRouter key or credits are not set up properly; revisit sections 7.3 and 7.4.

8. Usage

Start OpenCode from the project root (the folder where README.md is located):

opencode

Before you type anything, make sure the active agent is the editor, the primary agent that drives the whole pipeline. Press Tab (or Shift+Tab) to cycle through the primary agents until the status line shows editor. Then give it a brief:

Write a post on how to protect a small business from phishing scams.

From there the editor runs the pipeline on its own:

  1. derives the slug protect-a-small-business-from-phishing-scams,
  2. calls the researcher, producing research/protect-a-small-business-from-phishing-scams.md,
  3. calls the copywriter, producing drafts/protect-a-small-business-from-phishing-scams.md,
  4. calls the proofreader, producing for_review/protect-a-small-business-from-phishing-scams.md,
  5. reads the proofed file, checks it against the definition of done, and shows you the path to for_review/<slug>.md.

If the proofreader blocks the draft (an unsupported claim, a placeholder source, a missed word count), the editor sends it back to the copywriter one time and reruns the check, then stops.

9. Practical example

Brief: "How to protect a small business from phishing scams."

Slug the editor assigns: protect-a-small-business-from-phishing-scams.

Stage 1, research/protect-a-small-business-from-phishing-scams.md (researcher). Sourced notes, one claim per line, each followed by a real URL. For this topic they would come from agencies like the FTC and CISA:

The FTC says phishing emails often create a sense of urgency to trick you into acting fast.
https://consumer.ftc.gov/articles/how-recognize-and-avoid-phishing-scams

CISA recommends turning on multi-factor authentication to limit the damage of stolen passwords.
https://www.cisa.gov/secure-our-world

Sources:
https://consumer.ftc.gov/articles/how-recognize-and-avoid-phishing-scams
https://www.cisa.gov/secure-our-world

Stage 2, drafts/protect-a-small-business-from-phishing-scams.md (copywriter). The draft, written from those notes only, in Dana's voice: a title, a one-sentence summary, and 3-5 short sections, with every claim tracing back to a line in the notes.

Stage 3, for_review/protect-a-small-business-from-phishing-scams.md (proofreader). The same article, proofed for grammar and voice and fact-checked against the notes. This is the file Dana opens to review and publish.

Practical Example Run

10. Output and definition of done

A run is "done" when, per AGENTS.md, there is:

  • a draft in drafts/<slug>.md that follows the house voice, hits 500-700 words, and has a title, a one-sentence summary, and 3-5 sections, with every claim mapping to a note, and
  • a proofed, fact-checked version in for_review/<slug>.md.

for_review/<slug>.md is the artifact Dana reviews. The agents stop there, and Dana reviews the draft and decides whether to publish it.

11. Customization

  • Change the voice or rules: edit AGENTS.md. It is the single source of truth for voice, the hard rules (sourcing, word count, structure), file naming, and the definition of done. Every agent reads it.
  • Swap models or tune behavior: edit the frontmatter in any .opencode/agents/ file (see OpenCode agent docs for the full list of options.)
    • model: which LLM to use (e.g. openrouter/openai/gpt-5.4-mini)
    • temperature: controls creativity; lower is more deterministic, higher is more varied
    • steps: maximum number of tool calls the agent can make in one run
    • permission: which tools and file paths the agent can access
  • Tighten or loosen permissions: adjust the per-agent permission blocks in .opencode/agents/ rather than loosening the project defaults in opencode.json; keep that file as the deny-by-default baseline. For example, set the researcher's webfetch to ask to pause before pulling untrusted pages (slower, but gives you a confirmation step before each fetch). Read more about OpenCode permission controls.

12. Notes and limitations

  • Output folders (research/, drafts/, for_review/) are gitignored, so artifacts stay local and are not committed.
  • Publishing is manual by design. The agents have no publishing tools and are instructed never to attempt it.
  • All models route through OpenRouter (other providers can be used)

About

Demo set of orchestrator-worker Agents to write simple blog posts

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors