Module 12

Enterprise Prospecting & Outreach Orchestrator

The capstone integrates the Claude API, the Claude Agent SDK, and Claude Code into a single production system. You will build a Coordinator Agent that decomposes prospecting requests into parallel research subagents, synthesizes findings via the Advisor tool, ships outreach at scale through Message Batches, and stays reliable under long-running sessions with hooks, compaction, and case facts.

Answer key Module12_Complete.ipynb

Project Overview

Self-driven lab Module12_Self_Driven_Lab.ipynb

You are building the Enterprise Prospecting & Outreach Orchestrator: a system that identifies high-value prospects, performs deep research using a multi-agent hub-and-spoke model, generates high-volume outreach campaigns, and maintains strict reliability through deterministic hooks and context compaction. Every concept from Modules 1 through 11 lands in this single project.

Phase 1: Agent Definition & Data Governance

Define the Coordinator Agent with the Claude Agent SDK so the runtime owns history, tool dispatch, and termination. Pair it with adaptive thinking, US data residency, and high effort at call time.

  • Model & Capabilities: claude-opus-4-7 with adaptive thinking so Claude can dynamically determine reasoning depth.
  • Data Residency: set inference_geo: "us" on each call. Note the 1.1x pricing multiplier on Opus 4.6+.
  • Effort Control: set effort: "xhigh" for long-horizon prospecting work.
  • Interview Pattern: before planning, the Coordinator must ask 2-3 clarifying questions about outreach goals, such as tone constraints, competitor sensitivity, required technical depth, and any claims that require human approval.
Python
import os

import anthropic
from dotenv import load_dotenv

load_dotenv()  # reads ANTHROPIC_API_KEY from your .env file

client = anthropic.Anthropic()

coordinator_agent = client.beta.agents.create(
    name="Enterprise Research Coordinator",
    model="claude-opus-4-7",
    description="Orchestrates prospecting research and outreach strategy.",
    system=(
        "You are the lead orchestrator. Use the Task tool to delegate to "
        "specialist subagents. Always maintain a 'case facts' block with "
        "non-negotiable transactional data. Before generating the research "
        "plan, ask 2-3 concise clarifying questions about outreach goals, "
        "including tone, competitor sensitivity, and technical depth."
    ),
    tools=[
        {
            "type": "agent_toolset_20260401",
            "configs": [
                {"name": "web_search", "enabled": True, "permission_policy": {"type": "always_allow"}},
                {"name": "web_fetch",  "enabled": True, "permission_policy": {"type": "always_allow"}},
            ],
        }
    ],
)

Phase 2: Knowledge Mapping with MCP & Resources

Connect the CRM directly to the Messages API with the MCP Connector instead of paying for exploratory tool calls. Expose Resources as a navigable map of the data so Claude can plan its tool sequence before executing.

  • Beta Header: mcp-client-2025-11-20.
  • Project Config: .mcp.json with environment variable substitution (${CRM_TOKEN}) keeps secrets out of version control.
  • CRM Resource Hierarchy: expose crm://docs, crm://schemas, and crm://workflows resources so Claude can inspect the CRM's documentation hierarchy before calling query or write tools.
  • Selection Reliability: tool descriptions must explain why CRM MCP tools are preferred over built-in text tools such as Grep for structured data lookups.
  • Discovery Tax Reduction: Resources act as catalogs. The agent should inspect crm://schemas and crm://workflows before exploratory CRM queries instead of discovering tables through repeated tool calls.
  • ZDR note: the MCP Connector is not ZDR-eligible due to server-side routing.
