Post-Call Analytics

View as Markdown

After each call, the platform automatically generates analytics. You can configure what data to extract.

What Gets Generated

Every completed call includes postCallAnalytics:

FieldDescription
summaryAI-generated call summary
dispositionMetricsExtracted data points you configure

Accessing Post-Call Data

1from smallestai.atoms.helpers import CallAnalytics
2
3call = CallAnalytics() # reads SMALLEST_API_KEY from the environment
4
5# Get call details
6details = call.get_call("CALL-1768842587790-69eb58")
7data = details["data"]
8
9# Access analytics
10analytics = data.get("postCallAnalytics", {})
11
12print(f"Summary: {analytics.get('summary')}")
13
14for metric in analytics.get("dispositionMetrics", []):
15 print(f" {metric['identifier']}: {metric['value']}")
16 print(f" Confidence: {metric['confidence']}")
17 print(f" Reasoning: {metric['reasoning']}")

Example Output

Summary: The call involved an agent reaching out to discuss AI products.
The user expressed interest and provided their name.
user_interested: yes
Confidence: 1
Reasoning: The user explicitly stated 'I am interested'.
user_name: John
Confidence: 1
Reasoning: The user provided their name directly.

Configuring Disposition Metrics

Use set_post_call_config() to define what data to extract:

1from smallestai.atoms.helpers import CallAnalytics
2
3call = CallAnalytics()
4
5call.set_post_call_config(
6 agent_id="696e655577e1d88ff54b4fbf",
7 summary_prompt="Summarize this sales call briefly.",
8 disposition_metrics=[
9 {
10 "identifier": "user_interested",
11 "dispositionMetricPrompt": "Was the user interested? yes, no, or unclear",
12 "dispositionMetricType": "ENUM",
13 "choices": ["yes", "no", "unclear"]
14 },
15 {
16 "identifier": "user_name",
17 "dispositionMetricPrompt": "What is the user's name? Return 'unknown' if not mentioned.",
18 "dispositionMetricType": "STRING"
19 }
20 ]
21)

Disposition Metric Types

TypeDescriptionRequires choices
STRINGFree text (names, notes)No
BOOLEANYes/No valuesNo
INTEGERNumeric values (ratings)No
ENUMSelection from predefined listYes
DATETIMEDate/time valuesNo

Metric Configuration Schema

Each disposition metric requires:

FieldRequiredDescription
identifierYesUnique ID (e.g., customer_status)
dispositionMetricPromptYesQuestion to extract this data
dispositionMetricTypeYesSTRING, BOOLEAN, INTEGER, ENUM, DATETIME
choicesFor ENUMList of allowed values

Getting Current Configuration

1config = call.get_post_call_config("696e655577e1d88ff54b4fbf")
2
3print("Configured metrics:")
4for metric in config["data"].get("dispositionMetrics", []):
5 print(f" {metric['identifier']}: {metric['dispositionMetricType']}")

Complete Example: Sales Call Analytics

1import time
2from smallestai import SmallestAI
3from smallestai.atoms.helpers import Audience, Campaign, CallAnalytics
4
5client = SmallestAI()
6call = CallAnalytics()
7audience = Audience()
8campaign = Campaign()
9
10# 1. Create agent
11agent = client.atoms.agents.create_agent(
12 name=f"Sales Agent {int(time.time())}",
13 global_prompt="You are a sales agent. Ask if interested and get their name.",
14 description="Testing disposition metrics"
15)
16agent_id = agent.data
17
18# 2. Configure disposition metrics
19call.set_post_call_config(
20 agent_id=agent_id,
21 summary_prompt="Summarize this sales call briefly.",
22 disposition_metrics=[
23 {
24 "identifier": "user_interested",
25 "dispositionMetricPrompt": "Was the user interested? yes, no, or unclear",
26 "dispositionMetricType": "ENUM",
27 "choices": ["yes", "no", "unclear"]
28 },
29 {
30 "identifier": "user_name",
31 "dispositionMetricPrompt": "What is the user's name? Return 'unknown' if not mentioned.",
32 "dispositionMetricType": "STRING"
33 }
34 ]
35)
36
37# 3. Create audience and campaign
38phones = client.atoms.phone_numbers.list()
39phone_id = phones.data[0].id
40
41aud = audience.create(
42 name=f"Test Audience {int(time.time())}",
43 phone_numbers=["+916366821717"],
44 names=[("Test", "User")]
45)
46audience_id = aud["data"]["_id"]
47
48camp = campaign.create(
49 name=f"Analytics Test {int(time.time())}",
50 agent_id=agent_id,
51 audience_id=audience_id,
52 phone_ids=[phone_id]
53)
54campaign_id = camp["data"]["_id"]
55
56# 4. Start campaign
57campaign.start(campaign_id)
58print("Call in progress...")
59
60# 5. Wait for completion
61time.sleep(60)
62
63# 6. Get call with analytics
64calls = call.get_calls(agent_id=agent_id, limit=1)
65call_id = calls["data"]["logs"][0]["callId"]
66
67details = call.get_call(call_id)
68data = details["data"]
69
70# 7. Display results
71print(f"\nCall Status: {data['status']}")
72print(f"Duration: {data['duration']}s")
73
74print("\nTranscript:")
75for line in data.get("transcript", []):
76 print(f" [{line['role'].upper()}]: {line['content']}")
77
78analytics = data.get("postCallAnalytics", {})
79if analytics:
80 print(f"\nSummary: {analytics.get('summary')}")
81 print("\nDisposition Metrics:")
82 for m in analytics.get("dispositionMetrics", []):
83 print(f" {m['identifier']}: {m['value']}")
84 print(f" Confidence: {m['confidence']}")
85 print(f" Reasoning: {m['reasoning']}")
86
87# 8. Cleanup
88campaign.delete(campaign_id)
89audience.delete(audience_id)
90client.atoms.agents.archive_agent(agent_id)

SDK Reference

MethodDescription
call.get_post_call_config(agent_id)Get agent’s analytics config
call.set_post_call_config(agent_id, ...)Configure summary and disposition metrics
call.get_call(call_id)Get call details with analytics
call.get_calls(agent_id=..., limit=...)List calls with optional filters

Tips

Disposition metrics are extracted after the call ends, typically within 10-30 seconds. The AI analyzes the transcript based on your configured prompts.

Be specific and direct. Instead of “What happened?”, use:

  • “Did the customer agree to schedule a follow-up? Answer yes or no.”
  • “What is the customer’s email? Return ‘not provided’ if not mentioned.”

Yes. New calls use the updated config. Existing calls keep their original analytics.

The metric will have an empty or null value. Specify fallback behavior in your prompts, like “Return ‘unknown’ if not mentioned.”