ElevenLabs Agents
Use Runway Characters with an ElevenLabs agent when you already have one and want a custom Character to deliver it. ElevenLabs handles speech recognition, reasoning, and text-to-speech; Runway lip-syncs that audio to your Character over WebRTC and does not run its own conversation model for the session.
Before you start
Section titled “Before you start”You’ll need:
- A Runway API key
- A custom Character your API key owns and is ready to use
- An ElevenLabs API key with ElevenAgents read permission
- An ElevenLabs agent with Advanced → User input audio format → PCM 16000Hz
Set these server-side environment variables (see the Next.js example for a full .env.example):
RUNWAYML_API_SECRET=...RUNWAY_AVATAR_ID=...ELEVENLABS_API_KEY=...ELEVENLABS_AGENT_ID=...-
Install the Characters SDK
Terminal window npm install @runwayml/avatars @runwayml/avatars-reactServer helpers such as
createElevenLabsSessionlive in@runwayml/avatars/api. The React package re-exports them for convenience, but your API route should import from the core package. -
Create a server route
createElevenLabsSessionfrom@runwayml/avatars/apifetches an ElevenLabs signed URL, creates a Runway session withintegration: { type: "elevenlabs", signedUrl }, polls untilREADY, and returnssessionId,sessionKey,avatarId, andbaseUrlforAvatarCall.app/api/avatar/connect/route.ts // app/api/avatar/connect/route.tsimport { createElevenLabsSession } from '@runwayml/avatars/api';export async function POST() {const session = await createElevenLabsSession({runwayApiSecret: process.env.RUNWAYML_API_SECRET!,avatarId: process.env.RUNWAY_AVATAR_ID!,elevenLabsApiKey: process.env.ELEVENLABS_API_KEY!,elevenLabsAgentId: process.env.ELEVENLABS_AGENT_ID!,});return Response.json(session);}Also exported from
@runwayml/avatars-react/apiif you already depend on the React package only.Without the SDK, run the same three steps manually: fetch the signed URL, create the session, poll until ready. See Building your integration for session lifecycle patterns.
-
Connect from the client
Pass the JSON from your connect route to
AvatarCall:'use client';import { AvatarCall } from '@runwayml/avatars-react';import '@runwayml/avatars-react/styles.css';export function Conversation({ sessionId, sessionKey, avatarId, baseUrl }) {return (<AvatarCallavatarId={avatarId}sessionId={sessionId}sessionKey={sessionKey}baseUrl={baseUrl}/>);}createElevenLabsSessionechoesavatarIdandbaseUrlso you can forward the server response without rebuilding those fields. -
Test it
Trigger your connect route, then confirm Character video appears while your ElevenLabs agent responds. Mic audio goes Runway → worker → ElevenLabs; agent audio drives lip sync on the way back.
Full working app: Next.js + ElevenLabs example.
End sessions promptly
Section titled “End sessions promptly”Runway bills realtime Character sessions while the Character worker is active. End calls via AvatarCall onEnd and handle errors on your connect route so sessions are not left running.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Fix |
|---|---|
404 Could not find Avatar | Use a Character ID scoped to the same API key (see Custom Avatars) |
401 or inactive API key | Check your Runway API key in the Developer Portal |
Session stuck NOT_READY | Retry; confirm your environment has the ElevenLabs integration deployed |
| Silent agent / no audio | Set PCM 16000Hz input format on the ElevenLabs agent |
personality… cannot be used with integration | Remove personality, startScript, and tools from the session create request |
| ElevenLabs signed URL fails | Check xi-api-key, agent ID, and ElevenAgents read permission |
See Troubleshooting for general Characters SDK debugging.