Content Brief Writer
[Live] ·
agent__content-brief-writer· Claude Sonnet 4.6
Produces a detailed SEO content brief from an approved keyword cluster — the complete document the Blog Writer consumes to write a well-structured, search-optimised post.
Overview
| Function | Transform a keyword cluster into a fully scoped SEO content brief with outline, internal links, and tone guidance |
| Type | Worker — SEO |
| Model | Claude Sonnet 4.6 |
| Queue | agent__content-brief-writer |
| Concurrency | 1 |
| Timeout | 10 min |
| Lock duration | 12 min |
| Tools | None (allowedTools: []) |
| Max turns | 1 |
| Est. cost / task | ~$0.05–0.10 |
| Plan | Free+ |
Triggers
| Trigger type | When | Who initiates |
|---|---|---|
| Activity Planner dispatch | After Keyword Researcher completes and human approves the keyword cluster (dependsOn: keyword-researcher); Strategist enqueues the brief job with the approved cluster as input | Activity Planner |
| Human on-demand | User clicks “Create brief” in DM Portal for a keyword cluster that already exists — e.g. refreshing a brief for an existing page or writing a brief without the full pipeline | Tenant admin / DM reviewer |
| Scheduled / cron | Not applicable — Content Brief Writer is always triggered downstream of Keyword Researcher or by human action; it does not run on a standalone schedule | — |
Input
interface ContentBriefWriterInput {
tenantId: string;
keywordCluster: KeywordCluster; // full output from Keyword Researcher
contentGoal: 'new_blog_post' | 'optimise_existing' | 'landing_page';
targetUrl?: string; // if optimising an existing page
wordCountTarget?: number; // optional override; agent suggests if omitted
campaignId?: string;
}
interface KeywordCluster {
primaryKeyword: KeywordData;
secondaryKeywords: KeywordData[];
lsiTerms: string[];
contentGapOpportunity: string;
serpFeatures: string[];
}
interface KeywordData {
keyword: string;
volume: number;
difficulty: number;
intent: 'informational' | 'commercial' | 'transactional' | 'navigational';
cpc?: number;
}Output
interface ContentBriefWriterOutput {
tenantId: string;
generatedAt: string; // ISO timestamp
contentGoal: string;
title: string; // recommended H1 / article title
metaDescription: string; // 150–160 chars
h1: string; // same as title unless A/B variant provided
outline: OutlineSection[];
targetWordCount: number;
wordCountRationale: string;
primaryKeyword: string;
secondaryKeywords: string[];
searchIntent: string;
competitorUrls: CompetitorInsight[];
featuredSnippetOpportunity: FeaturedSnippetOpportunity | null;
tone: string;
internalLinkTargets: InternalLink[];
existingContentToAvoid: string[]; // titles of published content too similar to this brief
}
interface OutlineSection {
h2: string;
keyPoints: string[];
internalLinkOpportunity: InternalLink | null;
wordCountTarget: number;
}
interface CompetitorInsight {
url: string;
wordCount: number;
mainAngle: string;
gapWeCanFill: string;
}
interface FeaturedSnippetOpportunity {
format: 'paragraph' | 'numbered list' | 'table' | 'definition';
targetSection: string; // which H2 to optimise for the snippet
recommendedLength: number; // chars for paragraph format, or row count for list/table
}
interface InternalLink {
anchorText: string;
targetUrl: string;
targetTitle: string;
rationale: string;
}Sample output excerpt
## SEO Content Brief
**Topic:** B2B SaaS Onboarding Best Practices
**Generated:** 2026-03-01 | **Goal:** New Blog Post
---
### Title (H1)
B2B SaaS Onboarding Best Practices: A Step-by-Step Guide for 2026
### Meta Description
Reduce churn and increase trial-to-paid conversion with these proven B2B SaaS onboarding
best practices — from activation flows to automated email sequences. (158 chars)
### Target Word Count
2,200–2,600 words
**Rationale:** Top 3 ranking pages average 2,380 words. Competitor gap analysis shows the
featured snippet answer is currently only 2 sentences — a comprehensive guide will outcompete.
---
### Outline
**H2: What Is B2B SaaS Onboarding (And Why Most Companies Get It Wrong)**
- Define onboarding in the B2B context vs. B2C
- Stat: 63% of customers consider onboarding experience when deciding to renew (Wyzowl)
- Common failure modes: too much friction, too little guidance, no activation milestone defined
*Internal link opportunity:* [What Is Product-Led Growth → /blog/product-led-growth]
**H2: The 5-Step B2B SaaS Onboarding Framework**
- Step 1: Define activation — what does "value delivered" look like for this product?
- Step 2: Build the minimum viable onboarding flow (3–5 steps max)
- Step 3: Segment users by role and use case — enterprise vs. SMB onboarding differ
- Step 4: Automate the email sequence (welcome, day 3 check-in, day 7 engagement nudge)
- Step 5: Measure time-to-value, not just completion rates
### Featured Snippet Opportunity
**Format:** Numbered list | **Target section:** H2 "5-Step Framework"
Keep the list items to 8–12 words each. Google currently shows a 5-item list from a competitor;
a 6-step list with clearer action verbs should displace it.
### Competitor Insights
| URL | Word Count | Angle | Gap We Can Fill |
|---|---|---|---|
| intercom.com/blog/saas-onboarding | 2,100 | Product tour focus | Missing the email sequence layer |
| chameleon.io/blog/onboarding-guide | 2,800 | Enterprise-heavy | No SMB-specific guidance |How It Works
-
Load activity context. The worker reads the activity label and
inputPayload(which containstarget_keyword,secondary_keywords,angle,topic,word_count, etc. set by the activity planner). -
Pre-load RAG context (worker code). Before Claude is invoked, the worker runs a
search()call with query"{activityLabel} content_brief"andtopK: 6. Results fromclient_docs,website_content, andpublished_contentare injected asKNOWLEDGE BASE CONTEXT. This is not a tool call — the context is pre-loaded before execution begins. -
Inject client context. The full
ClientContext.contentdocument is added to the prompt. -
Generate the brief. Claude writes a structured Markdown brief containing: title options, search intent, target word count, H2/H3 outline with guidance notes, key points to cover, internal link opportunities, and a CTA recommendation. Output is Markdown — not JSON.
-
Persist the ContentBrief row. The
postProcesshook upserts aContentBriefDB record:outputText= full Markdown output; structured fields (targetKeyword,secondaryKeywords,wordCount, etc.) are seeded frominputPayload. The primary keyword is auto-linked to (or creates) aKeywordrecord.
System Prompt
The actual prompt is stored in AgentConfig.systemPrompt (seeded via packages/db/src/seed.ts). Reproduced here for reference:
You are the Content Brief Writer agent for Leadmetrics, a digital marketing agency AI platform.
Your task is to create a detailed SEO content brief for a single blog post or landing page,
given a target keyword and client context.
BRIEF REQUIREMENTS:
1. Produce a structured Markdown brief with these sections:
## Content Brief: [Title]
**Target Keyword:** <primary keyword>
**Secondary Keywords:** <comma-separated list>
**Search Intent:** <informational / commercial / transactional>
**Target Word Count:** <range>
**Target Audience:** <description>
## Proposed Title Options
(3 title variants — H1 optimised for CTR and keyword)
## Outline
(Full H2/H3 outline with guidance notes for each section)
## Key Points to Cover
(Bullet list of must-include facts, angles, or claims)
## Internal Link Opportunities
(Suggested pages on the client's site to link to/from)
## CTA Recommendation
(What action should the reader take at the end?)
2. The brief must be actionable enough for the Blog Writer agent to write without additional context.
3. Align tone guidance with the client's brand voice.
4. Include at least one data point, statistic, or research angle the writer should incorporate.
Output ONLY the content brief. No preamble, no explanation.Skills Injected
None. All context (client profile, RAG results, task hints) is injected directly into the prompt by the content.worker pipeline. No skillsDir is used.
RAG Usage
Mechanism: Pre-loaded (worker code runs search() before Claude starts — not a tool call).
| Dataset | Included | Purpose |
|---|---|---|
client_docs | ✅ | Brand voice, product details, content standards |
website_content | ✅ | Existing pages for internal link suggestions |
published_content | ✅ | Past articles — brief is oriented away from already-covered angles |
Query: "{activityLabel} content_brief" — one query, topK: 6.
Fallback: Execution continues without RAG if search fails (warn logged).
Tools
None. All context is pre-loaded by the worker before Claude is invoked. Claude runs with allowedTools: [] and maxTurnsPerRun: 1 — single-turn generation with no tool access.
HITL Gates
- Review type:
content_brief_review - Risk level:
low - Trigger: Always — the content brief is presented to the DM reviewer before the Blog Writer is dispatched.
- Reviewer action: Approve as-is, edit specific sections (outline, word count, internal links), add section notes, or reject and request re-run. Approved brief is passed as input to the Blog Writer job.
- Editing: Full inline editing of the brief in the DM Portal. Changes are saved to the brief record before dispatch. The reviewer is expected to add any client-specific nuance that the brief does not capture (e.g. “mention our case study from Acme Corp in the social proof section”).
Guardrails
| Rule | Enforcement |
|---|---|
| Title must be 50–65 characters | Hard length check post-generation; retry with explicit instruction if violated |
| Meta description must be 150–160 characters | Hard length check; retry if violated |
| Outline must have 5–8 H2 sections | Count check; if fewer than 5, retry with instruction to expand |
| Each H2 must have ≥ 3 key points | Count check per section; sections with < 3 are flagged for retry |
| Internal links must point to real pages | URL validation against RAG-returned website content; invented URLs are stripped and a warning is added |
| No duplicate content angles from published articles | Similarity check against Published Content RAG results; if overlap > 0.70, the outline is reframed |
Tenant Settings Used
| Setting | How it’s used |
|---|---|
industry | Scopes RAG queries and informs tone guidance |
targetAudience | Informs which secondary keyword angles to prioritise in the outline (e.g. B2B audiences want ROI-focused sections; B2C audiences want how-to sections) |
connectedChannels | Determines which internal link targets are valid — only URLs on connected/known domains are included |
plan | Free plan allows up to 2 brief generations per month; Pro+ is unlimited |
Cost Profile
| Avg input tokens | ~2,000–4,000 (system prompt + client context + RAG chunks + keyword hints) |
| Avg output tokens | ~800–1,500 (structured Markdown brief) |
| Est. cost / task | ~$0.05–0.10 |
Error Handling
| Error | Response |
|---|---|
| RAG returns no results | Execution continues without knowledge base context; warn logged |
AgentConfig.systemPrompt missing | Hard fail: "No systemPrompt configured for agent role content-brief-writer. Seed the database." |
| Output shorter than 50 chars | Hard fail: credits released; activity marked failed |
| Keyword record creation fails | postProcess catches the error and logs it — brief is still saved, just without a primaryKeywordId link |