17 KiB
Onboarding, tutorial & help (chat-first, cloud login)
Summary
Workstream research for the LifeOps Personal Assistant MVP (GitHub project 15). Product decision, paraphrased from the owner: onboarding happens in chat, and for the MVP it is exactly one step — log in with Eliza Cloud. A flagged variant for local agent + local models exists and stays flagged. All status widgets, thinking indicators, and reactions appear in the chat; views assist in the background but everything happens in chat. The guiding constraint is minimal additional scope: turn what exists into an MVP by fixing, testing, verifying and validating — prefer deleting/simplifying over adding.
The good news: the cloud-only in-chat onboarding, the chat-native tutorial, and help-as-agent-knowledge all already shipped (#13377, PRs #13393/#13521/#13394). The bad news: the only tests that prove a REAL cloud account + REAL LLM work after onboarding live in a nightly lane that has not produced a green run since at least 2026-06-25, the device lanes cover the deep-link remote-connect path but not the production-default cloud sign-in path, and there is no live-LLM scenario proving the agent can actually answer help questions from its seeded knowledge. This doc's core deliverable is the test/verification plan that closes those gaps.
Current state
All references verified on origin/develop (c1362eaf72d, 2026-07-05) unless
noted. Note for readers on older branches: PR #13394 (chat-native tutorial +
Help→knowledge) merged to develop on 2026-07-05; branches cut before it still
carry the deleted spotlight tutorial and HelpView.
Onboarding paths that exist today
- Cloud-only onboarding — the production default (#13377).
isRuntimeChooserEnabled()(packages/ui/src/first-run/first-run-runtime-flag.ts:51) returns false on every build by default; the Play-Store cloud-locked Android variant can never re-enable it (first-run-runtime-flag.ts:52-53, covered byfirst-run-runtime-flag.test.ts:54). With the chooser off, the in-chat conductor (packages/ui/src/first-run/use-first-run-conductor.ts:90-96) seeds a single greeting — "Sign in to Eliza Cloud and I'll get you set up" — with one CHOICE button. A usable stored steward session at mount skips the ask entirely ("Welcome back", zero interactions). Provisioning success callscompleteFirstRun("chat")immediately (use-first-run-conductor.ts:467-473on develop); existing cloud agents are auto-adopted (no picker). Exactly onePOST /api/first-runfires per onboarding (idempotency funnel,packages/ui/src/first-run/first-run-finish.ts:100; server routes inpackages/agent/src/api/first-run-routes.ts). - Flagged local/remote chooser (dev only).
VITE_ELIZA_ENABLE_RUNTIME_CHOOSER=1build flag or localStorageeliza:enable-runtime-chooserre-enables the three-way runtime choice (cloud / on this device / remote) plus provider and tutorial steps. The flag contract is unit-tested (first-run-runtime-flag.test.ts) and every chooser-mode e2e lane opts in explicitly (packages/app/test/ui-smoke/onboarding-to-home.shared.ts:327). - Mobile remote-connect deep link.
elizaos://first-run/runtime/remote?api=<url>connects a fresh device to an existing agent (packages/ui/src/first-run/deep-link-handler.ts; driven on-device bypackages/app/test/android/onboarding-to-home.android.spec.tsandpackages/app/scripts/ios-onboarding-smoke.mjs). - Headless real-cloud login for tests.
packages/ui/src/platform/e2e-wallet.tsinstalls a harness-seeded EIP-1193 wallet (never on store builds, never on deployed origins, never over a real wallet) andpackages/ui/src/state/cloud-siwe-login.tsperforms a genuine EIP-4361 nonce→sign→verify handshake against the real cloud API. Witheliza:e2e-wallet:autologin=1the session lands before onboarding mounts — proven zero-touch on the iOS simulator against real Eliza Cloud in <35s (#13377 evidence). This is the key that makes automated real-account device e2e possible; today it is wired into no recurring lane.
After login
- Cloud handoff: shared→dedicated agent migration with phase events and a
one-shot retry (
packages/ui/src/cloud/handoff/run-cloud-agent-handoff.ts). - The onboarding sheet auto-collapses on completion and the user lands in chat;
a one-time post-onboarding character-select landing can still occur
(#13396 product decision,
packages/ui/src/state/startup-phase-hydrate.ts:264-292). - Getting-started notifications are seeded once per agent — "Take the tour"
(
/tutorial), "Get help any time" (/chat), "Connect your calendar" (/connectors) —packages/agent/src/runtime/onboarding-notifications.ts:44-73. - Post-login permission priming soft-ask modal
(
packages/ui/src/components/permissions/permission-priming.ts).
Tutorial (post-#13394)
Chat-native, no overlay engine: packages/ui/src/tutorial/tutorial-service.ts
(guarded state machine, persisted to eliza:tutorial-state),
tutorial-script.ts (six conversational steps: welcome, send-message, voice,
navigate, new-chat, done; each auto-advances on the real action with a "Next"
fallback), TutorialConductor.tsx seeds turns into the live transcript, and the
__tutorial__: action channel carries choices. Entry points: the launcher tile
(packages/ui/src/components/pages/LauncherSurface.tsx:101), the /tutorial
builtin view (packages/agent/src/api/builtin-views.ts:14-23), typed
"start/stop/restart tutorial" composer commands, and the seeded notification.
The tour never auto-launches.
Help (post-#13394)
There is no Help view. HelpView.tsx and help-content.ts were deleted;
the FAQ now ships as help-tagged default knowledge documents
(packages/agent/src/runtime/default-help-documents.ts, seeded idempotently by
seedBundledDocuments in default-documents.ts). The chat is the help surface:
the agent answers "how do I…" from retrieval.
Test coverage today — what is real and what is mocked
| Lane | What it covers | Real or mocked | Status |
|---|---|---|---|
onboarding-cloud-only.spec.ts (3 tests) |
Production-default flow: sign-in-only greeting, session-injection zero-tap, auto-adopt no-picker | Cloud login + provisioning mocked at network boundary | Green in keyless CI |
onboarding-to-home.spec.ts / -mobile / onboarding-confused-user.spec.ts / first-run-startup.spec.ts / reset-returns-to-onboarding.spec.ts |
Chooser-mode local path, spam-tap/error recovery, factory reset → onboarding | All APIs mocked (installDefaultAppRoutes) |
Green in keyless CI |
use-first-run-conductor.test.ts + .fuzz.test.ts |
Conductor state machine incl. cloud-only describe block | Unit (jsdom) | Green |
tutorial-chat.spec.ts |
Chat-native tour end to end, typed commands, narration via SpeechSynthesis spy | Routes mocked | Green |
cloud-live.spec.ts |
REAL login (ELIZAOS_CLOUD_API_KEY), REAL provisioning, REAL cloud chat turn asserting a non-stub reply | Nothing mocked | Only runs in nightly app-live-e2e.yml — see below |
live-agent-chat.spec.ts |
Real local runtime + live provider chat turn from the UI | Live | Same lane |
.github/workflows/app-live-e2e.yml |
The only home for real-cloud/real-LLM onboarding proof | Live, secret-gated, nightly | No green run since ≤2026-06-25 — every scheduled run 06-25→07-05 is failure/cancelled (gh run list); known causes: desktop-packaged runtime-copy break + live-chat spec timeout |
test/dev-smoke/bun-dev-onboarding-chat.spec.ts |
Real local-runtime first-run with a live provider against bun run dev |
Live, self-skips keyless | Runs only with keys |
Android device: onboarding-to-home.android.spec.ts |
Remote-connect deep link only — not the cloud sign-in default | Real WebView, real deep link | On-demand |
iOS: scripts/ios-onboarding-smoke.mjs |
Remote-connect only (Preferences-driven verifier) | Real simulator | On-demand |
iOS cloud: test:e2e:ios:cloud → scripts/cloud-provisioning-e2e.mjs |
Real Hetzner-backed cloud agent provisioning + runtime answer | Real, but programmatic — no UI, no onboarding DOM | On-demand |
scenario-runner (packages/scenario-runner/test/scenarios/) |
No onboarding, tutorial, or help scenario exists | — | Gap |
What is weak, broken, or untested
- The verification of record is dead. Every claim that "a real Eliza Cloud
account works and a real LLM answers after onboarding" rests on
app-live-e2e.yml, which has been red/cancelled for 10+ consecutive days. Until it is green, the production-default onboarding is functionally unverified end to end. - No automated device coverage of the default path. Both device onboarding lanes exercise the remote-connect deep link — a secondary, flagged-adjacent path — while the single path every real user takes (cloud sign-in) is only covered by desktop-Chromium mocks and one manual evidence capture. The zero-touch SIWE wallet exists precisely to automate this and is unused.
- Help has no proof it helps. The FAQ moved from a searchable view into
agent knowledge, which means its efficacy now depends on retrieval + a live
model.
default-documents.test.tscovers seeding mechanics only; nothing asserts a real model answers "how do I start the tutorial?" correctly. - "Everything happens in chat" is not fully landed. PR #14168 (boot trouble speaks in chat: deletes floating boot/handoff banners, in-chat recovery cards, full→half onboarding detent) is OPEN, DRAFT, and CONFLICTING. Develop still has the floating-banner surfaces it removes.
- Evidence mechanics drift. Several specs still write evidence into
.github/issue-evidence/underE2E_RECORD=1(e.g.first-run-startup.spec.ts:33-52); the MVP convention is inline MP4 + JPG posted in issues/PRs. - Post-onboarding character-select detour. Cloud-only completion says "You're all set — ask me anything" then may land the user on character select once (#13396). Two messages fighting for the first impression.
Design considerations
- Two-tier testing, deliberately. The mocked keyless lanes are the regression net (fast, deterministic, fork-safe) and are genuinely good — the cloud-only specs assert the exactly-once POST at the network boundary and the confused-user storms are fuzzed. Keep them. The live lane is the verification of record; fixing it beats adding anything new.
- Real accounts are already reachable. Two independent mechanisms exist:
API-key sessions (
ELIZAOS_CLOUD_API_KEY, used bycloud-live.spec.ts) and the genuine SIWE handshake via the e2e wallet (covers the login UX itself, works headless on devices). The MVP test plan is wiring, not building. - Device evidence tooling exists.
startAndroidScreenRecord(MP4 via adb),simctl io recordVideo, and the screenshot helpers are already in the lanes; posting inline (MP4 + JPG) is a convention change, not new machinery. - A "liveness contract" is the cheapest strong guarantee. Every onboarding
path, on every surface, should end the same way: send one real chat message,
assert a real (non-stub-marker) reply.
cloud-live.spec.tsalready encodes this pattern (STUB_FIXTURE_MARKERnegative assertion) — generalize it. - No new onboarding scope. No name pickers, provider marketplaces, or wizard steps. The one-tap flow is right for children, elderly users, and everyone in between — fewer steps is the accessibility strategy, with no special rails and no therapy language (the current copy already complies).
Open questions → answers
Q1. Is the flagged local path in MVP test scope? A: Keep it verified at the flag boundary only: the existing unit tests, the existing mocked chooser-mode lanes, and one assertion that store/cloud-locked builds can never enable it. Do not build live lanes for local onboarding — the MVP default is cloud, and the dev-smoke live lane already covers local first-run for developers with keys. (Owner-confirmable, but the default is clear from "minimize scope".)
Q2. Should the tutorial auto-launch after onboarding?
A: No. Today it never auto-launches (tile, notification, typed command,
/tutorial view) and the wrap-up copy points at it. That matches the views
doctrine (no suggestion chips, agent-proactive is for view switches) and the
no-special-rails constraint. Keep as-is; test discoverability instead.
Q3. Keep the one-time character-select landing after cloud-only completion? A: Default answer: remove it for MVP — cloud-only completion already lands in chat with "ask me anything", and a full-screen detour immediately after contradicts one-obvious-path. Because #13396 made this a deliberate product decision, this needs a one-line owner confirmation before deleting; the issue below is written to ask first, then act.
Q4. Where should real-cloud onboarding verification run?
A: Keep app-live-e2e.yml nightly as the home (it exists, is secret-gated,
and never runs on fork PRs), fix its two red jobs independently, and add
workflow_dispatch usage to the Definition of Done for onboarding-touching
PRs: run the lane, link the green run in the PR. Do not move live tests into
keyless PR lanes — they cannot have secrets.
Q5. Does help need any UI surface beyond chat?
A: No. #13394 deleted the view deliberately; the launcher keeps the tutorial
tile and the notification inbox points "Get help any time" at /chat. What is
missing is proof the agent answers help questions — a scenario, not a view.
Q6. How should evidence be attached now?
A: Inline in the GitHub issue/PR: MP4 (renders inline) for walkthroughs and
device recordings, JPG for screenshots (size), plus logs/trajectory excerpts in
collapsed <details> blocks. Specs should stop writing to
.github/issue-evidence/; CI lanes upload artifacts and the PR author posts
the reviewed files inline. Issue drafts below encode this.
Recommendation (minimal-scope MVP plan, ordered)
- P0 — Make the live lane green (
app-live-e2e.yml): triage the desktop-packaged runtime-copy failure and thelive-agent-chat.spec.tstimeout; a green scheduled run with reviewed artifacts is the acceptance. Everything else in this workstream depends on this lane meaning something. - P0 — Automate the production-default path on devices: wire the e2e
wallet (
eliza:e2e-wallet:pk+:autologin) into an iOS-simulator and Android-emulator lane that performs the REAL SIWE handshake, onboards through the real UI, and records MP4 + JPG. The manual #13377 recipe is the spec; turn it into a command. - P1 — Liveness contract everywhere: every onboarding e2e (desktop packaged, web, iOS, Android, cloud-live) ends with one real chat turn and a non-stub reply assertion.
- P1 — Help scenario: a scenario-runner scenario that asks realistic help questions ("what do I do first?", "how do I talk to it?", "how do I restart the tour?") against a live model with the seeded help knowledge, trajectory reviewed by hand.
- P1 — Land or explicitly descope PR #14168 (boot trouble speaks in chat). It is the remaining piece of "all status happens in chat".
- P2 — Post-onboarding landing cleanup: owner decision on the character-select detour; delete if confirmed.
- P2 — Spec/evidence hygiene: move spec evidence output to CI artifacts + inline posting; keep the chooser-lock regression assertions.
Out of scope (MVP non-goals)
- Any new onboarding step, wizard, or personalization flow.
- Live/e2e investment in the flagged local-model onboarding path beyond the flag-boundary tests that exist.
- Re-adding a Help view or a searchable FAQ surface.
- Redesigning the tutorial script or adding tour steps.
- The cloud login web page polish (#13519 sign-in flash) — cloud-frontend workstream, not this one.
- Therapy-flavored or audience-segmented onboarding copy — explicitly banned; current copy is universal and stays that way.
Proposed issues
[onboarding] P0 — Resurrect App Live E2E: real cloud login + real-LLM chat must produce a green nightly run[onboarding] P0 — Device e2e for the default cloud sign-in onboarding via the SIWE e2e wallet (iOS sim + Android emu)[onboarding] P1 — Liveness contract: every onboarding e2e ends with a real chat turn and a non-stub reply[onboarding] P1 — Scenario: agent answers help questions from seeded help knowledge (live LLM, trajectory reviewed)[onboarding] P1 — Land in-chat boot recovery (PR #14168): rebase, resolve, verify no floating banners remain[onboarding] P2 — Remove the one-time character-select landing after cloud-only onboarding (owner confirm, then delete)[onboarding] P2 — Onboarding test hygiene: inline MP4/JPG evidence, drop .github/issue-evidence writes, chooser-lock assertions