npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@elevenlabs/client

v1.23.0

Published

ElevenLabs JavaScript Client Library

Readme

hero

ElevenAgents TypeScript SDK

Build multimodal agents with ElevenAgents.

A TypeScript / JavaScript client library for using ElevenAgents, or as a base for framework-specific libraries. If you're using React, consider using @elevenlabs/react instead.

LOGO Discord Twitter

Installation

npm install @elevenlabs/client

Quick Start

import { Conversation } from "@elevenlabs/client";

const conversation = await Conversation.startSession({
  agentId: "agent_7101k5zvyjhmfg983brhmhkd98n6", // replace with your agent's ID
  onConnect: ({ conversationId }) => {
    console.log("Connected:", conversationId);
  },
  onDisconnect: () => {
    console.log("Disconnected");
  },
  onMessage: message => {
    console.log("Message:", message);
  },
  onAgentResponseCorrection: ({
    original_agent_response,
    corrected_agent_response,
  }) => {
    console.log(
      "Agent response corrected:",
      original_agent_response,
      "->",
      corrected_agent_response
    );
  },
  onError: message => {
    console.error("Error:", message);
  },
});

// End the conversation
await conversation.endSession();

Documentation

For the full API reference including connection types, client tools, conversation overrides, and more, see the JavaScript SDK documentation.

Entrypoints

| Path | Stability | | ----------------------------------- | ------------------------------ | | @elevenlabs/client | Public, semver-stable | | @elevenlabs/client/internal | Internal, no semver guarantees | | @elevenlabs/client/internal/unity | Internal, no semver guarantees | | @elevenlabs/client/worklets/* | Public, semver-stable |

Self-hosting AudioWorklets under a strict CSP

By default, Conversation and Scribe load their AudioWorklet processors from blob:/data: URLs generated at runtime. AudioWorklet.addModule() requests are governed by the script-src-elem directive (falling back to script-src), so a strict CSP that only allows script-src 'self' will reject those URLs.

To support strict CSPs, the raw processor sources are published as static assets under @elevenlabs/client/worklets/*. Copy the ones you need into your own static assets (e.g. via a build step or bundler copy plugin) and serve them same-origin, then point the SDK at them:

import { Conversation } from "@elevenlabs/client";

const conversation = await Conversation.startSession({
  agentId: "agent_...",
  workletPaths: {
    rawAudioProcessor: "/vendor/elevenlabs/raw-audio-processor.js",
    audioConcatProcessor: "/vendor/elevenlabs/audio-concat-processor.js",
  },
});
import { Scribe } from "@elevenlabs/client";

const connection = Scribe.connect({
  token: "...",
  modelId: "scribe_v2_realtime",
  microphone: {
    workletPaths: {
      scribeAudioProcessor: "/vendor/elevenlabs/scribe-audio-processor.js",
    },
  },
});

Approving MCP tool calls

When an agent's MCP tool requires approval, the server sends an mcp_tool_call event in the awaiting_approval state and waits for a decision. Pass onMCPToolApprovalRequest to decide, and the SDK puts the result on the wire for you:

import { Conversation } from "@elevenlabs/client";

const conversation = await Conversation.startSession({
  agentId: "agent_...",
  onMCPToolApprovalRequest: async toolCall =>
    window.confirm(
      `Allow ${toolCall.tool_name} from ${toolCall.service_id}?\n\n` +
        JSON.stringify(toolCall.parameters, null, 2)
    ),
});

The handler resolves to true to allow the call and false to deny it. Rejecting, or resolving to anything that is not a boolean, is reported through onError and treated as a denial, so a broken handler can never let a tool call through.

Each tool_call_id is answered at most once. If the server moves a call out of awaiting_approval before the handler resolves — its approval window elapsed, for example — or the session ends, the late decision is dropped rather than sent, and onError reports it. The handler's second argument carries an AbortSignal for that case, so approval UI can dismiss itself instead of waiting on a decision that no longer matters:

const conversation = await Conversation.startSession({
  agentId: "agent_...",
  onMCPToolApprovalRequest: (toolCall, { signal }) =>
    new Promise(resolve => {
      const dialog = showApprovalDialog(toolCall, resolve);
      signal.addEventListener("abort", () => dialog.close());
    }),
});

onMCPToolCall still fires for every state, including awaiting_approval, so existing observability code is unaffected. Handling approvals yourself with onMCPToolCall plus conversation.sendMCPToolApprovalResult() also keeps working — the handler is opt-in.

Development

Please refer to the README.md file in the root of this repository.

Contributing

Please create an issue first to discuss the proposed changes. Any contributions are welcome!

Remember, if merged, your code will be used as part of a MIT licensed project. By submitting a Pull Request, you are giving your consent for your code to be integrated into this library.