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.
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
~/.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.
3. Quick talk, or build their own chat?
User step. Ask which they want:
- A super-quick link — talk to an avatar soon, without building a bot.
- Build their own custom avatar chat — a Pipecat voice pipeline with the Akapulu Labs avatar in their app.
Path 1: Super-quick link
User step. Ask how they want that link made:
- You create it with their API key — you call the API and hand them a URL to paste in a browser.
- They use the Akapulu Labs UI — in-app onboarding / Hosted links in the dashboard.
Path 1a: You create the hosted link
A hosted link is a public page Akapulu Labs hosts. You create the row; they openurl and click Start Call. Docs: Hosted links, Create a hosted link.
Defaults for this path (do not ask):
- Avatar: Clara —
avatar_id1f777f64-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.
POST /api/hosted-links/ with Bearer auth and a JSON body that is exactly:
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, andAkapuluAvatar.
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 frompipecat-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
- The Akapulu Labs worker, started by the live-session API after they already have
room_urlandavatar_token AkapuluAvatarin the voice bot, which forwards assistant audio to that worker
Recommended place in a Pipecat (or any) voice pipeline
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:
- Build (or keep) the voice pipeline as usual until there are assistant audio frames.
- On their server, call
create_akapulu_callbefore the bot starts. It readsDAILY_API_KEYandAKAPULU_API_KEY, creates the private Daily room, mints the three meeting tokens, andPOST /api/live-sessions/. It returns the room URL, the bot token, the browser token, andsession_id. The room lasts two hours unless they passroom_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. - Put
AkapuluAvatarin the voice bot pipeline after that assistant audio, withsession_id. - 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_subscriptionsand sets that microphone tounsubscribed. The browser stays subscribed to it. The code is on Your bot. - Join the browser with the browser token.
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_KEYin 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, andCARTESIA_API_KEY. If one of those is not already in this environment, instruct them to activate it here.
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 withAkapuluAvatar inside it (talking to the Akapulu Labs worker).
User step. ActivateAKAPULU_API_KEYandDAILY_API_KEYin 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
AkapuluAvatarafter 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.
Lifecycle (in order)
- Their server calls
create_akapulu_callwithavatar_idandshow_ai_label. Use the Claraavatar_idin the manual POST below unless they pick another from the catalog. It creates the private Daily room, mints the three meeting tokens, andPOST /api/live-sessions/. It returns the room URL, the bot token, the browser token, andsession_id. The room lasts two hours unless they passroom_exp_secs. That starts the Akapulu Labs worker. It does not wait for the first frame. The code is on Your bot. - A server that already has a Daily room skips
create_akapulu_call. It mints the worker token and callsPOST /api/live-sessions/with BearerAKAPULU_API_KEYand JSON:avatar_id(use Clara1f777f64-3758-4a7d-9cbc-c64ae654f7d1unless 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)
- On that manual POST, the response is
session_id. The helper already returned that same id. Pass it toAkapuluAvatar. - The voice bot starts, joins the room with the voice-bot token, and passes
session_idintoAkapuluAvatar(after the assistant audio in the pipeline). - The browser joins with the browser token (usually from their page / server).
- When the voice bot produces assistant audio,
AkapuluAvatarsends that audio to Akapulu Labs; the Akapulu Labs worker publishes lip-synced video + that audio in the room.
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:- How a call fits together: https://docs.akapulu.com/guides/getting-started/how-akapulu-works
- Your bot: https://docs.akapulu.com/guides/calls/your-bot
- Hosted links: https://docs.akapulu.com/guides/calls/hosted-links
- Catalog: https://docs.akapulu.com/guides/avatars/avatar-catalog
- Verify a recording: https://docs.akapulu.com/guides/video-marks/verify
- Pricing: https://akapulu.com/pricing/

