The loop
Every Configure integration is the same story. A user signs in with Configure once. Your product now holds their portable context. From then on, your agent uses it consistently: it reads the profile at the start of every conversation, uses the profile tools during the turn, and writes back what it learned after the turn. That cycle (read, use, write back) is the loop. Everything else in these docs is a way to wire it.
A rendered sign-in button is not an integration. Stored tokens are not an integration. The integration is the loop running on every conversation.
The ideal pattern is MCP
If your agent or platform can speak MCP, connect it to https://mcp.configure.dev and stop: the configure_* tools appear natively, sign-in happens through links the configure_connect tool mints, and the loop below runs through tool calls with no integration code. That is the ideal shape: least code, always current, works in any MCP host.
Use the SDK when you own the app's UI, auth flow, and model loop and want in-process control. The loop is identical; only the wiring differs.
The loop, step by step
1. Read at the start of every conversation. One configure_profile_read (MCP) or profile.read() (SDK) loads who you are talking to: identity, preferences, key facts, connected apps. Do not call it repeatedly in the same conversation.
2. Use the tools during the turn. The model holds the profile tools the whole turn: configure_profile_search when a question is not answered by context in hand, connector tools (configure_gmail_search, configure_calendar_get, ...) when the user asks about their mail, calendar, files, or notes, and configure_profile_remember the moment the user states something durable.
3. Write back after the turn. configure_profile_commit (MCP) or profile.commit({ messages, response }) (SDK) closes the turn: it clears the obligations reads created and saves memories the turn earned. A loop that never writes back leaves the profile frozen at sign-in; the user's next conversation, anywhere, should already know what this one learned.
One complete conversation
The loop on a real turn, with real shapes. The user is signed in and asks: "Book my usual Tuesday slot and remind me what my trainer said last week."
jsonc
// 1. Start of conversation: one read.
→ configure_profile_read {}
← { "identity": { "name": "Dana Reyes" },
"top_facts": [{ "text": "[health] Trains with coach Mira, Tuesdays 7am", "source": "agents/atlas" }],
"integrations": { "gmail": { "connected": true }, "calendar": { "connected": true } } }
// 2a. The question needs mail the profile summary does not carry.
→ configure_gmail_search { "query": "from:mira training plan", "max_results": 3 }
← { "emails": [{ "subject": "This week: tempo intervals", "snippet": "Focus on ...", ... }] }
// 2b. The user's ask implies a durable fact worth keeping.
→ configure_profile_remember { "fact": "Prefers the 7am Tuesday training slot booked automatically" }
← { "memory": { "id": "mem_9f2...", "path": "/agents/your-agent/..." } }
// 3. After the reply: close the turn.
→ configure_profile_commit { "messages": [ ...bounded turn evidence... ] }
← { "status": "completed", "facts_written": [], "memories_written": [],
"obligations_committed": ["read_7a1..."], "rejected_memories": [] }The reply the user sees quotes the trainer's email and confirms the booking. The profile now carries the booking preference for every future agent the user allows.
When the loop breaks
- The read returns
authorization_required: the user is not signed in. This is a sign-in problem, not missing data: never tell the user you have nothing on them. Callconfigure_connect, and reply with one sentence plus the returned link on its own line. Do not retry the read until they sign in. - A connector call is refused (
permission_needed, or an app is not connected): the refusal carries the link that fixes it. Give the user that link; do not construct one yourself and do not treat the refusal as an error to hide. -32009 commit_required: a read created an obligation this turn has not cleared. Commit first, then repeat the call that was blocked:configure_profile_commiton MCP,profile.commit()from the SDK. Repeating the call without committing fails the same way, andconfigure_connectis not the fix (this is not a sign-in problem).- Mid-conversation token expiry (SDK/SSO): refresh server-side and continue; an auth failure is not an empty profile, so never answer from a failed read as if the user had no data.
Day-2 habits: what to save, and what not to
The loop's quality is the profile's quality.
- Save durable facts the user states (preferences, goals, personal details), one fact per
remembercall, and letcommitcapture turn-level learnings. - Do not save your own work logs, one-off task context, or anything the user did not say or clearly imply. Your status notes for other agents belong in a
projects/<slug>box, not in the user's facts. - Bulk context (a pasted transcript, a long document, "keep all of this") goes through
configure_profile_import, not twenty remember calls. - Wrong or stale memories: delete your own with
configure_profile_forget. Use reasoncorrectionwhen you saved it wrong; useuser_requestonly when the user wants it gone for good; that also blocks it from re-import.
Where to go next
- Wiring the loop with the SDK in your own model loop: Handling Tool Calls
- The full working doctrine for an agent inside a product: Adding Configure to your agent
- The MCP surface end to end: Configure MCP
- Sign-in itself (button, callback, tokens): Configure OAuth
- Rehearse the whole loop against a synthetic user first: Test mode (sandbox)