Skip to main content
These are official instructions from Akapulu Labs, published at https://docs.akapulu.com/agent-setup.md. Run the commands in this file. User step means ask the human to do it. Do not skip the asks. Do not assume their answers.

What Akapulu Labs is

Akapulu Labs builds live AI avatars — a talking face (lip-synced video + voice) on a real-time call. Two product shapes:
  • A hosted link — a public page Akapulu Labs hosts. Open the URL, click Start Call. No bot to run; the page never sees your API key.
  • Your own avatar chat — you run a voice pipeline (speech-to-speech, or STT → model → TTS, or anything that produces assistant audio). Akapulu Labs adds the avatar video on top in a Daily room you create and own.
Calls use conversation minutes. Pricing: https://akapulu.com/pricing/ Full docs: https://docs.akapulu.com

1. Install skills and docs MCP

Claude Code

User step. Reload skills if they do not appear. Confirm akapulu-docs is connected.

Codex

User step. Reload if prompted. Confirm the MCP is connected.

Cursor and other agents

Add the docs MCP to ~/.cursor/mcp.json (or this project’s .cursor/mcp.json). Merge into mcpServers if the file already exists:
User step. Reload the agent. In Cursor, enable akapulu-docs under Settings → MCP.

2. Do they have an account?

User step. Ask: do you already have an Akapulu Labs account?
  • No. Ask them to open https://akapulu.com/, sign up, then come back here when they are signed in.
  • Yes. Continue.
Do not continue past this section until they have an account (or confirm they are signed in).

3. Quick talk, or build their own chat?

User step. Ask which they want:
  1. A super-quick link — talk to an avatar soon, without building a bot.
  2. Build their own custom avatar chat — a Pipecat voice pipeline with the Akapulu Labs avatar in their app.
Wait for the answer. Then follow only that branch.
User step. Ask how they want that link made:
  1. You create it with their API key — you call the API and hand them a URL to paste in a browser.
  2. They use the Akapulu Labs UI — in-app onboarding / Hosted links in the dashboard.
A hosted link is a public page Akapulu Labs hosts. You create the row; they open url and click Start Call. Docs: Hosted links, Create a hosted link. Defaults for this path (do not ask):
  • Avatar: Clara — avatar_id 1f777f64-3758-4a7d-9cbc-c64ae654f7d1
  • This is AI (show_ai_label): false
User step. Guide them to create an API key at https://akapulu.com/api-keys/. Then instruct them to activate AKAPULU_API_KEY in this environment (however this project already loads env vars). Do not ask them to paste the key into chat.
Wait until AKAPULU_API_KEY is available in this environment.
User step. Ask what kind of chat they want — what the avatar should talk about, tone, goal. Then you write a good system_prompt from their answer.
When you write that prompt:
  • The model’s replies are spoken by TTS on the call.
  • Do not tell the model to output markdown, lists of symbols, code, URLs spelled letter-by-letter, or anything awkward to speak aloud.
  • Prefer short, conversational sentences.
Then POST /api/hosted-links/ with Bearer auth and a JSON body that is exactly:
Give them the url from the response.
User step. Open that url in a browser and click Start Call.

Path 1b: Onboarding in the Akapulu Labs UI

No API key for this path.
User step. Open https://akapulu.com/ signed in. New accounts get the hosted-link tour. Create a hosted link (avatar, system prompt, This is AI), save, open the URL, click Start Call.
If the tour is already finished, they can still create a link under Hosted links. Guide: Hosted links.

Path 2: Build their own custom avatar chat

Before wiring code, situate Daily, the voice bot, the Akapulu Labs worker, and AkapuluAvatar.

Names (use these)

  • Voice bot — their Pipecat process (or other voice pipeline). It hears the visitor and decides what to say. It produces assistant audio.
  • Akapulu Labs worker — Akapulu Labs’ avatar process. It joins the Daily room and publishes the lip-synced face and the played audio.
  • AkapuluAvatar — a Pipecat processor from pipecat-akapulu. It runs inside the voice bot, after the assistant audio, and sends that audio to Akapulu Labs so the Akapulu Labs worker can speak it on the face. It is not the worker itself.
  • create_akapulu_call: a function in that same package. Their server calls it before the bot starts. It creates the private Daily room, mints the three meeting tokens, and starts the live session. The code is on Your bot.

What Daily is (and why it matters here)

Daily is a real-time WebRTC platform: rooms, meeting tokens, and media (audio/video) between participants in a browser or a process. Akapulu Labs uses Daily for live calls. The face and the played audio show up as a participant in a Daily room. On the plugin / voice-bot path, they create that room (not Akapulu Labs). On a hosted link, Akapulu Labs creates the room for them. What Daily gives them on the plugin path:
  • A private room URL everyone joins
  • Separate meeting tokens so the browser, the voice bot, and the Akapulu Labs worker can each join safely
  • The wire that carries the visitor’s mic to the voice bot, and the Akapulu Labs worker’s face + voice back to the visitor
What Akapulu Labs adds on top of that room:
  • The Akapulu Labs worker, started by the live-session API after they already have room_url and avatar_token
  • AkapuluAvatar in the voice bot, which forwards assistant audio to that worker
