Account Research Brief Example
This example shows how to use the Phoenix Agents API to generate comprehensive account research briefs. You'll learn how to start a research run, poll for completion, and retrieve the generated brief.
Prerequisites
- A Phoenix API key (get one from Settings > API Keys)
- Python 3.8+ with the
requestslibrary
Quick Start
Get the Script
You can either copy the script from the Complete Python Script section below, or download it using curl:
curl -O https://phoenix.hginsights.com/docs/scripts/generate_brief.py
Installation
pip install requests
Environment Setup
export PHOENIX_API_KEY="phx_your_api_key_here"
Complete Python Script
Save this as generate_brief.py:
#!/usr/bin/env python3
"""
Phoenix Account Research Brief Generator
This script demonstrates how to use the Phoenix Agents API to generate
comprehensive account research briefs for sales enablement.
Usage:
python generate_brief.py salesforce.com
python generate_brief.py --depth deep cisco.com
python generate_brief.py --output brief.html hubspot.com
"""
import argparse
import os
import sys
import time
from typing import Literal
import requests
# Configuration
BASE_URL = "https://phoenix.hginsights.com/api/agents/v1"
API_KEY = os.environ.get("PHOENIX_API_KEY")
def get_headers() -> dict:
"""Get request headers with authentication."""
if not API_KEY:
print("Error: PHOENIX_API_KEY environment variable not set")
print("Set it with: export PHOENIX_API_KEY='phx_your_key_here'")
sys.exit(1)
return {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def start_research_run(
domain: str,
depth: Literal["quick", "standard", "deep"] = "standard",
) -> str:
"""
Start an account research brief generation run.
Args:
domain: Target company domain (e.g., "salesforce.com")
depth: Research depth - "quick" (1-2 min), "standard" (2-4 min), or "deep" (4-8 min)
Returns:
run_id: The ID of the started run
"""
print(f"Starting research for {domain} (depth: {depth})...")
response = requests.post(
f"{BASE_URL}/agents/account-research/runs",
headers=get_headers(),
json={
"input": {"domain": domain},
"params": {
"depth": depth,
"output_formats": ["html"],
},
},
)
if response.status_code == 401:
print("Error: Invalid API key")
sys.exit(1)
elif response.status_code == 400:
print(f"Error: {response.json().get('detail', 'Bad request')}")
sys.exit(1)
response.raise_for_status()
data = response.json()
print(f"Run started: {data['run_id']}")
return data["run_id"]
def poll_for_completion(run_id: str, poll_interval: int = 5) -> dict:
"""
Poll the run status until completion.
Args:
run_id: The run ID to poll
poll_interval: Seconds between polls
Returns:
Final run status data
"""
print("Waiting for completion", end="", flush=True)
while True:
response = requests.get(
f"{BASE_URL}/runs/{run_id}",
headers=get_headers(),
)
response.raise_for_status()
data = response.json()
status = data["status"]
progress = data.get("progress")
if status == "succeeded":
print(" Done!")
return data
elif status == "failed":
print(" Failed!")
print(f"Error: {data.get('error', 'Unknown error')}")
if data.get("failed_tools"):
print(f"Failed tools: {', '.join(data['failed_tools'])}")
sys.exit(1)
elif status == "partially_failed":
print(" Completed with warnings")
if data.get("failed_tools"):
print(f"Warning: Some tools failed: {', '.join(data['failed_tools'])}")
return data
# Show progress
if progress:
print(f" {progress:.0%}", end="", flush=True)
else:
print(".", end="", flush=True)
time.sleep(poll_interval)
def get_artifact_url(run_id: str) -> str:
"""
Get the URL for the generated brief artifact.
Args:
run_id: The completed run ID
Returns:
URL to download the HTML brief
"""
response = requests.get(
f"{BASE_URL}/runs/{run_id}/artifacts",
headers=get_headers(),
)
response.raise_for_status()
data = response.json()
for artifact in data.get("artifacts", []):
if artifact["artifact_type"] == "html":
return artifact["url"]
raise ValueError("No HTML artifact found")
def download_brief(artifact_url: str) -> str:
"""
Download the brief content.
Args:
artifact_url: Relative URL from artifacts endpoint
Returns:
HTML content of the brief
"""
# Construct full URL (artifact_url is relative)
full_url = f"https://phoenix.hginsights.com/api/agents{artifact_url}"
response = requests.get(full_url, headers=get_headers())
response.raise_for_status()
return response.text
def generate_brief(
domain: str,
depth: Literal["quick", "standard", "deep"] = "standard",
output_file: str | None = None,
) -> str:
"""
Generate an account research brief for a company.
This is the main function that orchestrates the entire workflow:
1. Start a research run
2. Poll until completion
3. Download the generated brief
Args:
domain: Target company domain
depth: Research depth level
output_file: Optional file path to save the brief
Returns:
HTML content of the generated brief
"""
# Step 1: Start the run
run_id = start_research_run(domain, depth)
# Step 2: Wait for completion
run_data = poll_for_completion(run_id)
# Step 3: Get artifact URL
artifact_url = run_data.get("artifact_url")
if not artifact_url:
artifact_url = get_artifact_url(run_id)
# Step 4: Download the brief
print("Downloading brief...")
brief_content = download_brief(artifact_url)
# Step 5: Save to file if requested
if output_file:
with open(output_file, "w", encoding="utf-8") as f:
f.write(brief_content)
print(f"Brief saved to: {output_file}")
# Print summary
print("\n" + "=" * 50)
print("RESEARCH BRIEF GENERATED SUCCESSFULLY")
print("=" * 50)
print(f"Company: {domain}")
print(f"Run ID: {run_id}")
if run_data.get("cost_summary"):
cost = run_data["cost_summary"]
print(f"Credits used: {cost.get('total_credits', 'N/A')}")
print("=" * 50)
return brief_content
def main():
"""CLI entry point."""
parser = argparse.ArgumentParser(
description="Generate Phoenix Account Research Briefs",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python generate_brief.py salesforce.com
python generate_brief.py --depth quick hubspot.com
python generate_brief.py --depth deep --output cisco_brief.html cisco.com
Depth levels:
quick - Executive summary (1-2 minutes)
standard - Comprehensive brief (2-4 minutes)
deep - In-depth research (4-8 minutes)
""",
)
parser.add_argument(
"domain",
help="Target company domain (e.g., salesforce.com)",
)
parser.add_argument(
"--depth",
choices=["quick", "standard", "deep"],
default="standard",
help="Research depth level (default: standard)",
)
parser.add_argument(
"--output", "-o",
help="Output file path for the HTML brief",
)
args = parser.parse_args()
# Generate the brief
brief = generate_brief(
domain=args.domain,
depth=args.depth,
output_file=args.output,
)
# If no output file, print a preview
if not args.output:
print("\nBrief preview (first 500 chars):")
print("-" * 40)
print(brief[:500] + "...")
print("-" * 40)
print("\nTip: Use --output brief.html to save the full brief")
if __name__ == "__main__":
main()
Usage Examples
Basic Usage
Generate a standard-depth brief for a company:
python generate_brief.py salesforce.com
Output:
Starting research for salesforce.com (depth: standard)...
Run started: 550e8400-e29b-41d4-a716-446655440000
Waiting for completion.... 45%.... 78%.... Done!
Downloading brief...
==================================================
RESEARCH BRIEF GENERATED SUCCESSFULLY
==================================================
Company: salesforce.com
Run ID: 550e8400-e29b-41d4-a716-446655440000
Credits used: 7.5
==================================================
Quick Research
Get a fast executive summary:
python generate_brief.py --depth quick hubspot.com
Deep Research with Output File
Generate a comprehensive brief and save to file:
python generate_brief.py --depth deep --output cisco_brief.html cisco.com
Then open cisco_brief.html in your browser to view the formatted brief.
Understanding the Response
Run Status Values
| Status | Description |
|---|---|
queued | Run accepted, waiting to start |
running | Research in progress |
succeeded | Completed successfully |
partially_failed | Completed with some data sources unavailable |
failed | Research failed |
Research Depth Levels
| Depth | Duration | Best For |
|---|---|---|
quick | 1-2 min | Quick prospect qualification |
standard | 2-4 min | Sales call preparation |
deep | 4-8 min | Strategic account planning |
Brief Contents
The generated HTML brief includes:
- Executive Summary: Company overview and key facts
- Firmographic Profile: Size, revenue, industry, location
- Technology Stack: Current tools and platforms
- Spending Analysis: IT and cloud spend breakdown
- Key Contacts: Decision makers and stakeholders
- Recommendations: Talking points and next steps
Error Handling
The script handles common errors:
# API key not set
if response.status_code == 401:
print("Error: Invalid API key")
# Invalid input
if response.status_code == 400:
print(f"Error: {response.json().get('detail')}")
# Run failed
if status == "failed":
print(f"Error: {data.get('error')}")
print(f"Failed tools: {data.get('failed_tools')}")
Programmatic Integration
Use generate_brief() in your own code:
from generate_brief import generate_brief
# Generate brief and get HTML content
html_content = generate_brief(
domain="acme.com",
depth="standard",
output_file="acme_brief.html",
)
# Process the HTML content
print(f"Brief length: {len(html_content)} characters")
Batch Processing
Process multiple companies:
import csv
from generate_brief import generate_brief
companies = ["salesforce.com", "hubspot.com", "zendesk.com"]
for domain in companies:
try:
generate_brief(
domain=domain,
depth="quick",
output_file=f"briefs/{domain.replace('.', '_')}.html",
)
except Exception as e:
print(f"Failed for {domain}: {e}")
Next Steps
- Account Research Brief Guide - Detailed agent documentation
- API Reference - Complete endpoint documentation
- Company Analysis Example - Using individual MCP tools