A SERP-based content brief should identify a search task, proposed sections and the sources an editor must review. The implementation below produces a deterministic JSON brief from search results and approved source passages. It does not generate an article, infer facts from snippets, or claim that a model has checked the evidence.
Define the output before adding a model
| Field | Purpose |
|---|---|
| query | The search task that produced this brief |
| sources | Source URL and an excerpt already checked against the retrieved text |
| sections | A suggested heading with source IDs, not an unsupported claim |
| editor_checks | Questions requiring human review before drafting |
Fetch a search envelope using the Google Search API contract. Check HTTP status and the business code, then read data.organic. Review source URLs before extraction. A result snippet is useful for finding a page; it is not sufficient evidence for a price, legal conclusion or technical guarantee.
Run the brief builder with a small fixture
import json
from urllib.parse import urlsplit
def build_brief(query, envelope, reviewed_passages):
if envelope.get("code") != 0 or not isinstance(envelope.get("data"), dict):
raise ValueError("Search contract failed")
rows = envelope["data"].get("organic", [])
if not isinstance(rows, list):
raise ValueError("Expected organic array")
sources, sections = [], []
for row in rows:
url = row.get("link") if isinstance(row, dict) else None
if not isinstance(url, str) or urlsplit(url).scheme != "https":
continue
source = reviewed_passages.get(url)
if not isinstance(source, dict):
continue
quote, text = source.get("quote"), source.get("text")
if not isinstance(quote, str) or not quote.strip() or not isinstance(text, str) or quote not in text:
raise ValueError("Quote is absent from the reviewed source")
sid = "source-" + str(len(sources) + 1)
sources.append({"id":sid, "url":url, "quote":quote})
sections.append({"heading":row.get("title") or "Untitled source", "source_ids":[sid]})
if not sources:
raise ValueError("No reviewed sources: do not generate an unsupported brief")
return {"query":query, "sources":sources, "sections":sections,
"editor_checks":["Does the quote support the proposed claim?", "What original contribution is missing?"]}
if __name__ == "__main__":
# Synthetic inputs demonstrate the contract, not a live SERP or a factual finding.
url = "https://example.com/source"
envelope = {"code":0, "data":{"organic":[{"title":"Cache validation", "link":url}]}}
brief = build_brief("cache validation", envelope,
{url:{"text":"Revalidate expired records.", "quote":"Revalidate expired records."}})
print(json.dumps(brief, indent=2))
Save this as brief.py and run python brief.py. The fixture uses a reserved example domain and fictional text. Its output contains one source and one proposed section. Replace the fixture with reviewed passages to create a real brief. The function rejects a quote absent from the source, an invalid response shape and a brief without usable evidence.
What an editor still has to decide
An exact substring match only checks that the excerpt was present. It does not prove that it supports the proposed interpretation, remains current, or represents the whole page fairly. Review the claim, omitted context and publication date. Then name the contribution this article will add: a reproducible test, an original decision rule, or a documented implementation detail. If the existing cluster owner already answers the same task, update that owner instead of generating a competing article.
An LLM can propose an outline after these checks, but its output needs the same source IDs and a schema validator. This tutorial intentionally has no placeholder “AI-generated brief” string and no dependency on an untested SDK version. To measure actual results after publishing, use the GSC and GA4 reporting contract.