Inline UI Components
Use Configure hosted UI for consent, profile seeding, connector setup, and action approval. Use the server-side SDK for profile reads, model tools, tool execution, and memory writes.
For chat products with sign-in, pair these components with Continue with Configure: SSO authenticates the user, then inline Configure lets them manage profile permissions and connect tools without leaving the chat. Use Link-only when your product has no sign-in flow or no place for an SSO button.
Add Configure to chat
For chat products, place Configure in the same + menu that holds images and files. If the user already completed Continue with Configure, this row should behave as "Manage Configure" and open permissions, connectors, and personalization. If the user has not authenticated with Configure yet, it falls back to Configure Link and returns an agent-scoped token after consent.
html
<script src="https://configure.dev/js/configure.js"></script>
<div id="personalization-entry"></div>
<script>
Configure.personalizationButton({
el: "#personalization-entry",
publishableKey: "pk_...",
agent: "your-agent",
agentName: "Your Agent",
personalizationLabel: "Manage Configure",
placeholder: "Ask your agent anything",
font: "Inter, -apple-system, BlinkMacSystemFont, sans-serif",
onImage: () => openImagePicker(),
onFile: () => openFilePicker(),
onEvent(event) {
if (event.type === "configure:linked") {
fetch("/api/configure/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: event.payload.token }),
});
}
},
});
</script>For SSO-authenticated users, keep OAuth access and refresh tokens on the backend. Hosted Configure UI can reuse the Configure-origin session created during SSO. Pass a browser-safe Configure handoff token or userId only when your backend intentionally returns one for hosted UI; never pass OAuth access or refresh tokens to browser JavaScript.
The Images and Files rows belong to your app. The helper emits configure:image-select and configure:file-select, and also accepts onImage and onFile callbacks.
The Personalization row emits configure:personalization-open when it needs to open Link, and configure:personalization-toggle when an already-linked user turns personalization on or off locally. Use showImages: false, showFiles: false, data-hide-images, or data-hide-files if the host owns a narrower menu.
If your app already has an inline integrations list instead of a + menu, use the Configure lockup variant. It renders a rounded rectangle integration button with the white Configure lockup on Configure grey. Pressing it opens inline Configure in the chat flow.
js
Configure.personalizationButton({
el: "#configure-integration",
publishableKey: "pk_...",
agent: "your-agent",
agentName: "Your Agent",
personalizationLabel: "Manage Configure",
variant: "integration",
onEvent(event) {
if (event.type === "configure:linked") {
fetch("/api/configure/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: event.payload.token }),
});
}
},
});Declarative equivalent:
html
<div
data-configure-personalization
data-publishable-key="pk_..."
data-agent="your-agent"
data-agent-name="Your Agent"
data-placeholder="Ask your agent anything"
data-image-label="Images"
data-file-label="Files"
data-font="Inter, -apple-system, BlinkMacSystemFont, sans-serif">
</div>Integration-list equivalent:
html
<div
data-configure-personalization
data-variant="integration"
data-publishable-key="pk_..."
data-agent="your-agent"
data-agent-name="Your Agent">
</div>Settings page or static button
This path is not for chat products. Use it only when there is no chat composer to attach to: a settings page, an integrations screen, or a standalone button. Use the declarative data-configure-link trigger and read the token from event.detail.token:
html
<script src="https://configure.dev/js/configure.js"></script>
<button
data-configure-link
data-publishable-key="pk_..."
data-agent="your-agent">
Personalize
</button>
<script>
document.addEventListener("configure:linked", (event) => {
fetch("/api/configure/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ token: event.detail.token }),
});
});
</script>Token event shapes differ by entry point: Configure.personalizationButton({ onEvent }) exposes the token at event.payload.token; the declarative configure:linked DOM event exposes it at event.detail.token. Send only the token to the backend; never put it in the model prompt.
Backend step
After Continue with Configure, use the server-side OAuth access token. After Link fallback, send only the configure:linked token to your backend. In both cases, create the profile object on the server with a client built from your sk_ key (see Installation; the browser pk_ key does not work server-side):
ts
import { Configure } from "configure";
const configure = new Configure({ apiKey: process.env.CONFIGURE_API_KEY, agent: process.env.CONFIGURE_AGENT });
const profile = configure.profile({ token });
const tools = profile.tools({
connectors: ["gmail", "calendar"],
});Alternatively, pass the same access token to an MCP client pointed at https://mcp.configure.dev. No SDK code is required; the tools surface natively.
The model receives Configure tool definitions and Configure tool results, not browser credentials, raw tokens, or user IDs. Use configure_profile_read and configure_profile_search when a turn needs overview, a specific memory, or source-attributed detail. The default tool set from profile.tools() is configure_profile_read, configure_profile_search, configure_profile_remember, and configure_profile_forget, so the model can also save durable facts and delete its own memories when the user asks.
Connector Setup
Show connector state with the hosted connections UI:
js
Configure.connections({
el: "#configure-connections",
publishableKey: "pk_...",
agent: "your-agent",
connectors: ["gmail", "calendar", "drive", "notion", "sheets"],
token,
});After a user connects Gmail, Calendar, Drive, Notion, or Google Sheets, your server may opt into matching connector tools:
ts
profile.tools({ connectors: ["gmail"] });Actions
Use the hosted approval UI to collect explicit approval before running action tools:
ts
profile.tools({ actions: ["email.send"] });Mount the hosted approval component with Configure.toolApproval:
js
Configure.toolApproval({
el: "#configure-approval",
publishableKey: "pk_...",
agent: "your-agent",
token,
params: { to: "sam@example.com", subject: "Quarterly recap" },
actionId: "act_123",
});The component helps capture user approval for a specific operation. Your server still decides which action tools your app supports and must execute only authorized model tool calls with profile.executeTool().