Add Configure to onboarding
This is the Quickstart for a surface that is not a chat: an onboarding step, a settings row, a first-run screen. Everything else on the Quickstart still applies, the credentials, the daily refresh, the commit, and the tools; only the entry point and the return change, and this page is those two things.
Two names below come from the Quickstart, and they are yours:
ts
import { Configure } from "configure";
export const configure = new Configure({ apiKey: process.env.CONFIGURE_API_KEY, agent: process.env.CONFIGURE_AGENT });
export const profileFor = (userId: string) => configure.profile({ externalId: userId }); // one handle per user, keyed by your id
// The daily read, also run once on the return. Returns null until the user has connected.
export async function refreshContext(userId: string) {
const read = await profileFor(userId).read({ sections: ["identity", "preferences", "summary", "integrations"] });
if (!read.profile.linked) return null;
const text = read.profile.format();
await store(userId, text); // `store` is your database: one string per user
return text;
}Onboarding is not a chat, so there is no fixed message and no card. The entry point is your own button with its own label, and the click goes to a route on your server that sends the user to Configure's page. Pass returnUrl on the mint and Configure brings them back there when they finish, connected. Your return route refreshes their context (Quickstart, step 5) and moves on to the next screen, which can now be filled in from their profile instead of asked.
ts
const RETURN_URL = "https://yourapp.com/onboarding/return"; // a constant, never from the request
// The onboarding step's button goes here.
app.get("/onboarding/connect", async (req, res) => {
const connect = await profileFor(req.user.id).connect({ returnUrl: RETURN_URL });
res.redirect(connect.connect_url); // Configure's page, then back; a user who already connected lands straight back
});
// Configure sends the user here when they are done.
app.get("/onboarding/return", async (req, res) => {
const context = await refreshContext(req.user.id); // reads the profile; null until linked
if (!context) return res.redirect("/onboarding?step=2¬ice=not-connected");
res.redirect("/onboarding?step=3");
});Two rules for the return:
returnUrlmust behttps(orhttpon localhost while you develop), and it is a constant, never built from the request. Configure forwards the user there without a click when the browser'sRefererorigin matches it, which the default policy sends, or when its host is inallowed_return_hostson your developer account. Any other destination gets a button with the host spelled out, so a Configure page never sends someone onward silently. That list is not the same thing asnpx configure add origin, which registers an OAuth callback and has no effect here.- Trust the profile, not the URL. The return route reads
read().profile.linkedand decides from that; anyone can type the return address into a browser.


What you can pre-fill, from read({ sections: ["identity", "summary", "integrations"] }):
| Field | Where it comes from |
|---|---|
identity.given_name, identity.family_name, identity.email | The account the user signed in with. identity.email_verified says whether Configure verified it. |
identity.role, identity.occupation, identity.location, identity.company_website | Derived from the user's memories. A thin profile leaves them null, so treat each as a default, not a fact. |
integrations.gmail.connected, and the same for calendar, drive, notion, sheets | Which apps the user connected. Show the connected ones as already on. |
summary | One paragraph on who the user is and how they like to work. |
Anything still null after the return is a question for the next screen, not a blocker. A user who skips this step is not lost: the chip in your chat (Quickstart, step 2) offers the same trip later, and the card takes it from there.

An app that uses Configure only in onboarding still runs step 5: the profile keeps growing everywhere else the user takes it, and a snapshot from sign-up day goes stale.
Next
- The chat surface, the card, and the rest of the loop: Quickstart.
- The button for this step, and the connected state: Components.