| name | content-agent-triage |
| description | Automate content improvement with Content Agent (Agent Actions) safely. The queued โ staged review pipeline, draft-as-review-gate pattern, instruction design, and the Content Release upgrade. Trigger on: content agent, agent actions, agent.action.generate, triage, agentReview, stale content refresh, SEO drafting, review queue. |
Content Agent Triage
Automate the "nightly catalog triage" journey: the sync flags underperforming
articles, and a scheduled Function uses Agent Actions to draft reasoning and
improved SEO โ always into a draft a human approves. Nothing goes live
automatically.
Core principle
The draft is the review gate. Every agent write lands in
drafts.<id>, never the published document. The ops lead reviews the "Content
Agent Queue" in Studio and publishes to approve. The agent only touches
editorial/SEO fields โ never the read-only analytics signal.
The state machine
agentReview.status on article drives the whole pipeline:
idle โ queued โ in_progress โ staged โ approved | dismissed
queued โ set by the sync (runSync) when an article newly enters the
stale tier and its review is idle/unset. Only idle reviews are touched, so
in-flight work is never disturbed.
in_progress โ set by the triage Function as it starts an article.
staged โ set after the agent writes; the draft is ready for review.
approved / dismissed โ the human decision (publish or discard draft).
The triage Function
functions/agent-triage/index.ts runs ~30 min after the sync (schedule in
sanity.blueprint.ts). Per run:
QUEUED_QUERY loads agentReview.status == "queued" articles, joining their
articlePerformance tier / referrer / percentile as context.
- For each: set
in_progress, ensure a draft exists (copy published minus
_rev into drafts.<id>), call client.agent.action.generate, then set
staged + releaseId + reviewedAt on the draft.
- On error, requeue (
status: 'queued') so the next run retries.
Agent Actions setup
const client = createClient({projectId, dataset, token, apiVersion: 'vX', useCdn: false})
await client.agent.action.generate({
schemaId,
documentId: draftId,
instruction: INSTRUCTION,
instructionParams: {
tier: {type: 'constant', value: article.tier ?? 'stale'},
referrer: {type: 'constant', value: article.referrer ?? 'organic'},
percentile: {type: 'constant', value: String(article.percentile ?? 0)},
},
target: [{path: 'agentReview.agentNotes'}, {path: 'seoTitle'}, {path: 'seoDescription'}],
})
Safety layers (why this is trustworthy)
- Scoped input โ the GROQ filter limits the agent to queued articles.
- Scoped output โ
target restricts writes to editorial/SEO fields.
- Draft-only โ writes go to
drafts.<id>; publishing is a human act.
- Grounded instruction โ the prompt passes signal as read-only context and
tells the agent to ground everything in the article's actual content, then
optimize SEO for the article's top acquisition channel.
Instruction design
The INSTRUCTION string channel-tailors the SEO advice: organic โ search
intent/keywords; social โ a scroll-stopping hook; email โ narrative depth + CTA;
direct/referral โ updated facts + internal linking. It asks for one reasoning
paragraph plus exactly three concrete improvement opportunities. Keep field
limits explicit (seoTitle โค 70 chars, seoDescription โค 160).
Reviewing in Studio
studio/structure.ts defines the Content Agent Queue โ articles with
agentReview.status in ["queued", "in_progress", "staged"]. Editors open a
staged article, read the agent notes in the agentReview object, compare the
drafted SEO, and publish (approve) or discard the draft (dismiss).
Production upgrade: Content Releases
Each run currently tags staged drafts with a releaseId
(stale-content-refresh-YYYY-MM-DD). The documented upgrade is to promote this
batch to a first-class Content Release via the Releases API, so the whole
nightly triage can be reviewed and published atomically. See AGENT.md.
References
functions/agent-triage/index.ts โ the triage Function
packages/@starter/analytics-sync/src/index.ts โ where articles get queued
studio/schemaTypes/article.ts โ agentReview object + status field
studio/structure.ts โ Content Agent Queue view
sanity.blueprint.ts โ schedule + env injection