Ephemeral containers and claim
Your agent can connect a user who has no Wire account. They get a fully working ephemeral container with a 7-day lifetime: same tools, same MCP endpoint, no signup. When they’re ready to keep it, the SDK upgrades the container to permanent without the user ever leaving your agent.
This is the no-account onboarding flow: connect first, let the user try things, prompt to claim before the container expires.
Know when a container is ephemeral
Section titled “Know when a container is ephemeral”Two surfaces tell you:
connection.expiresAtis non-null on an ephemeral connection and tells you when the container lapses.getStatus(apiKey)returnscontainer.isEphemeralandcontainer.ephemeralExpiresAt, so you can check at any time and decide when to prompt.
Claim, the blocking way
Section titled “Claim, the blocking way”const claimed = await client.claim(connection.apiKey, { onUserPrompt: ({ url }) => { myUi.show(`Sign up to keep your container: ${url}`); },});// claimed.expiresAt === null, the container is permanentclaim() mints a single-use claim link, hands it to your onUserPrompt handler (or prints it and opens the OS browser if you don’t pass one), and resolves once the user finishes signing up. All their data, the MCP URL, and the apiKey stay exactly the same.
Semantics worth knowing:
- Calling
claim()on an already-claimed container resolves immediately with the current snapshot. It’s safe to call twice. - If the user doesn’t finish within five minutes (configurable via
timeoutMs),claim()throwsCLAIM_TIMEOUT. The link itself stays valid for 30 minutes, so the user can still finish in the browser, and a latergetStatus()will show the container as permanent.
Claim, the non-blocking way
Section titled “Claim, the non-blocking way”Turn-based agents shouldn’t hold a promise open while a user signs up. Mint the link, show it, and detect completion on your own schedule:
const { url, expiresAt } = await client.getClaimUrl(connection.apiKey);myUi.show(`Sign up to keep your container: ${url}`);
// Any later turn:const status = await client.getStatus(connection.apiKey);if (!status.container.isEphemeral) { // claimed, celebrate accordingly}getClaimUrl() mints the link and nothing else. It throws ALREADY_CLAIMED if the container is already permanent, which doubles as a cheap “does this still need claiming” check.
Timing the prompt
Section titled “Timing the prompt”ephemeralExpiresAt gives you the deadline. A pattern that works well: prompt once when meaningful data has accumulated (the user now has something to lose), then again as expiry approaches. Avoid prompting on first contact; the whole point of the flow is that the user experiences value before being asked to sign up.