JSON (.mcp.json)
{
  "mcpServers": {
    "crm": {
      "command": "node",
      "args": ["./mcp-servers/crm-server.js"],
      "env": {
        "CRM_TOKEN": "${CRM_TOKEN}",
        "CRM_BASE_URL": "${CRM_BASE_URL}"
      }
    }
  }
}
JSON (CRM resources/list response)
{
  "resources": [
    {
      "uri": "crm://docs/prospecting",
      "name": "CRM prospecting documentation",
      "description": "Use before lead searches. Explains lead stages, required fields, and routing rules.",
      "mimeType": "text/markdown"
    },
    {
      "uri": "crm://schemas/leads",
      "name": "Leads schema",
      "description": "Use before CRM lead lookups. Lists column names, allowed enum values, and join keys so the agent chooses crm_query_leads instead of built-in Grep for structured account data.",
      "mimeType": "application/json"
    },
    {
      "uri": "crm://workflows/outreach-approval",
      "name": "Outreach approval workflow",
      "description": "Approval gates required before process_outreach can run.",
      "mimeType": "text/markdown"
    }
  ]
}

Phase 3: Multi-Agent Research Workflow

Hub-and-Spoke architecture: the Coordinator decomposes a prospecting request and spawns specialist subagents in parallel inside a single turn.

  • Parallel Execution: the Coordinator calls the Task tool multiple times to spawn subagents for Web Research, Financial Analysis, and Competitor Tracking.
  • Isolated Context: subagents do not inherit the Coordinator's history. Pass each subagent only the data it needs.
  • Structured Errors: subagents return errorCategory and isRetryable so the Coordinator can recover intelligently rather than failing the workflow.
Python
session = client.beta.sessions.create(
    agent_id=coordinator_agent.id,
    mcp_servers=[
        {
            "name": "crm-server",
            "type": "url",
            "url": "https://mcp.your-enterprise.com/crm",
            "authorization_token": os.environ["CRM_TOKEN"],
        }
    ],
)

# Coordinator turn: spawn parallel research subagents in a single message
client.beta.sessions.events.send(
    session_id=session.id,
    event={
        "type": "user.message",
        "content": [{
            "type": "text",
            "text": (
                "Research AI adoption in Fintech and Healthcare simultaneously. "
                "Spawn three Task subagents: web_research, financial_analysis, "
                "and competitor_tracking. Pass each only the prospect summary."
            ),
        }],
    },
)

When using the Messages API directly, include the MCP Connector beta header on the call:

Python (Messages API with MCP Connector)
response = client.beta.messages.create(
    model="claude-opus-4-7",
    max_tokens=4096,
    mcp_servers=[{
        "name": "crm-server",
        "type": "url",
        "url": "https://mcp.your-enterprise.com/crm",
        "authorization_token": os.environ["CRM_TOKEN"],
    }],
    tools=[{
        "type": "mcp_toolset",
        "mcp_server_name": "crm-server",
        "configs": {
            "resources/read": {"enabled": True},
            "crm_query": {"enabled": True},
            "process_outreach": {"enabled": True},
        },
    }],
    betas=["mcp-client-2025-11-20"],
    messages=[{"role": "user", "content": "Map the CRM docs, then find fintech prospects."}],
)
Python (subagent error handler)
def subagent_tool_handler(tool_input):
    try:
        return {"data": run_research(tool_input)}
    except TimeoutError:
        return {
            "errorCategory": "TIMEOUT",
            "isRetryable": True,
            "message": "Research API timed out. Retry with a narrower query."
        }
    except PermissionError:
        return {
            "errorCategory": "PERMISSION",
            "isRetryable": False,
            "message": "Token lacks access. Coordinator should pivot, not retry."
        }

Phase 4: Synthesis & Scaled Outreach

Synthesize research findings, then ship outreach at volume.

  • Advisor Tool (advisor_20260301): Sonnet 4.6 executor handles writing while an Opus 4.7 advisor course-corrects mid-generation.
  • Message Batches: 50% discount on bulk outreach. Each request needs a unique custom_id; results return out of order.
  • Extended Output: output-300k-2026-03-24 beta header raises max_tokens to 300,000 for book-length intelligence reports.
  • Structured Extraction: JSON-schema outputs with nullable fields for annual_revenue, budget_range, etc., to prevent hallucination when data is missing.
  • Position-Aware Input Ordering: the synthesis prompt must put key_findings and decision-critical summaries first, then detailed evidence under explicit prospect and source-type section headers.
  • Extensible Categories: prospect schemas must use an enum with other plus a required detail field for extensible fields such as industry or reason_for_outreach.
