Skip to main content

Account Research Brief Example

This example shows how to use the HG 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​

  • An HG Insights API key (get one from Settings > API Keys)
  • Python 3.8+ with the requests library

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
"""
HG Insights Account Research Brief Generator

This script demonstrates how to use the HG 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 HG Insights 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​