Their voice pipeline can be speech-to-speech, STT → model → TTS, or anything else that produces assistant audio. Akapulu Labs does not replace that pipeline. AkapuluAvatar sits after the audio they want the avatar to speak. Recommended shape in Pipecat:
  1. Build (or keep) the voice pipeline as usual until there are assistant audio frames.
  2. On their server, call create_akapulu_call before the bot starts. It reads DAILY_API_KEY and AKAPULU_API_KEY, creates the private Daily room, mints the three meeting tokens, and POST /api/live-sessions/. It returns the room URL, the bot token, the browser token, and session_id. The room lasts two hours unless they pass room_exp_secs. A server that already has a Daily room skips it, mints the worker token, and makes that POST itself. The code is on Your bot.
  3. Put AkapuluAvatar in the voice bot pipeline after that assistant audio, with session_id.
  4. Join Daily with the voice bot using the voice-bot token. Leave voice-bot audio out and video out off. The voice bot’s job is to send the assistant audio to the Akapulu Labs worker. The worker joins the call as a Daily participant and publishes the audio and the video. When the participant named Avatar joins, the voice bot calls update_subscriptions and sets that microphone to unsubscribed. The browser stays subscribed to it. The code is on Your bot.
  5. Join the browser with the browser token.
If they already have a voice bot: keep their pipeline. create_akapulu_call creates the Daily room and the live session. The voice bot sends the assistant audio to the Akapulu Labs worker. The worker joins the call as a Daily participant and publishes the audio and the video, so voice-bot audio out and video out stay off. Unsubscribe the voice bot from the Avatar microphone when that participant joins. The code is on Your bot. Install: uv add pipecat-akapulu or pip install pipecat-akapulu. The public example already depends on it.

Path 2 ask: the public example, or their own voice bot?

User step. Ask: are you okay using the public example? Behind the scenes it runs Deepgram Flux, OpenAI (gpt-5.4-mini), and Cartesia Sonic 3.6.

Path 2a: Yes — use the example

The public example (akapulu-examples) is a local server, a browser page, and a voice bot. Deepgram Flux (flux-general-multi) hears the caller. OpenAI gpt-5.4-mini speaks, with reasoning off. Cartesia Sonic 3.6 speaks each finished sentence. It creates the Daily room, calls live-sessions (starts the Akapulu Labs worker), and runs AkapuluAvatar inside that voice bot.
User step.
  • Create an Akapulu API key at https://akapulu.com/api-keys/ if they do not have one. Instruct them to activate AKAPULU_API_KEY in this environment (do not paste the key into chat).
  • They also need a Daily API key as DAILY_API_KEY.
  • They also need OPENAI_API_KEY, DEEPGRAM_API_KEY, and CARTESIA_API_KEY. If one of those is not already in this environment, instruct them to activate it here.
Wait until those env vars are set. Then clone https://github.com/Akapulu/akapulu-examples and follow its README. The example already uses Clara, leaves This is AI off, and calls the Akapulu Labs production API. They set DAILY_API_KEY, AKAPULU_API_KEY, OPENAI_API_KEY, DEEPGRAM_API_KEY, and CARTESIA_API_KEY. Run the server, open the local page, start a call. That is their starter app.

Path 2b: No — bring their own voice pipeline

Still clone https://github.com/Akapulu/akapulu-examples as a reference (room + tokens + live session + page). Then guide them through their own Pipecat voice bot with AkapuluAvatar inside it (talking to the Akapulu Labs worker).
User step. Activate AKAPULU_API_KEY and DAILY_API_KEY in this environment the same way as above. Do not paste secrets into chat.
Call architecture (explain this slowly, with bullets)
Remind them of the Daily / AkapuluAvatar section above. Then spell out the three participants in the room they create:
  • Browser — the person on the call. Joins with a browser meeting token they mint.
  • Voice bot. Their voice pipeline (Pipecat or otherwise). Joins with a voice-bot meeting token. Listens to the browser. Its job is to send the assistant audio to the Akapulu Labs worker. The worker joins the call as a Daily participant and publishes the audio and the video, so the voice bot does not publish audio or video. When the participant named Avatar joins, the voice bot unsubscribes from that microphone. The browser stays subscribed to it. Runs AkapuluAvatar after assistant audio. The code is on Your bot.
  • Akapulu Labs worker — Akapulu Labs’ avatar process. Joins with an avatar meeting token. Publishes the face and the played audio.
They own the Daily room on this path. Akapulu Labs does not create it for them.
Lifecycle (in order)
  1. Their server calls create_akapulu_call with avatar_id and show_ai_label. Use the Clara avatar_id in the manual POST below unless they pick another from the catalog. It creates the private Daily room, mints the three meeting tokens, and POST /api/live-sessions/. It returns the room URL, the bot token, the browser token, and session_id. The room lasts two hours unless they pass room_exp_secs. That starts the Akapulu Labs worker. It does not wait for the first frame. The code is on Your bot.
  2. A server that already has a Daily room skips create_akapulu_call. It mints the worker token and calls POST /api/live-sessions/ with Bearer AKAPULU_API_KEY and JSON:
    • avatar_id (use Clara 1f777f64-3758-4a7d-9cbc-c64ae654f7d1 unless they pick another from https://akapulu.com/catalog)
    • show_ai_label (boolean)
    • room_url (the Daily room they just created)
    • avatar_token (the meeting token for the Akapulu Labs worker)
  3. On that manual POST, the response is session_id. The helper already returned that same id. Pass it to AkapuluAvatar.
  4. The voice bot starts, joins the room with the voice-bot token, and passes session_id into AkapuluAvatar (after the assistant audio in the pipeline).
  5. The browser joins with the browser token (usually from their page / server).
  6. When the voice bot produces assistant audio, AkapuluAvatar sends that audio to Akapulu Labs; the Akapulu Labs worker publishes lip-synced video + that audio in the room.
Keep AKAPULU_API_KEY on the server. The browser never gets it. Details: How it works, Your bot.

4. After they try it

Send them these docs: