# Wire AI > Wire AI is the AI Growth Engineer for Mobile Apps. Analytics tells you where users left; Wire tests four ways to keep them. It generates four variants for each tested stage of your users' journey, runs them live on real users, reads which one keeps them, and keeps the winner. You set the goal; the AI runs the loop. The credibility boundary: you define what success means, Wire decides how to reach it (it never touches your pricing, roadmap, or marketing). Analytics is free to 299k events a month, forever, on any app. 15 founder seats get the whole engine free in the founding cohort (4 of 15 filled). After the cohort there are three plans, priced on how much of the journey you test: Free at €0 (5 variants on onboarding), Starter at €49 a month (10 variants across two surfaces), Pro at €149 (20 variants across the whole journey). No usage meter on experiments. Early adopters get 2 months free, then 40% off Starter and Pro until the end of the year. Billing is not switched on yet, so nothing charges. There is a public self-serve door at https://getwireai.com/signup, with no card and no call. Account signup confirms your email, takes a password, and creates the app, the API key and a console where that key stays readable. While account signup is switched off the same page hands you a key on the spot instead, creating neither a client nor a password. That key is returned once, because that door mints no login to read it back from. An app created either way runs a scripted two-question flow and makes no model calls; switching the AI flow on is a manual step by email. Built on React Native today, more mobile platforms on the way. The open-source Wire RN SDK is the generative-UI layer it renders with. ## Core pages - [Wire AI](https://getwireai.com/): The AI Growth Engineer for Mobile Apps. It covers five stages of the journey: onboarding, added value, AI personalization, the in-app review and the in-app questionnaire. Four of them run four pre-generated versions at once and Wire keeps the winner; AI personalization is the engine step that sets a new user's initial app state. Nothing is written live per user. First card in ~130ms. - [Create an account or get a key](https://getwireai.com/signup): The self-serve door, public and free. No card, no call, no approval queue. Account signup takes an app name and an email, mails a confirmation link, and on the password you choose it creates the app, the API key and your console, where the key stays readable. While account signup is switched off the page returns the key, the app id and the server URL on the spot instead, once, creating neither a client nor a password. Either way the app lands on the Free plan running a scripted two-question flow until the AI flow is switched on by email. - [Pricing](https://getwireai.com/pricing): The founding cohort free (15 seats, 4 filled), analytics free to 299k events a month forever, then Free at €0, Starter at €49 a month, or Pro at €149, with no usage meter on experiments. Early adopters get 2 months free, then 40% off Starter and Pro until the end of the year. Billing is not switched on yet, so nothing charges. - [How it works](https://getwireai.com/onboarding): The depth page. Demo gallery, integration detail, FAQ. - [Open source](https://getwireai.com/generative-ui-react-native): the open-source Wire RN SDK (npm wireai-rn), the generative-UI layer Wire AI renders with. MIT licensed, A2A today with A2UI arriving in v0.3, streaming by default. - [How to integrate](https://getwireai.com/integrate): Three integration paths. Let your coding agent wire it, install it manually, or ship it with us on the founding cohort install call. - [Documentation](https://getwireai.com/generative-ui-react-native/docs): Install, quick-start, components, hooks, adapters, A2A protocol. - [Blog](https://getwireai.com/blog): Technical articles on generative UI, local LLMs, and React Native AI. ## Integrate Wire AI (verified against @wireai/activation 0.13.5 + wireai-rn 0.2.4) If you are a code-generating model wiring Wire AI into an app, use exactly this. Every line below is checked against the published package, not prose. 1. Install (the kit and the renderer are both required): ``` npm install @wireai/activation wireai-rn ``` 2. Peer dependencies. Required: `react` >=18, `react-native` >=0.73, `react-native-safe-area-context` >=4 (the host must render a `SafeAreaProvider` ancestor), `zod` >=3 (v3 only, v4 changed the API and will fail validation). `wireai-rn` >=0.2.3 (the renderer, installed in step 1). Optional (guarded lazy require, no-op fallback when absent, install only for the feature): `react-native-reanimated` >=3, `expo-blur` >=13, `expo-store-review` >=6, `expo-haptics` >=13, `@expo/vector-icons` >=14, `@blazejkustra/react-native-onboarding` >=1. No native rebuild is required for the kit itself (it is pure JS); a rebuild is only needed if the app's own gating mechanism uses a native module. 3. Wire Metro (required, prevents a second React copy from crashing the app): ```js // metro.config.js const { getDefaultConfig } = require("expo/metro-config"); const { withWireOnboarding } = require("@wireai/activation/metro"); module.exports = withWireOnboarding(getDefaultConfig(__dirname)); ``` 4. Set the env vars. Two are required: ``` EXPO_PUBLIC_WIREAI_API_KEY=wai_... EXPO_PUBLIC_WIREAI_SERVER_URL=https://... ``` `EXPO_PUBLIC_WIREAI_APP_ID` is optional (defaults to `"default"` if unset; you can also pass `appId` directly to `wireConfigFromEnv({ appId: "my-app" })`). The `apiKey` is a tenant key and is safe in the bundle. Both required values come from https://getwireai.com/signup, and no card is asked for. With an account the key is bound to it and stays readable at https://getwireai.com/console. While account signup is switched off the page returns the key, the app id and the server URL on the spot, once, creating nothing you can log into and nowhere to read it back, so copy it when you see it. 5. Render it. `wireConfigFromEnv` returns `null` when the env vars are missing, so always keep a fallback path: ```tsx import { WireOnboarding, themeFromBrand, wireConfigFromEnv } from "@wireai/activation"; export function Onboarding() { const config = wireConfigFromEnv({ appId: "my-app" }); if (!config) return null; // or render your static onboarding return ( { // result: { answers, raw } }} /> ); } ``` Only `config` and `onComplete` are required props. `config` must carry `apiKey`, `serverUrl`, and `appId`. 6. The join key. `user_context.device_key` is the only thing that joins an onboarding session to everything the app reports later; without it the `activated` funnel stays permanently empty and reports no error. Since 0.12.2 the kit supplies its own key, so the default is correct and most apps write nothing: - Pass `storage` to `` and the kit merges in its own persisted per-install key. - A host-supplied key always wins: `userContext={activationJoinContext(deviceKey)}` is forwarded verbatim, nothing is merged over it. A host that owns no device id of its own can read the kit's: `activationJoinContext(resolveAutoDeviceKey({ appId, storage }))`. Never hand-write `userContext={{ deviceKey }}` on ``: the server's device lookup reads `device_key`, and `activationJoinContext` is what produces that shape. - **No `storage`, no injection, and since 0.13.0 a `storage` adapter that FAILS earns no injection either.** The gate used to be a bare presence check on the `storage` prop, never the success of the write, so a rejecting adapter (locked, full, or permission denied) injected a fresh `wdev_*` on every launch. That is worse than injecting nothing: the server counts `min_sessions` by distinct opens grouped on `device_key`, so a per-launch key makes that counter structurally incapable of exceeding 1 and inflates distinct-device counts. The gate now reads `IdentityRecord.durable`, true only when the id was adopted from storage or written to it successfully, and the dev warning names which of the three reasons applied. - **If your app owns its own device id, pass the SAME string on every surface.** `createAnalytics({ serverUrl, apiKey, appId, userContext: { deviceKey } })`, `useLifecycleEvents(config, { deviceKey })`, and `` (plus `createWireActivation({ deviceKey })` if you use it). Miss one surface and the kit injects its own key there, so the app's events and the onboarding session land in disjoint id spaces and `activated` still reads zero. Since 0.13.0 every surface constructed with a host-supplied device key records it on a process-wide provenance registry scoped per `appId`, and a mount that injected its own key while the process demonstrably owns a host one warns in dev and prints both ids. It warns rather than adopting the other key: which of two ids the host meant is not something construction order can decide. - `autoJoinKey={false}` opts out and restores the pre-0.12.2 behaviour, for a host that genuinely wants an unlinked session. Default is `true`. 7. Identity provenance (new in 0.13.0, root exports). Every id now carries a record instead of being a bare string. `resolveIdentity(...)` returns an `IdentityRecord` of `{ value, space, source, durable }`, where `space` is `"onboarding-session" | "app-session" | "device"`, `source` is `"host" | "auto"`, and `durable` says the value was actually persisted rather than living only in this process. `hostIdentity(space, appId)` answers the question no single mount can answer alone: does this app own a host-supplied id in that space that this mount was not given. `hydrateDeviceIdentity(...)` is the awaited, provenance-carrying sibling of `hydrateAutoDeviceKey` (which is unchanged and still returns a bare string). Most integrations never call these directly; they are why the kit now declines and says so where it used to fabricate an id and return `true`. 8. Mount the lifecycle hook. Do not skip this step: ```tsx import { useLifecycleEvents } from "@wireai/activation"; useLifecycleEvents(config, { deviceKey, sessionCount, userId }); // once, at the app root ``` It emits `app.first_open` (once ever) and `app.session_started` (per open), it registers the per-open session id that `createAnalytics`, `wire.track` and the gates all correlate to, and with `config.storage` it stamps the persisted `device_key` on `app.session_started`, which is what the server's `min_sessions` rule counts. Mount it before anything else touches analytics. Alternatives, all root exports: `wireLifecycleEvents` is the React-free counterpart and fires both events in one call, `reportFirstOpen` fires just the once-ever one, and `useSessionStart` / `reportSessionStart` cover a host that already owns an open counter but do NOT emit `first_open`. Do not call `initWireOnboarding`. It is not exported by @wireai/activation; it belongs to a backend example in the wireai-rn repo. Calling it will not resolve. Package subpath exports: `.`, `./analytics`, `./coachmarks`, `./showcase`, `./reviews`, `./questionnaire`, `./metro`. The analytics facade (`createAnalytics`, `useAnalytics`, `createScreenTracker`, `reportAppEvent`, `createEventQueue`) lives on `./analytics` only; importing it from the root does not compile. What changed in 0.13.0 that your generated code must account for: - `identifyOnboarding` no longer binds to the app-open session by default, and its return type widened from `boolean` to `"onboarding" | "app_session" | false`. The old tier-3 fallback posted the per-open app session id into a field that means the ONBOARDING session, then returned `true`, so the row could never join the onboarding funnel while the host was told it had worked. The fallback is now opt-in via `allowAppSessionFallback: true` and names itself in the return value. `"onboarding"` is truthy, so `if (await identifyOnboarding(...))` behaves identically; only an explicit `: boolean` annotation needs updating. - `wire.track()` returns `false` for an event the server DISCARDED. `POST {serverUrl}/v1/events` answers HTTP 200 with `{ ok, written, skipped }`, and only an explicit positive `skipped` demotes a 200, so an older server that sends no such field still resolves `true`. Do not treat `false` as a network error. - `OnboardingProgress.slot_id` is a stable per-slot identity for a screen. `readProgress` reads it and `deriveAnswers` prefers it over `key`; `validators` are looked up by `slot_id` first, then `progress.key`. The fallback is decided PER CARD, never cached per session, so a thread that mixes slotted and unslotted cards keys each one correctly. This matters because `key` is authored from the question's prompt text (tenant flows slugify it and cut at 32 chars), so re-wording a question mints a new key and a host reading `answers.interests` silently starts reading `undefined`. Key your `validators` map and your `answers` reads by slot where your flow has slots. Version caveat: servers running funnel releases older than 2026-07-28, self-hosted ones included, never send `slot_id` at all, and `deriveAnswers` falls back to `progress.key` per card, so always keep the key-based map alongside any slot-keyed entries. - Two `createAnalytics` instances for one `appId` no longer share one persisted queue slot: the second claimant of the appId-derived DEFAULT storage key gets a rotated key and a dev warning. An explicit `storageKey` is never rotated, since that is a host declaring which slot it owns. - Removed: `DoneBlock` (deprecated since 0.1.x, superseded by `CompletionView`) and `RESERVED_USER_CONTEXT_KEYS` (read by nothing; `EXTRA_KEY_PREFIX` is what actually enforces namespacing). Known pitfalls, pre-answered: - Forgetting `useLifecycleEvents` is the most common wiring failure: nothing throws, no request fails, and the `activated` funnel silently reads zero forever. Always pass `storage` too, or the device key is per-launch instead of per-install. - A `storage` adapter that throws or rejects is the second: since 0.13.0 the kit declines the join key rather than injecting a per-launch one, and says why in dev. Verify your adapter actually writes before you assume the funnel is wired. - EAS and cloud builds: install from the registry or a git URL, never a local `file:` path outside the app repo. EAS cannot resolve it. - Always use the `withWireOnboarding` Metro helper. A second React instance crashes React Native. - `zod` must be `^3`. Zod v4 changed the API and the SDK validates against v3. - Streaming uses XHR, not `fetch` streams, because Hermes does not expose fetch streaming. Hermes and the New Architecture are both supported. - `wireai-rn` itself is pure JS/TS with no native modules, so there is nothing to autolink for the renderer. ## Wire AI usage docs (how to use the product) - [How it works](https://getwireai.com/docs): The five-stage activation loop: onboarding, added value, AI personalization (the engine step, no variants), the in-app review and the in-app questionnaire, plus how the four versions are run and the learning loop that follows. The four versions of a tested stage are pre-generated and served deterministically; Wire never writes a step live for a user. - [Getting started](https://getwireai.com/docs/getting-started): Install @wireai/activation and wireai-rn, wire Metro with withWireOnboarding, set the env vars, and render WireOnboarding with a fallback flow and an onComplete handler. - [MCP integration](https://getwireai.com/docs/mcp): The Wire AI MCP is a hosted remote server at https://wireai-mcp.fly.dev/mcp. Connect a URL and an Authorization: Bearer header (no install, no login step). The tenant wai_ key unlocks the read loop; the admin key unlocks app management and the A/B/C/D experiments. Stdio from a kit checkout still works as a fallback. - [Skills](https://getwireai.com/docs/skills): No Claude skill ships with Wire AI, and none can be obtained. What ships is INTEGRATION_PROMPT.md, inside the published @wireai/activation package: paste it into your coding agent from the root of your app and it wires the SDK in. The hosted MCP server is the other way in. - [Billing](https://getwireai.com/docs/billing): Analytics is free to 299k events a month. The founding cohort get the engine free. After the cohort: Free, Starter (€49/mo) or Pro (€149/mo), priced on how much of the journey you test, with no usage meter on experiments. Billing is not switched on yet, so nothing charges. ## Policy and terms - [What Wire will not optimize on](https://getwireai.com/docs/what-wire-will-not-optimize-on): The three vulnerability classes Wire AI will not use as optimization inputs, and what customers may not instruct it to do: minor status and age, health condition, and financial distress. - [Terms and Conditions](https://getwireai.com/tos): The terms of service, including the Acceptable Use section listing the Annex III high-risk contexts Wire AI is not to be deployed in, and the Roles section (the customer is the deployer, Wire AI is the provider of a limited-risk system). - [Trust](https://getwireai.com/trust): Wire AI's role under the EU AI Act (provider of a limited-risk system, the customer is the deployer), the three signals it will not optimize on, its Article 25(2) specification that it is not to be changed into a high-risk system, its reasoned Article 50 transparency position pending legal review, and where the service runs. A data processing agreement and a current list of sub-processors are available on request. ## For AI agents (integrate Wire AI into an app) - [SDK agent brief (AGENTS.md)](https://github.com/chohra-med/wireai-rn/blob/main/AGENTS.md): goal, API surface, integration steps, gotchas, read this first. - MCP server (`wireai-mcp`): hosted remote endpoint https://wireai-mcp.fly.dev/mcp, connect with `claude mcp add --transport http wireai https://wireai-mcp.fly.dev/mcp --header "Authorization: Bearer "` (per-request bearer; tenant key = read tools, admin key = management + A/B/C/D experiments). No install/login; stdio-from-checkout fallback exists. Docs: https://getwireai.com/docs/mcp - [Copy-paste integration prompt](https://github.com/chohra-med/wireai-rn/blob/main/docs/agent-integration-prompt.md): hand to your coding agent (Cursor / Claude Code / Copilot / Codex) to integrate end-to-end. - [Integrate via backend (A2A)](https://github.com/chohra-med/wireai-rn/blob/main/docs/integrate-via-backend.md) · [Expo setup](https://github.com/chohra-med/wireai-rn/blob/main/docs/expo-integration.md). - Drop-in onboarding kit ``, themed; props + ordered steps in its AGENTS.md (ships with the package). - A2A agent-card for machine capability discovery: `/.well-known/agent-card.json` on the tenant backend. ## Concepts (glossary) - [Generative UI for Mobile](https://getwireai.com/glossary/generative-ui-for-mobile) - [A2UI Protocol](https://getwireai.com/glossary/a2ui-protocol) - [Dynamic Onboarding](https://getwireai.com/glossary/dynamic-onboarding) - [Streaming UI](https://getwireai.com/glossary/streaming-ui) ## Onboarding examples - [Food Recommendation](https://getwireai.com/onboarding/food-recommendation) - [Mental Health](https://getwireai.com/onboarding/mental-health) ## Free resources (lead magnets, via the Code Meet AI newsletter) - [Onboarding resources on the product page](https://getwireai.com/onboarding#resources) - The Onboarding Psychology Playbook (free PDF): the psychology Cal AI and Duolingo run, the six-stage onboarding arc, and the per-screen measurement loop. Via https://codemeetai.substack.com - The Onboarding Verification Prompt (copy-paste): a self-contained prompt that audits any mobile onboarding flow screen by screen. Via https://codemeetai.substack.com ## Comparisons - [vs Crayon](https://getwireai.com/vs/crayon) - [vs LangChain UI](https://getwireai.com/vs/langchain-ui) - [vs Tambo](https://getwireai.com/vs/tambo) ## Install - npm: https://www.npmjs.com/package/wireai-rn - GitHub: https://github.com/chohra-med/wireai-rn ## Contact - Email: malik@getwireai.com