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.
Project Overview
Self-driven lab Module12_Self_Driven_Lab.ipynbYou 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-7with 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.
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.jsonwith environment variable substitution (${CRM_TOKEN}) keeps secrets out of version control. - CRM Resource Hierarchy: expose
crm://docs,crm://schemas, andcrm://workflowsresources 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
Grepfor structured data lookups. - Discovery Tax Reduction: Resources act as catalogs. The agent should inspect
crm://schemasandcrm://workflowsbefore 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.
{
"mcpServers": {
"crm": {
"command": "node",
"args": ["./mcp-servers/crm-server.js"],
"env": {
"CRM_TOKEN": "${CRM_TOKEN}",
"CRM_BASE_URL": "${CRM_BASE_URL}"
}
}
}
}
{
"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
Tasktool 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
errorCategoryandisRetryableso the Coordinator can recover intelligently rather than failing the workflow.
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:
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."}],
)
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-24beta header raisesmax_tokensto 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_findingsand decision-critical summaries first, then detailed evidence under explicit prospect and source-type section headers. - Extensible Categories: prospect schemas must use an enum with
otherplus a required detail field for extensible fields such asindustryorreason_for_outreach.
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,
},
}
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
PreToolUsehook blocks anyprocess_outreachcall if the prospect'srisk_scorehas not been verified. - Server-Side Compaction:
compact_20260112with 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_humanimmediately.
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,
)
{
"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 aglobsfrontmatter key enforces the standard outreach template only when Claude is editing files underoutreach/. - Agent Skills: a
generate-auditskill withcontext: forkperforms 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 inreferences/so the agent only loads extra context when needed. - CI Review Output: use
claude -pwith--output-format jsonand--json-schemaso automated review findings can be posted as inline PR comments.
---
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.
---
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.
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_resultsrather 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
- 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_tokenson 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.