Python
aggregated_research = {
    "key_findings": [
        "Fintech CTOs show high interest in agentic workflow governance.",
        "Healthcare prospects require stricter compliance language and human review."
    ],
    "sections": {
        "prospect_startup_segment": startup_evidence,
        "prospect_fortune_500_segment": enterprise_evidence,
        "source_crm_notes": crm_notes,
        "source_web_research": cited_web_findings,
    },
}
Python
message_batch = client.beta.messages.batches.create(
    betas=["output-300k-2026-03-24"],
    requests=[
        {
            "custom_id": "outreach-campaign-001",
            "params": {
                "model": "claude-sonnet-4-6",
                "max_tokens": 300000,
                "messages": [{
                    "role": "user",
                    "content": "Generate a 100-page market intelligence report for Fintech CTOs."
                }],
                "tools": [{
                    "type": "advisor_20260301",
                    "name": "advisor",
                    "model": "claude-opus-4-7",
                    "effort": "xhigh",
                    "caching": {"type": "ephemeral", "ttl": "1h"}
                }],
                "output_config": {
                    "format": {
                        "type": "json_schema",
                        "schema": {
                            "type": "object",
                            "properties": {
                                "company_name":   {"type": "string"},
                                "contact_email":  {"type": "string"},
                                "annual_revenue": {"type": ["integer", "null"]},
                                "budget_range":   {"type": ["string", "null"]},
                                "industry": {
                                    "type": "string",
                                    "enum": ["fintech", "healthcare", "manufacturing", "retail", "other"]
                                },
                                "industry_detail": {"type": ["string", "null"]},
                                "reason_for_outreach": {
                                    "type": "string",
                                    "enum": ["ai_governance", "workflow_automation", "security_review", "other"]
                                },
                                "reason_detail": {"type": ["string", "null"]}
                            },
                            "required": [
                                "company_name", "contact_email", "annual_revenue", "budget_range",
                                "industry", "industry_detail", "reason_for_outreach", "reason_detail"
                            ],
                            "additionalProperties": False
                        }
                    }
                }
            }
        }
    ]
)

Phase 5: Production Reliability & Context Hygiene

Long-running research sessions need active context management and deterministic safety rails.

  • Deterministic Hooks: a PreToolUse hook blocks any process_outreach call if the prospect's risk_score has not been verified.
  • Server-Side Compaction: compact_20260112 with a 50,000-token trigger summarizes verbose history automatically.
  • Case Facts Pattern: non-negotiable transactional data ("Max Budget: $50k") lives in a persistent block so compaction never paraphrases it away.
  • Human-in-the-Loop: if a prospect requests "no AI contact" or a policy gap is detected, the agent must call escalate_to_human immediately.
Python (compaction config)
response = client.messages.create(
    model="claude-opus-4-7",
    max_tokens=16000,
    thinking={"type": "adaptive"},
    effort="xhigh",
    inference_geo="us",                     # 1.1x multiplier; ZDR-eligible
    context_management={
        "edits": [
            {
                "type": "compact_20260112",
                "trigger": {"input_tokens": 50000},
                "instructions": "Summarize research findings but preserve 'case facts' verbatim."
            }
        ]
    },
    extra_headers={"anthropic-beta": "compact-2026-01-12"},
    messages=conversation,
)
JSON (PreToolUse hook)
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": {"tool_name": "process_outreach"},
        "hooks": [
          {
            "type": "command",
            "command": "python verify_risk_score.py"
          }
        ]
      }
    ]
  }
}

Phase 6: Claude Code & Skills

