
Designing Agentic Marketing on AWS: A Bedrock AgentCore Blueprint for GEO and AEO
Learn how to build an autonomous AI marketing agent on AWS Bedrock AgentCore that handles Generative Engine Optimization (GEO) and Answer Engine Optimization (AEO) end-to-end — with Claude Skills, MCP tools, and production-ready code.
Gartner predicted traditional search engine volume would drop 25% by 2026. It happened. If your marketing stack still optimizes only for "ten blue links," your brand is invisible to half of your buyers now asking ChatGPT, Perplexity, Claude, and Google AI Overviews instead.
For years, SEO was the entire game. Then AEO (Answer Engine Optimization) showed up to win featured snippets and voice answers. Now GEO (Generative Engine Optimization) is the discipline of getting cited inside LLM-generated answers — and it's a different beast. LLMs don't rank links, they synthesize sources. To be one of those sources, your content needs structured authority signals, entity clarity, and quote-worthy passages that an AI will lift verbatim.
Doing all of that — keyword research, content writing, schema markup, technical audits, citation tracking — by hand, every week, across hundreds of pages? That's where most marketing teams hit the wall.
This post walks through how I designed an agentic marketing system on AWS that handles the whole GEO/AEO lifecycle autonomously, using Amazon Bedrock AgentCore, the open-source SEO & GEO Claude Skills library , and a handful of AWS primitives most builders already have in their toolbox (Thanks, Aaron Zhu).
Why agents, and why now?
A single LLM call can write a blog post. That's not agentic — that's autocomplete with extra steps.
An agent is a system that can plan a multi-step goal, call tools, observe results, course-correct, and persist memory across runs. For GEO/AEO, the goal isn't "write me a paragraph." It's: "For this product, find the queries our buyers ask LLMs, identify the citation gaps, write authoritative content that fills them, mark it up with schema, audit it against E-E-A-T, publish it, and track which AI engines start citing us within 30 days."
That's a workflow with branches, tool calls, and feedback loops. Bedrock AgentCore, which reached general availability in October 2025, was built for exactly this. It ships as composable services: Runtime for serverless execution, Memory for context, Gateway for turning APIs into MCP tools, Identity for delegated auth, and Observability for tracing.
The design
One supervisor agent orchestrates four specialists, each loading a focused slice of the SEO/GEO skills:
- Research runs
keyword-research,serp-analysis,content-gap-analysis— finds where LLMs cite competitors but not you.
- Writer runs
seo-content-writer,geo-content-optimizer,schema-markup-generator— drafts content engineered for LLM citation, with JSON-LD schema attached.
- Auditor runs
content-quality-auditor(80-item CORE-EEAT) anddomain-authority-auditor(40-item CITE) — blocks publish unless score clears 95/120.
- Monitor runs
rank-tracker,performance-reporter,alert-manager— checks at 7/14/30 days whether AI engines started citing the new URL.
Tools live behind AgentCore Gateway as MCP-compliant Lambda functions. State and citation history live in DynamoDB; drafts in S3; short-term context in AgentCore Memory.
The skills are markdown — zero dependencies, no SDK, no version drift when Bedrock updates a model. You drop them into the agent's system prompt.
The code
Here's the supervisor skeleton. Roughly 100 lines, deployable as-is on AgentCore Runtime.
"""Agentic Marketing Supervisor on Amazon Bedrock AgentCore========================================================pip install bedrock-agentcore strands-agents boto3"""import boto3from pathlib import Pathfrom bedrock_agentcore import AgentCoreApp, MemoryClientfrom strands import Agent, toolfrom strands.models import BedrockModel
# Load SEO/GEO skill files from https://github.com/aaron-he-zhu/seo-geo-claude-skillsSKILLS_ROOT = Path("./skills")
def load_skills(*names: str) -> str: return "".join( f"\n<skill name='{n}'>\n{(SKILLS_ROOT / n / 'SKILL.md').read_text()}\n</skill>\n" for n in names )
# MCP tools exposed through AgentCore Gatewaygateway = boto3.client("bedrock-agentcore-gateway")
@tooldef keyword_research(seed_topic: str) -> dict: """Pull keyword + AI-prompt data and which LLMs cite competitors.""" return gateway.invoke_tool( gateway_name="seo-data-gateway", tool_name="keyword_research", payload={"seed": seed_topic}, )
@tooldef check_ai_citations(url: str, queries: list[str]) -> dict: """Query ChatGPT, Perplexity, Claude, Gemini, Google AI Overviews.""" return gateway.invoke_tool( gateway_name="seo-data-gateway", tool_name="ai_citation_check", payload={"url": url, "queries": queries}, )
@tooldef run_quality_audit(draft_s3_uri: str) -> dict: """Run CORE-EEAT (80) + CITE (40). Returns score 0-120 + deltas.""" return gateway.invoke_tool( gateway_name="audit-gateway", tool_name="full_audit", payload={"draft": draft_s3_uri}, )
@tooldef publish_to_cms(draft_s3_uri: str, schema_jsonld: dict, slug: str) -> dict: return gateway.invoke_tool( gateway_name="cms-gateway", tool_name="publish", payload={"draft": draft_s3_uri, "schema": schema_jsonld, "slug": slug}, )
# Specialist sub-agents — each loads only the skills it needsmodel = BedrockModel( model_id="anthropic.claude-sonnet-4-5-20251022-v1:0", region_name="us-east-1", temperature=0.3,)
researcher = Agent( model=model, system_prompt="Find GEO citation gaps where LLMs cite competitors but not us." + load_skills("research/keyword-research", "research/serp-analysis", "research/content-gap-analysis"), tools=[keyword_research, check_ai_citations],)
writer = Agent( model=model, system_prompt="Write content LLMs cite. Extractable facts, expert quotes, " "statistics, JSON-LD schema alongside every draft." + load_skills("build/seo-content-writer", "build/geo-content-optimizer", "build/schema-markup-generator"),)
auditor = Agent( model=model, system_prompt="Strict E-E-A-T auditor. Block publish if score < 95." + load_skills("cross-cutting/content-quality-auditor", "cross-cutting/domain-authority-auditor"), tools=[run_quality_audit],)
# Supervisor delegates and persists handoffs to long-term memorymemory = MemoryClient(memory_id="marketing-agent-memory")
@tooldef delegate_research(brief: str) -> str: return researcher(brief).message@tooldef delegate_writing(brief: str) -> str: return writer(brief).message@tooldef delegate_audit(uri: str) -> str: return auditor(f"Audit: {uri}").message
supervisor = Agent( model=model, system_prompt=( "You orchestrate a GEO/AEO workflow. Each run:\n" "1. Read prior handoff from memory.\n" "2. Identify highest-ROI citation gap via researcher.\n" "3. Commission draft via writer.\n" "4. Gate publish on auditor (score >= 95).\n" "5. Write handoff summary to memory before exiting.\n" + load_skills("cross-cutting/memory-management", "cross-cutting/entity-optimizer") ), tools=[delegate_research, delegate_writing, delegate_audit, publish_to_cms],)
# AgentCore Runtime entrypoint — EventBridge invokes this dailyapp = AgentCoreApp()
@app.entrypointdef handler(payload: dict) -> dict: prior = memory.retrieve(namespace="marketing/handoffs", query="latest weekly handoff", top_k=1) context = prior[0]["text"] if prior else "First run."
goal = payload.get("goal", "Find and fill the highest-ROI GEO citation gap this week.")
result = supervisor(f"Prior handoff:\n{context}\n\nGoal:\n{goal}")
memory.store(namespace="marketing/handoffs", content=result.message) return {"status": "ok", "summary": result.message}
if __name__ == "__main__": app.run()Deploy and schedule:
agentcore deploy --name marketing-supervisor --entrypoint app.handler
aws events put-rule --name daily-marketing-agent \ --schedule-expression "cron(0 11 * * ? *)"That's the whole control plane. AgentCore handles runtime, session isolation, memory, and observability. The Lambda tools handle integrations. The skills handle the how of GEO/AEO so this never becomes a Python problem.
What surprised me
Citation lag is real. New content takes 7–45 days to surface in LLM citations. Perplexity is fastest, ChatGPT slowest. Plan your evaluation window accordingly or you'll declare failure on content that's actually working.
The audit gate is the most valuable part. Without it, the writer agent happily generates plausible-but-thin content. With it, the writer revises until quality clears the bar — exactly what a senior content editor would force. Threshold of 95/120 was the sweet spot in testing.
Memory is where multi-day campaigns live or die. AgentCore Memory's session-vs-long-term split maps cleanly to HOT/COLD tiering. Without it, every run starts from scratch and the agent re-explores ground it already covered yesterday.
Wrapping up
The shift from SEO to SEO + AEO + GEO isn't a tooling change — it's a workflow change. You now need ten times the volume across more engines with shorter feedback loops. That's an agent-shaped problem. Bedrock AgentCore gives you the infrastructure, the open-source skills give you the playbook, and 100 lines of Python wire them together. The rest is iteration.
References
Posted as part of the AWS Community Builders program. Opinions are my own.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article