Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.inference.net/llms.txt

Use this file to discover all available pages before exploring further.

Catalyst instruments the ElevenLabs Agents SDK in TypeScript and Python. Initialize tracing before starting a conversation so the SDK conversation lifecycle and client-tool callbacks are patched before the session begins. Use this guide for applications that use @elevenlabs/client or the Python elevenlabs.conversational_ai.conversation APIs.

What Is Captured

  • One AGENT span named ElevenLabs Conversation for each conversation session
  • User and agent transcript messages as OpenInference message attributes
  • ElevenLabs metadata such as agent ID, conversation ID, user ID, auth mode, and text-only mode
  • TOOL child spans for registered client tools, including tool name, arguments, result, and errors
  • Error status and exception details when session startup, tool execution, or shutdown fails
Catalyst preserves the ElevenLabs agent identifier as elevenlabs.agent_id. When you need a stable cross-provider grouping key for the Agents dashboard, wrap the conversation lifecycle in agentSpan() / agent_span() and set the canonical agent.id yourself.

Install

bun add @inference/tracing @elevenlabs/client

TypeScript Conversation Session

Pass the ElevenLabs SDK namespace into setup() before calling Conversation.startSession().
TypeScript
import * as ElevenLabs from "@elevenlabs/client";
import { Conversation } from "@elevenlabs/client";
import { setup } from "@inference/tracing";

const tracing = await setup({
  serviceName: "voice-support",
  modules: { elevenlabs: ElevenLabs },
});

const conversation = await Conversation.startSession({
  agentId: process.env.ELEVENLABS_AGENT_ID!,
  textOnly: true,
  userId: "user_123",
  clientTools: {
    lookupAppointment: async ({ user_id }) => {
      return JSON.stringify({
        user_id,
        starts_at: "2026-04-29T10:30:00Z",
      });
    },
  },
  onMessage: (message) => {
    console.log(message.role, message.message);
  },
});

conversation.sendUserMessage("When is my next appointment?");
await conversation.endSession();
await tracing.shutdown();
For private agents, use the same tracing setup and pass the signedUrl or conversationToken options that your ElevenLabs app already uses. Catalyst keeps the same outer ElevenLabs Conversation span shape.

Python Conversation Session

Call setup() before constructing and starting the Conversation. This patches the installed ElevenLabs SDK and records the session lifecycle automatically.
Python
import os

from elevenlabs.client import ElevenLabs
from elevenlabs.conversational_ai.conversation import ClientTools, Conversation
from inference_catalyst_tracing import setup

tracing = setup(service_name="voice-support")

client = ElevenLabs(api_key=os.environ.get("ELEVENLABS_API_KEY"))
client_tools = ClientTools()
client_tools.register(
    "lookupAppointment",
    lambda params: {
        "user_id": params["user_id"],
        "starts_at": "2026-04-29T10:30:00Z",
    },
)

conversation = Conversation(
    client,
    os.environ["ELEVENLABS_AGENT_ID"],
    user_id="user_123",
    requires_auth=bool(os.environ.get("ELEVENLABS_API_KEY")),
    audio_interface=None,
    client_tools=client_tools,
    callback_agent_response=lambda text: print(f"Agent: {text}"),
    callback_user_transcript=lambda text: print(f"User: {text}"),
)

conversation.start_session()
conversation.send_user_message("When is my next appointment?")
conversation.end_session()
conversation_id = conversation.wait_for_session_end()
print(f"Conversation ID: {conversation_id}")

tracing.shutdown()
audio_interface=None keeps the example text-only. For voice conversations, use your normal ElevenLabs audio interface; the instrumentation records the same conversation span and transcript callbacks.

Stable Agent Identity

import { agentSpan } from "@inference/tracing";

await agentSpan(
  tracing.tracer,
  {
    agentId: "voice-support-agent",
    agentName: "Voice Support Agent",
    spanName: "voice-support.run",
    sessionId: "conversation-voice-1",
    role: "support",
    system: "elevenlabs",
  },
  async (span) => {
    span.setInput("When is my next appointment?");
    const conversation = await Conversation.startSession({
      agentId: process.env.ELEVENLABS_AGENT_ID!,
      textOnly: true,
      userId: "user_123",
    });
    conversation.sendUserMessage("When is my next appointment?");
    await conversation.endSession();
    span.setOutput("conversation ended");
  },
);

Verify In Catalyst

Filter traces by service.name=voice-support. A successful session should show an ElevenLabs Conversation AGENT span with nested TOOL spans when your agent calls lookupAppointment. When you add the wrapper above, the trace also has an outer AGENT span with your stable agent.id. For short-lived scripts, always call tracing.shutdown() before process exit so batched spans are flushed to Catalyst.