Manage the project's development standards through Claude Code.

  • Path-Scoped Rules: a rule file in .claude/rules/ with a globs frontmatter key enforces the standard outreach template only when Claude is editing files under outreach/.
  • Agent Skills: a generate-audit skill with context: fork performs deep compliance checks on generated emails without polluting the main development context.
  • Three-Level Progressive Disclosure: the skill must keep trigger logic in frontmatter, actionable workflow steps in SKILL.md, and detailed compliance material in references/ so the agent only loads extra context when needed.
  • CI Review Output: use claude -p with --output-format json and --json-schema so automated review findings can be posted as inline PR comments.
Markdown (.claude/rules/outreach-template.md)
---
globs: ["outreach/**/*.md", "outreach/**/*.html"]
---
# Standard Outreach Template Rules
- Open with the prospect's confirmed pain point from CRM, never a generic hook.
- Include one quantified case study from the same industry vertical.
- Close with a single, specific call to action (no menu of options).
- Never reference compliance regimes the prospect has not opted into.
YAML (.claude/skills/generate-audit/SKILL.md)
---
name: generate-audit
description: Audit generated outreach emails when asked to review campaign copy, regulated claims, unsupported personalization, or compliance-sensitive prospect messaging.
context: fork
allowed-tools: [read_file, web_search]
---
# Audit Skill
1. Read the email under review.
2. Cross-check claims against the prospect's stated regulated regimes.
3. Open `references/compliance-claims.md` only when the email mentions HIPAA, SOC 2, ISO 27001, privacy, safety, or procurement claims.
4. Flag unsupported claims, weak personalization, policy conflicts, and missing escalation triggers.
5. Return a structured JSON report with findings, severity, evidence, and recommended next action.
CI review command
claude -p "Review this capstone PR and return inline findings." \
  --output-format json \
  --json-schema .claude/schemas/pr-review-findings.schema.json

Phase 7: Evaluation & Success Metrics

Evaluate the orchestrator as a product, not only as a demo.

  • Quantitative: skill trigger reliability reaches at least 90% of relevant queries, the workflow uses fewer tool calls than a baseline, the coordinator salvages partial_results rather than re-running failed searches, and 10 high-confidence extractions are manually sampled across prospect segments and source types to catch segment-specific failures.
  • Qualitative: a new user can complete the task on the first try with minimal guidance, escalation summaries are actionable, PR review findings are specific enough to become inline comments, and a completely independent Claude instance in a fresh session catches unsupported claims or weak outreach that the generator missed.
  • Independent Review: start a fresh Claude session with no prior reasoning context. Provide only the final outreach, source evidence, and review rubric. The reviewer must catch unsupported claims, policy issues, weak personalization, and missing escalations that the generator may have rationalized.
  • Stratified Random Sampling: sample extractions across prospect segments and source types rather than relying on aggregate accuracy. Include at least one startup, one mid-market account, one Fortune 500 account, one CRM-sourced record, and one web-researched record.

Final Audit Checklist

Architect Tip for the Exam
  • ZDR check: adaptive thinking, citations, structured outputs, and standard web search are ZDR-eligible; Message Batches and the MCP Connector are not. Batch results are stored server-side for 29 days.
  • Cost check: inference_geo: "us" applies a 1.1x multiplier on Opus 4.6+ across input, output, and cache. The same multiplier applies to Priority-Tier burndown.
  • Token management: after compaction blocks fire, call client.messages.count_tokens on the outgoing payload to verify the effective context size.
  • Citations vs. Structured Outputs: mutually exclusive. Sending both returns a 400. Choose grounded research or CRM-ready extraction per request.
  • Schema safety: PHI must never appear in tool names, property names, or property descriptions because schemas are cached separately from message content.
  • Structured output limits: maximum 20 strict tools, 24 optional parameters, and 16 union-type parameters per request.
  • Independent review: final outreach must be audited by a fresh Claude session, not the generation session, so the reviewer is isolated from the generator's assumptions.
  • Subagents: isolated context by default. The Coordinator must explicitly forward only the data each subagent needs.