Skip to main content

Call Intelligence

Anima stores voice call records under the same agent identity as email, SMS, and vault events. Use call intelligence to monitor calls while they run, fetch the finalized transcript after they end, and read post-call artifacts such as summaries, scores, recordings, and security scans when enabled for your account.

Start a call

from anima import Anima

anima = Anima(api_key="ak_...")

call = anima.calls.create(
    agent_id="AGENT_ID",
    to="+15551234567",
    tier="basic",
    greeting="Hi, this is my Anima agent. I am calling from my own number.",
)

print(call.call_id, call.state)
import { Anima } from "@anima-labs/sdk";

const anima = new Anima({ apiKey: "ak_..." });

const call = await anima.calls.create({
  agentId: "AGENT_ID",
  to: "+15551234567",
  tier: "basic",
  greeting: "Hi, this is my Anima agent. I am calling from my own number.",
});

console.log(call.callId, call.state);

Stream live transcription

Use the voice WebSocket for live call events and bidirectional control.
conn = anima.calls.connect(agent_id="AGENT_ID")

def on_message(message: dict):
    if message.get("type") == "call.transcription":
        payload = message.get("data", message)
        print(payload.get("text"))

conn.on_message(on_message)
conn.create_call(
    "+15551234567",
    tier="basic",
    greeting="Hi, this is my Anima agent.",
)
const conn = anima.calls.connect({ agentId: "AGENT_ID" });

conn.on("message", (message) => {
  if (message.type === "call.transcription") {
    console.log(message.data?.text);
  }
});

conn.createCall("+15551234567", {
  tier: "basic",
  greeting: "Hi, this is my Anima agent.",
});

Fetch the transcript

After the call ends, fetch the finalized transcript.
transcript = anima.calls.get_transcript(call.call_id)

for segment in transcript.segments:
    print(f"[{segment.start_time}s] {segment.speaker}: {segment.text}")
const transcript = await anima.calls.getTranscript(call.callId);

for (const segment of transcript.segments) {
  console.log(`[${segment.startTime}s] ${segment.speaker}: ${segment.text}`);
}

List and inspect calls

calls = anima.calls.list(agent_id="AGENT_ID", limit=20)
for item in calls["calls"]:
    print(item.id, item.state, item.duration_seconds)

detail = anima.calls.get(call.call_id)
print(detail.state, detail.started_at, detail.ended_at)
const calls = await anima.calls.list({ agentId: "AGENT_ID", limit: 20 });
for (const item of calls.calls) {
  console.log(item.id, item.state, item.durationSeconds);
}

const detail = await anima.calls.get(call.callId);
console.log(detail.state, detail.startedAt, detail.endedAt);

Post-call intelligence endpoints

Some post-call artifacts are exposed as REST endpoints and MCP tools even when a specific SDK helper is not present yet.
curl https://api.useanima.sh/v1/voice/calls/CALL_ID/transcript \
  -H "Authorization: Bearer ak_..."

curl https://api.useanima.sh/v1/voice/calls/CALL_ID/summary \
  -H "Authorization: Bearer ak_..."

curl https://api.useanima.sh/v1/voice/calls/CALL_ID/score \
  -H "Authorization: Bearer ak_..."

curl https://api.useanima.sh/v1/voice/calls/CALL_ID/recording \
  -H "Authorization: Bearer ak_..."

curl https://api.useanima.sh/v1/voice/calls/CALL_ID/security \
  -H "Authorization: Bearer ak_..."
MCP equivalents include phone_call_get, phone_call_transcript_get, phone_call_recording_get, voice_get_summary, voice_get_score, and voice_get_security_scan depending on the connected MCP server version.

Guardrails

Outbound calls are gated server-side before dialing. The API enforces plan eligibility, TCPA consent posture, Reassigned Numbers Database checks, time-of-day windows, and per-tier call caps. If one of those checks fails, the call is rejected before reaching the telephony provider.

Next steps