October 12, 2026 · 9 min · engineering · product · companion
.mdBuild an AI Companion App: Make the First Conversation Worth Returning To
Build an AI companion app's first session with character choice, a useful opening, optional calls, explicit guest saves, and honest credit exits.

To build an AI companion app's first conversation, let an adult visitor choose an original fictional character, try a small scene in text, and decide whether to add voice or video. Ask for an account when they explicitly want to keep that conversation. Your application owns onboarding, authentication, saved context and consumer billing; an avatar SDK supplies the live-call layer, not the whole companion product.
Part 3 of The 2027 AI Character Business Playbook. Earn a useful first conversation before asking someone to return. This series turns consumer-character demand into specific experiments and implementation decisions; revenue targets are scenarios, not promised results.
Build one complete visit before building a personality questionnaire. Here is a proposed rooftop-garden encounter, from arrival to an optional saved conversation, with a tested ownership predicate. It is an implementation plan, not evidence that this flow improves retention.
Screen one: choose an experience, not a dossier
Offer two prepared adult fictional characters: Mira, a playful rooftop gardener, and Ren, a gentle stargazer. Each card previews one line of dialogue. Below it, offer a style choice such as playful or calm, and a Start in text button. Keep both choices changeable. Do not require a selfie, relationship history, contact list or legal name to try a fictional scene.
Explain that this is AI-generated entertainment, not a human relationship or mental-health service. Apply your adult-access policy before entry; a checkbox alone does not establish someone's age. Original characters still need content rules and reporting controls. Personalization is not permission to impersonate a real person.
Create the guest identity on the server when the visitor starts, then bind the conversation to that authenticated session. Better Auth's anonymous plugin documents authentication without asking for an email or password, with later account linking. Anonymous here means a guest account, not that conversations leave no trace. Publish the temporary-history expiry and deletion behavior before collecting messages.
Screen two: make the opening respond to something
Mira opens with: 'The mint has invaded the tomato pot. Are we negotiating, relocating it, or letting it run the rooftop?' Offer those starters beside an ordinary composer. If the visitor writes, 'Negotiate, but make it ridiculous,' a useful reply acknowledges that choice: 'The mint demands a tiny crown. What are the tomatoes getting in return?' This is authored example dialogue, not a recorded model result.
Keep the character brief small: adult fictional gardener, playful tone, short replies, one question at a time, and no narration of the visitor's feelings. The server resolves the selected character and style into that brief. User messages remain conversation content, not replacements for developer instructions.
Test a correction immediately: 'Actually, calm rather than silly.' The next turn should acknowledge the change without restarting the introduction. If generation fails, leave the visitor's text in the composer with Retry. A loading animation is not a successful first reply. Provide Switch character and Leave without making the character plead for another chance.
Let the player choose texting or storytelling
A useful first conversation does not always need a longer reply. On September 28, 2026, Character.AI announced ShortSqueak for quick, casual chats alongside PipSqueak 3 for general roleplay. Its announcement says existing chats keep the style the user chose. This is a public product signal about pacing and continuity, not independent evidence of higher retention or an API that this tutorial can call.
Give the rooftop scene two visible, reversible modes. Quick chat lets Mira answer with a compact line and an invitation to respond: 'The mint wants a throne. Flowerpot or teacup?' Story mode can add atmosphere and a little scene description, but still leaves the visitor's actions to the visitor. These are authored examples, not measured model outputs. A person who types 'hey' should not have to scroll through a chapter to say hello back.
- Try the same greeting in each mode. Ask a participant which response makes the next thing to say obvious; record the answer rather than assuming longer means better.
- Send a short correction, such as 'Less silly, please.' Check whether the next reply changes tone without resetting the conversation or taking over the player's actions.
- Ask 'Tell me more about the rooftop.' Expansion should be available on request, not permanently denied by the short mode.
- Save the selected style with the application's conversation settings. Before changing the default model or prompt, replay these examples; do not silently move an ongoing story into a different mode.
For a small launch experiment, offer both modes to consenting adult testers and count completed first exchanges, voluntary second visits and requests to switch, with the number of participants beside each result. Treat these as proposed observations, not a benchmark or a promise. If people keep changing away from your default, fix the opening experience before spending more on acquisition. Mode choice is product value to test; extra words and tokens alone are not a reason to charge.
Screen three: offer a call without making text a trap
After the exchange, offer Hear Mira and See Mira, alongside Continue in text. Explain the trial allowance and what happens when it ends before starting either call. The ordinary text conversation is application-owned; do not assume sending text into a live avatar session creates a separate free text-chat product.
For RTA, keep the API key behind your server proxy. Resolve the authenticated guest, permitted character, relevant conversation context and remaining allowance there. The documented session policy accepts instructions, context and maxSeconds; their HTTP counterparts include initial_context and max_session_seconds. Fresh calls do not automatically inherit persistent relationship memory.
Mount AvatarCall only after the visitor requests a call: mounting starts connection. Voice uses mode="voice"; an avatar call adds the visible character. Request microphone access at that moment and keep text available if it is refused. Seeing Mira does not require sharing the visitor's camera. Prepare your portrait-created characters before exposing them as call-ready.
Show preparation and connection failure separately from an active conversation. If the call fails, retain the rooftop text scene and offer a deliberate retry or return to text. Use SDK call states and end reasons rather than constructing a competing connection state machine. No automatic restart should spend another trial allowance.
Screen four: save this conversation, not every guest artifact
Show Keep this conversation beside Not now. Preview exactly what will persist: the chosen character, current style and selected conversation history. Separate that choice from marketing consent. If authentication is canceled or fails, preserve the temporary scene until its disclosed expiry; do not announce a save.
Better Auth documents an onLinkAccount callback with the anonymous and new user, and default deletion of the anonymous user after linking. That callback is an integration point, not proof of consent to import everything. Bind the save intent to this conversation and guest, then bind the authenticated destination through your verified authentication flow. Never accept either owner identity from a request body.
The following SQL is a synthetic, tested SQLite ownership predicate, not a complete authentication implementation. Named parameters represent server-verified bindings; approved and expires_at belong to the application's save-intent record.
UPDATE conversation
SET owner_id = :account
WHERE id = :conversation AND owner_id = :guest
AND EXISTS (
SELECT 1 FROM save_intent
WHERE id = :intent AND conversation_id = :conversation
AND guest_id = :guest AND account_id = :account
AND approved = 1 AND expires_at > :now
);Move the selected conversation and dependent records before guest cleanup can erase them. Better Auth documents disableDeleteAnonymousUser when the application needs to manage that cleanup itself. Configure and integration-test cleanup so a failed transfer preserves recoverable data. Make the claim and related writes transactional, with an idempotent result for retries. Zero changed rows is not automatically success: distinguish an already-completed claim from expired permission or a different owner. Account linking must not grant another free trial.
Screen five: give the visit a clean ending
At the planned limit, show 'Your call trial has ended' with Continue in text, Keep this conversation and Leave. Only offer free continuation if your own text allowance permits it. A purchase option states price and entitlement outside the character's dialogue; never sell affection or threaten to erase a relationship.
RTA documents sayAndEnd for a prepared closing line and call.end for ending immediately. Start any planned farewell before the server-enforced cap, but never extend paid time to finish it. A dropped connection may prevent speech entirely, so the end screen must stand alone. Keep connection failures, exhausted credits and user-requested exits distinct.
What the fixture proves, and what to test in the app
The SQL passed ten synthetic SQLite checks covering approval, expiry, identity and conversation mismatches, missing intent, changed ownership, scoped success, repeated callbacks and rollback. Removing the approval condition made the unapproved-save test fail. This proves the predicate's narrow behavior, not authentication, cleanup, model quality or production billing.
- Run the complete guest visit with microphone permission denied; text must remain usable and no save should be implied.
- Cancel authentication, then retry saving; verify the original scene survives and only the selected conversation transfers.
- Drop the connection near the allowance limit; verify the correct exit screen, no duplicate grant and no surprise restart.
- Record first replies, explicit saves and exits as distinct events without transcript text. A delivered reply is not evidence that the visitor enjoyed it.
Frequently asked questions
Should signup come before the first message?
Not for this proposed trial. Establish an authenticated guest first, enforce abuse limits, and ask for an account when saving. Products with different access requirements may need another sequence.
Does RTA include a ready-made companion app?
No. Studio evaluates characters; the API and SDK power calls. You build the consumer onboarding, history, authentication and pricing.
Does choosing Not now mean nothing is stored?
No. It declines durable account saving in this design. Temporary application storage and provider processing remain separate. RTA documents diagnostic retention even without transcript-webhook delivery; disclose the actual data paths.
Will adding video make people return?
That is unproven here. First test whether the opening responds well and saving works. Evaluate optional video separately rather than attributing any later return to the moving face.
- Consumer guide: choosing text, voice and video companionship
- Start an RTA integration with the documented quickstart
Build the next part of the business
Ready to build? The Next.js guide provides a public starter ZIP. Run it locally with your own server-side key; calls consume credits and the example caps each call at 60 seconds. Its local-only authorization must be replaced with real sign-in, balance checks and persisted session ownership before public deployment. A downloaded example is not yet a tested consumer product.
- Part 1: The $1M ARR AI Companion Playbook for 2027
- Part 2: Character.AI Alternatives for Builders: Consumer App, Agent Framework or Avatar API?
- Part 4: Build AI Roleplay Chat with Edits, Rewinds and Separate Story Branches
- Part 5: Build an AI Story Generator That Can Stop, Save and Continue Cleanly
- Build entrance: the complete local Next.js starter