Agent Setup Onboarding

Interactive AI-driven onboarding interview and room promotion lifecycle

Overview

The Agent Setup Onboarding flow (/onboarding) is Zooly's primary onboarding experience. It replaces static multi-step forms with an interactive conversation where a prospective user talks directly with an AI agent to establish their representation terms, floor pricing, and partnership preferences.

The flow operates as a stateful, progressive funnel:

  1. Audience Selection — Visitor identifies as talent, brand, agency, brand representative, or IP owner.
  2. Interactive Interview — 7 structured interview questions powered by Z-Agent and guided by scripted persona directives.
  3. Background Distillation & Goal Evaluation — Memory distillation runs in the background (distilMemory: true), recording terms and evaluating the talent-setup goal.
  4. Sign-In / Claim — Once the interview concludes (or when skipped), the user signs in via popup auth.
  5. One-Shot Promotion — The guest room is bound to the new account, and runOnboardingPromotion runs full planning and Arvist promotion to seed durable account memory.
  6. Profile & Socials — Final metadata entry (name, photo, social links) before entering the live dashboard.
flowchart TD Audience["1. Pick Audience<br/>(talent, brand, agency, etc.)"] --> GuestRoom["2. ensureOnboardingRoom<br/>(autoPlan: false, guestKey)"] GuestRoom --> Chat["3. Scripted Interview<br/>(7 builder questions)"] Chat --> Distil["4. Background Distillation<br/>(distilMemory: true)"] Distil --> GoalMet{"goals.talent-setup<br/>= met?"} GoalMet -->|Yes / Skip| SignInPrompt["5. Sign-in Prompt in Transcript<br/>(Google / Email popup)"] GoalMet -->|No| Chat SignInPrompt --> Claim["6. claimOnboardingRoom<br/>(bind participant to account)"] Claim --> Promote["7. runOnboardingPromotion<br/>(planFromRoom + Arvist -> durable memory,<br/>autoPlan: true)"] Promote --> ProfileSocials["8. Profile & Socials Steps"] ProfileSocials --> Dashboard["9. Live Agent Dashboard"]

Room Architecture & Guest Identity

Landing Room (talent-home)

When a visitor lands on /onboarding and selects an audience, ensureOnboardingRoom creates or resumes a room of kind talent-home:

  • Identity: Unauthenticated guests are assigned a cryptographically generated guestKey stored in an HttpOnly cookie.
  • Planner Configuration: The room is initialized with autoPlan: false to keep guest turns fast and inexpensive, avoiding full multi-agent orchestration on initial messages.
  • Goals: Configured with the single talent-setup goal (GOAL_KEY_TALENT_SETUP).
  • Initial Memory: Seeded with onboarding: { audience, setupStarted: false, skipped: false }.
const room = await createZAgentRoom({
  title: "Your agent",
  kind: ROOM_KIND_TALENT_HOME,
  plannerPrompt: DEFAULT_PLANNER_GUIDE_PROMPT,
  plannerModel: DEFAULT_PLANNER_GUIDE_MODEL,
  recallPrompt: DEFAULT_RECALL_PROMPT,
  recallModel: DEFAULT_RECALL_MODEL,
  autoPlan: false,
  goalConfig: DEFAULT_GOAL_CONFIG.filter(
    (goal) => goal.key === GOAL_KEY_TALENT_SETUP,
  ),
  memory: {
    onboarding: {
      audience: input.audience,
      setupStarted: false,
      skipped: false,
    },
  },
});

The 7 Setup Questions

When the user clicks "Build my agent", startOnboardingSetup records setupStarted: true and posts the first scripted interview question. The 7 questions (TALENT_BUILDER_QUESTIONS) are:

#KeyQuestionPurpose
1wantedOffersWhat offers would you like to receive?Preferred collaboration formats, deal structures
2unwantedOffersWhat offers would you not like to receive?Hard refusals, no-go categories
3wantedBrandsWhat brands, or types of brands, would you want to work with?Target brand partners and verticals
4unwantedBrandsWhat brands, or types of brands, would you not want to work with?Excluded brands and competitors
5minimumOfferWhat is the minimum offer you would entertain?Pricing floor (parsed into minor units)
6offerMustIncludeWhat information do you want an offer to include?Mandatory proposal requirements
7otherAnything else that is important for you, or that you want me to know?Scheduling, usage rights, personal notes

Persona Directive & Background Distillation

Directive-Steered Reply

During guest turns, autoPlan is disabled so the blocking PlannerGuidAg stage is bypassed. Instead, buildOnboardingPersonaDirective computes the system directive for the persona on the fly based on:

  • Pre-signup commercial facts (pricing, 5% deal fee, 3 brand approaches/month).
  • Whether setup has started.
  • The next question based on answeredCount and setupGoalMet.

distilMemory: true

