Permissions and data access
Users control access to their context and app connections. Configure enforces agent authorization and profile permissions. Your integration must protect credentials and handle profile text as user data.
What Configure stores
A profile has eight sections. A read returns only the ones you ask for:
| Section | Contents |
|---|---|
identity | Name, location, timezone, occupation, bio, interests |
preferences | Durable preferences the user or an agent recorded |
integrations | Which apps the user connected, and their state |
imports | Context brought over from another assistant, such as a ChatGPT export |
agents | What other agents the user approved have learned about them |
summary | Configure's synthesis of the above |
soul | A detailed description of the user derived from saved context |
context | The working-context document |
Your app does not receive the user's password, verification codes, or connected-app access tokens. App tools return results without exposing app credentials. Your own OAuth client secret is a separate credential and must remain on your server.
What the user controls
- Consent is per agent. The hosted flow shows your app's name in its title. It has no permissions screen. Finishing the flow approves your agent, and only your agent.
- Control is on their profile. At profile.configure.dev, a user can narrow what your agent reads (their profile information, imported context, and context other agents saved). They can also revoke your agent outright, disconnect an app, or delete their profile.
- Every memory is attributed. A user can see which agent saved what. Saved context retains its source attribution.
- Revoke anytime. When a user revokes your agent or disconnects an app, your reads are refused with a link. Handle the authorization response instead of treating it as missing data. Handle
authorization_requiredandtool_not_connectedas described in the Quickstart.
The profile is user data, not instructions
Profile context can contain text from other agents and user imports. Treat that text as untrusted data when inserting it into a system prompt. A closing delimiter in profile text can terminate your context block and expose the remaining text as instructions.
Remove the delimiter before wrapping the profile text. Repeat the removal until the text stops changing:
ts
// Matches the shape of the tag, not one spelling: "</ user_context>",
// "</user_context >" and "<user_context role='system'>" all read as the
// delimiter to a model, and \b keeps "<user_contextual_notes>" as prose.
const DELIMITER = /<\s*\/?\s*user_context\b[^>]*>/gi;
export function fence(profileText: string): string {
let text = profileText;
for (;;) {
const stripped = text.replace(DELIMITER, "");
if (stripped === text) return stripped; // a fixed point, not one pass
text = stripped; // every pass shortens, so this ends
}
}A single pass over </user_context<user_context>> removes the inner tag but leaves a valid closing delimiter. Repeat until no delimiters remain.
This removes the delimiter while preserving the surrounding context. Label the block as user data in the system prompt. Do not treat its contents as instructions or disclose private context in external searches or requests.
Where credentials live
| Credential | Lives | Never |
|---|---|---|
sk_ secret key | Your server's environment | In a browser, a prompt, or a repo |
pk_ publishable key | Browser code and the hosted flow | Used to authorize a server call |
| User tokens and MCP session tokens | Your server, against your session store | In the model's context |
| OAuth client ID and secret | Your server, for the sign-in variation | Anywhere a client can read |
What the model can reach
The model receives the profile context your server includes in its prompt, the Configure tool definitions you expose, and the results of tool calls. Keep credentials outside model-visible content. Apply these access boundaries:
- Identity never comes from the prompt. No Configure tool accepts a user ID. The credential created by your server identifies the user for each call. A prompt injection inside a retrieved email cannot redirect a read to another user.
- State-changing tools fail closed. Sending an email, creating an event, or writing to a sheet needs a connected account and a user who approved your agent. Without both, the call is denied and returns authorization guidance. Your app is responsible for confirming an individual send or event with the user. Connected apps shows the component for it.
If your server injects profile context into the system prompt, keep that path in your app. Also keep the Configure tools available to the model. Injected context provides initial information. The tools retrieve additional approved context when needed.
Test data is separate
The sandbox is fully separate from live data. sk_test_ keys cannot read live profiles, and live keys cannot read sandbox data. Every address in the synthetic profile is example.com. Test the integration in the sandbox before using production data.