Skip to main content

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

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

StatusDescription
queuedRun accepted, waiting to start
runningResearch in progress
succeededCompleted successfully
partially_failedCompleted with some data sources unavailable
failedResearch failed

Research Depth Levels

DepthDurationBest For
quick1-2 minQuick prospect qualification
standard2-4 minSales call preparation
deep4-8 minStrategic 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