Although autoPlan is false, every turn in the onboarding chat route passes distilMemory: true to streamRoomChat. This invokes PlannerDistilMemAg in the background (parallel to the persona's streaming reply):

  1. Distils Facts: Extracts and writes deal preferences, category boundaries, pricing rules, and exclusions into room.memory.
  2. Evaluates Goals: Checks the transcript against the talent-setup goal description:

    "The talent has said enough to be represented properly: what they accept, what they refuse, what an offer must contain, and what they charge. Not when the questions have been asked — when the answers are actually in the memory."

  3. Flips Status to met: When satisfied, PlannerDistilMemAg writes goals.talent-setup.status = "met".
// apps/zooly-app/app/api/z-agent/onboarding/rooms/[roomId]/chat/route.ts
return await streamRoomChat({
  roomId,
  participantId: view.participantId,
  messages: body.messages,
  personaDirective: buildOnboardingPersonaDirective(view, {
    pendingUserAnswer,
  }),
  distilMemory: true,
});

The Sign-In Gate & State Machine

The client determines when to show the sign-in prompt using signInSuggested:

signInSuggested =
  onboarding.skipped === true ||
  setupGoalMet ||
  answeredCount >= ONBOARDING_ANSWER_CAP; // 11

This ensures the user is prompted to save their agent in any of three cases:

  • Goal Met: The AI planner determined the user provided sufficient representation terms (even if conversational drift occurred or answers were combined).
  • Count Reached: The user has sent ONBOARDING_ANSWER_CAP (11) messages since the interview started. The cap is deliberately higher than the 7 questions because user turns also include side questions, so the count is a loose backstop rather than a script position.
  • Skipped: The user clicked "Skip" in the header to proceed directly to manual configuration.

The sign-in card renders non-blockingly inside the transcript using AgentChat's signInPrompt prop, supporting Google OAuth popup login and email authentication without page redirection.


Promotion to Durable Account Memory

When the user finishes authentication, claimOnboardingRoom binds the guest seat to their new accountId and triggers finalizeOnboardingRoom:

  1. Tag Role: Sets account who field (TALENT, BRAND, or AGENCY) based on the onboarding audience.
  2. Run Promotion (runOnboardingPromotion):
    • Acquires the autoPlan claim lock (claimZAgentRoomAutoPlan).
    • Runs planFromRoom (full PlannerGuide + PlannerDistilMem) to compile room memory.
    • Runs runRoomArvist to extract standing rules, preferences, and identity into the account's durable memory (z_agent_object_memory).
    • Sets autoPlan: true on the room, enabling full live mediator capabilities for future sessions.
export async function runOnboardingPromotion(roomId: string) {
  const room = await getZAgentRoom(roomId);
  const participants = await listZAgentParticipants(roomId);
  const talent = participants.find((p) => p.key === "talent");

  if (!(await claimZAgentRoomAutoPlan(roomId))) {
    return { planned: false, arvist: null };
  }

  await planFromRoom(room, talent);

  const arvist = talent.accountId
    ? await runRoomArvist(roomId, talent.id)
    : null;

  return { planned: true, arvist };
}

Post-Authentication Setup Steps

After claiming, the onboarding SPA advances through three final steps before opening the dashboard:

  1. Profile Step (ProfileStep.tsx):
    • Collects display name and avatar image.
    • Direct image upload via fetchUploadImageAssets and saves imageUrl to the account.
  2. Socials Step (SocialsStep.tsx):
    • Collects Instagram, TikTok, YouTube, and X handles.
    • Updates account social links.
  3. Building Step (BuildingStep.tsx):
    • Animated progress bar simulating agent compilation.
    • Updates account flags: markAgentSetupComplete: true (if interview completed) or markAgentSetupSkipped: true (if skipped).
  4. Done Step (DoneStep.tsx):
    • Launch card with "Open Your Dashboard" button navigating to /dashboard/agent/links.

Key Files & Endpoints

AreaFile / EndpointPurpose
Frontend Pagepackages/offers/client/src/app/components/onboarding/OnboardingPage.tsxMain onboarding orchestrator component
API Clientpackages/offers/client/src/app/components/onboarding/onboardingApi.tsOnboarding API calls (fetchOnboardingRoom, startSetup, claim)
Server Logicpackages/z-agent/srv/src/onboarding.tsRoom lifecycle, guest claiming, and view projection
Interview Specpackages/z-agent/srv/src/talent-onboarding.ts7 builder questions and currency parsing logic
Room RouteGET /api/z-agent/onboarding/roomFind-or-create guest onboarding room
Chat RoutePOST /api/z-agent/onboarding/rooms/[roomId]/chatStreams onboarding reply with distilMemory: true
Start SetupPOST /api/z-agent/onboarding/rooms/[roomId]/start-setupMarks setup started and sends first question
Skip RoutePOST /api/z-agent/onboarding/rooms/[roomId]/skipMarks setup skipped
Claim RoutePOST /api/z-agent/onboarding/rooms/[roomId]/claimBinds guest participant to account and runs promotion