# How we built a smart AI writing agent for blog articles

> Source: <https://dev.to/larry_agent/how-we-built-a-smart-ai-writing-agent-for-blog-articles-5dma>
> Published: 2026-07-07 17:47:30+00:00

Most "AI writer" products do the same thing: prompt → blob of text → paste. It works for a demo and falls apart in production, because the value isn't the prose; it's the **domain expert's judgment**, and a one-shot generation has nowhere to put it.

We build [Larry](https://larry-agent.com/en), a tool that turns a lawyer's expertise into articles that get cited by Google, ChatGPT and Gemini. Here's the actual shape of our writing agent: three tools, an interview-first loop, and two patterns worth stealing for any "AI for experts" product.

The instinct is: user asks for a change → send the whole article back to the model → get a whole new article. This is bad because every regeneration drifts. The intro you liked changes. The one accurate statistic gets "improved" into a hallucination. You lose the expert's voice on every pass.

The fix is to treat the article like **code**: give the agent an editing tool that makes *surgical* changes to a document that already exists, not a firehose that rewrites it.

`blog_posts`

row; the conversation and every tool call are persisted so the agent is stateful across turns.No agent framework. Just a `while`

loop that calls the model, runs any tool calls, feeds the results back, and repeats until the model stops asking for tools.

That's the entire toolbox. Resist adding more.

``` js
const tools = [
  {
    name: 'read_article',
    description: 'Read the current article (title, content, FAQ, tags, SEO metas) and author info.',
    parameters: {},
  },
  {
    name: 'replace_in_field',
    description: 'Replace text in a specific field of the article.',
    parameters: {
      field: ['title', 'content', 'faq', 'tags', 'excerpt',
              'meta_title', 'meta_description', 'example_validation'],
      old_string: 'Exact text to replace. Empty = replace the whole field.',
      new_string: 'The new value.',
    },
  },
  {
    name: 'web_search',
    description: 'Search the web for current facts. Returns a source URL + snippet.',
    parameters: { query: 'string' },
  },
];
```

`replace_in_field`

is the important one. `old_string`

must match **exactly one occurrence** in the target field, the same contract as the `Edit`

tool in a coding agent. The agent reads the article, finds the sentence to fix, and patches only that sentence. Everything else is byte-for-byte preserved. Voice and facts stop drifting because 95% of the document is never re-touched.

The system prompt enforces a strict sequence, and the golden rule is: **never run a step that needs an answer without stopping for it.**

`replace_in_field`

.Step 2 is where the product lives. Anyone can generate a generic article about a legal topic. The moat is the lawyer's own example: the exception, the mistake clients always make, the thing a Google search gets wrong. So the agent's first job isn't to write; it's to *interview*. Here's the shape of that prompt:

```
You are capturing a lawyer's expertise on a specific topic.
Ask 2–3 precise questions, ONE exchange at a time.
You MUST ask for one concrete, anonymized real case or anecdote
that illustrates the topic. Wait for the answer before proposing a plan.
```

**1. A validation gate the model can't fake.**

Our quality bar requires a real anonymized example in the body. We enforce it with a boolean field, `example_validation`

, that's *also a tool target*. The rule: the agent may only set it to `true`

**after** re-reading the article with `read_article`

and confirming the example is actually present. The model can't self-certify from memory; it has to go look. It's a cheap way to turn a soft "please include an example" into a hard state transition.

**2. External URLs come from search only.**

The single biggest hallucination risk in legal content is invented case law and fake source links. The guardrail is a hard rule: every external URL in the article must come from a real `web_search`

result, never from the model's memory. Research isn't optional polish; it's the only sanctioned source of links. (We also forbid citing specific law firms, for the same trust reason.)

There's also a silent self-critique pass after each edit: the agent re-checks its own output against the quality rules (direct-answer intro, question-form headings, short paragraphs, the example, the call-to-action) and patches the gaps *before* handing back, without narrating any of it to the user. The lawyer sees "done," not a checklist.

The model is a commodity you swap with an env var. The product is everything around it: **capture the expert's judgment through an interview, edit the document with surgical patches instead of regenerating it, and gate quality with tools the model can't bluff past.**

If you want to see the finished version aimed at lawyers, it's at [larry-agent.com](https://larry-agent.com/en). Curious what other expert domains this shape would fit. What would you point it at?
