Introducing the Deft SEO Agent
A technical tour of the Deft SEO Agent — company context, research-first planning, section drafting through Deft, mechanical assembly, and fact-check flags.
At a glance
- The orchestrating model never writes body prose—every paragraph comes from Deft, so the articles read human without a scrubbing pass and without consulting a detector.
- It researches your company once and reuses that context, then plans, drafts, assembles, and fact-checks each article as separate stages you can watch.
- Assembly and corrections are mechanical and constrained, so a factual fix cannot quietly rewrite a paragraph into something new.
The Deft SEO Agent is an application that writes long-form SEO articles for one specific company. You point it at your website once, hand it an article concept, and it researches the topic, plans the piece, drafts it, assembles it, and fact-checks it, streaming the whole agent trace on the page while it works. It will live at deftwriting.com/seo-agent, which is not open yet.
What it is good at is narrow and worth stating plainly: the articles do not read like AI slop. They read like a person wrote them — more specific, more varied, more enjoyable to get through — and prose that reads human is less likely to be flagged as machine-written. Nothing in the pipeline consults an AI detector. The register comes from where the sentences are generated, not from a scrubbing pass bolted on at the end.
The Rule the Design Serves
The orchestrating model never writes a sentence of the article. Every paragraph of body prose comes from Deft, a model tuned on real human web text so its output distribution matches human writing instead of model-average prose. The orchestrator's own words reach the page in exactly three places, all of them HTML metadata rather than body copy: the title tag, the URL slug, and the meta description.
The system prompt states the reason directly — any text the orchestrating model writes or edits itself "carries machine-structured fingerprints." So it is forbidden from rewriting, paraphrasing, or polishing a draft, and forbidden from asking Deft to rewrite existing text. When a section comes back wrong, the fix is to change that section's outline and regenerate it. The only manual edits allowed anywhere are mechanical: headings, verbatim quote injection, and exact-string replacement.
If what you have is already a generic AI draft, that is a job for Rewrite mode in the writing product at deftwriting.com. The agent only generates.
Company Context
The most distinctive part of the application is what happens before you ask for any article. A separate research agent takes your website and works through the homepage, product and pricing pages, the category's buying queries, and 3–6 direct competitors — including their sitemaps or blog indexes, to see which topics they own and which they leave open. Its instructions forbid padding the profile with plausible-sounding guesses. It saves one file, server/data/company-context.json: company name, summary, products, audience, positioning, competitors, content angles worth owning, and the key pages worth linking to.
Every later article run loads that JSON straight into the writer's system prompt, which changes what gets written. The keyword and angle are chosen for searchers the company can convert rather than a generic reader. The product appears where it belongs — typically one section plus a link to a relevant key page. Competitor gaps become the article's reason to exist.
The Pipeline
| Stage | What happens | What comes out |
|---|---|---|
| Context (once) | Research agent studies your site, market, and competitors | company-context.json |
| Research | Web search and page fetch until every planned section has 3+ concrete facts | Typed fact corpus with source URLs |
| Plan | Title, slug, meta description, 6–10 H2 sections with facts written inline, keyword plan | One complete write_article brief |
| Draft | Server drafts every section through Deft concurrently, one draft per section, one retry each | Section drafts |
| Assemble | Headings, verbatim quote injection, near-duplicate removal, exact keyword counts | Assembled Markdown |
| Editorial pass | Deletion-only reviewer strips filler and quirks | Trimmed Markdown |
| Fact check | Every specific compared against the fact corpus | Flags attached to the document |
The plan is where the operator-visible craft lives. Sections target 350–600 words, keyword density is aimed at 0.5–1.5% with an exact-phrase directive on every body section rather than bookend placement, an FAQ section handles long-tail questions, and the intro and conclusion are designed last because they are the slots most prone to fabrication. Section shapes that reliably draft badly — price round-up lists, "Step 1 / Step 2" enumerations, abstract sections with no concrete anchor — get reshaped in the outline rather than resampled.
The Tools
The article agent has four tools. Research is not among them: web search and page fetch are OpenRouter server-side tools injected into the request payload, not local functions.
// server/src/agent/agent.ts
tools: [
createWriteArticleTool(session), // one brief in, one finished document out
createReviseSectionTool(session), // regenerate one section, rebuild the doc
createFactCheckTool(session), // re-run the flag-only check
createApplyCorrectionsTool(session), // exact-string fixes and citation links
]
write_article is called exactly once and everything after it is server code: drafting, assembly, the editorial pass, delivery, and the automatic fact check. The model does not re-thread section IDs or prose between stages, which removes most of the failure surface. A per-run circuit breaker ends the run after two consecutive failed calls to the same tool, or 25 tool calls total, so a confused agent cannot spend credits indefinitely.
Assembly and the Editorial Pass
Assembly is code, not another writing pass: headings, verbatim quote injection at an exact anchor, near-duplicate sentence removal, keyword counts. Then one reviewer pass runs, mechanically constrained rather than trusted. It proposes edits as find/replace pairs; each find must occur exactly once in the document, a deletion must be a complete sentence or paragraph, and a replacement may be at most two plain words containing no punctuation. Anything else is rejected and reported. There is a hard cap of 60 edits, and if the reviewer is unreachable after three attempts the pass is skipped and the document assembles without it.
So the reviewer can remove filler, memo voice, and distracting quirks, but cannot write. Deft prose is never rewritten by another model — which is exactly how a carefully generated article turns back into uniform synthetic voice.
Fact-check Flags
Deft invents specifics when it is starved of them. The system prompt says so, and the pipeline treats that as a standing risk rather than a solved problem. Each brief carries a typed research corpus — numbers, dates, names, quotes, citations, claims, each with a source URL — and the assembled document is checked against it automatically. The checker is flag-only and told never to propose a rewrite. Every flag must quote a span copied verbatim from the document so the interface can highlight it; spans that do not literally appear get dropped. Flags come back as supported, unsupported, or contradicted, and sit beside the article for human review.
Corrections are exact-string replacements with an enforced expected match count, so a factual fix cannot quietly rewrite a paragraph into something new. If the brief supplied no facts, the check is skipped rather than run against nothing and blanketing a clean article in false flags. If it fails outright, the article is still delivered, explicitly marked unverified.
What You See, and What Is Kept
The client is one page: setup, the company-context card, a concept box that takes an optional PDF reference (up to 15 MB, used for that run only and never written to disk), the live agent trace, and the finished article with a SERP preview, keyword counts, and the flag list. Copy or download the Markdown.
Almost nothing is stored. company-context.json is the only persisted artifact; runs, traces, and finished articles live in server memory and are gone on restart, so take the article when it is done. A dropped browser connection does not kill a run — the server finishes, and the browser keeps the run ID and last document snapshot in localStorage and reconnects through GET /api/runs/:id. Only the Stop button aborts.
The Stack
- Server: Hono on Node, streaming SSE.
- Agents: two of them — the article writer and the company researcher — built on the Pi SDK, running Gemini 3.5 Flash through OpenRouter.
- Research: OpenRouter's server-side web search on the Parallel engine, plus direct page fetch.
- Review: Claude Sonnet 5 for the editorial pass and the fact check.
- Prose: Deft's
/v1/generate. - Client: Vite and React, monochrome, one page.
Two keys run the whole thing, Deft and OpenRouter. Entered in the UI they stay in server memory and the browser's localStorage; their values are never written to disk or returned to the browser. DEFT_MOCK=1 swaps in canned prose so interface work costs nothing. The intent is to release the source, but there is no public repository yet — treat that as a plan rather than a link.
What It Is Not
It is not a "write 100 posts" button, and it does not remove editorial judgment. It gives that judgment somewhere useful to land: an article whose every sentence came from a human-register generator, whose specifics are checked against a named source list, and whose unresolved claims are flagged rather than smoothed over.