seekrit
← all posts

Your agent needs a Disconnect button as much as a Connect button

Vault

A customer connects their email so your agent can prepare a daily briefing. A month later, they change roles. They still want the assistant, but they no longer want it reading that account.

They should be able to see the connection and disconnect it. Your agent should stop trying to use it. A job already queued for tomorrow should not silently restore the access they removed.

Those are product behaviors you need after the first successful API call. Seekrit Vault supplies the connection states and controls your application can build around, including a hosted page where customers can manage their own connections.

Make account access visible

Your app can create a manage link for the authenticated customer:

import { Vault } from "@seekrit/sdk/vault";

const vault = new Vault();

const manage = await vault.manage.create({ userRef: "u_123" });
// Show manage.url only to the customer represented by u_123.

That page lists the customer's connections in your project and lets them disconnect. They do not need a Seekrit account or a support ticket. Your app can put the link behind a "Connected accounts" entry in settings or offer it when the customer asks what the assistant can access.

Create it from authenticated backend state and deliver it privately. A manage link carries authority over the connections it displays; it is not something the model needs to inspect or retain in a conversation transcript.

Distinguish a broken connection from a withdrawn one

Your product should respond differently to these states:

StateWhat your app can do
activeAttempt the authorized task; provider errors are still possible.
reauth_requiredPause affected work and offer a reconnect link with a clear explanation.
revokedStop using the connection. Require a new connection flow if the customer chooses to grant access again.

Active connections can require reauthentication and return to active after reconnecting. Active or broken connections can be revoked; renewed access then needs a new connection.

Reconnect repairs a grant. Revocation ends it; future access needs a new connection.

A reconnect repairs an existing connection. Your backend creates a Connect session with purpose: "reconnect" and the same connectionId, customer reference, and provider. The customer supplies fresh authorization and Vault stores the next credential revision.

Revocation means the customer or platform withdrew access. Treat it as a decision. A revoked connection cannot be repaired through the reconnect flow; a new grant starts with a new connection.

This backend helper offers a repair only for the right customer and state:

async function reconnectForCustomer(userRef: string, connectionId: string) {
  // Both arguments must come from authorized application state.
  const connection = await vault.connections.get(connectionId);
  if (connection.userRef !== userRef) {
    throw new Error("Connection belongs to another customer");
  }
  if (connection.status !== "reauth_required") {
    throw new Error("This connection does not need a reconnect");
  }
  return vault.connect.create({
    userRef,
    connectionId: connection.id,
    providerId: connection.providerId,
    purpose: "reconnect",
  });
}

Return the resulting link to that customer's UI. If the connection is revoked between the check and link creation, handle the refusal rather than automatically creating a new grant.

What Disconnect stops

Vault revocation deletes the stored credential ciphertext and refuses future releases. Credential write-backs cannot revive a revoked connection. That matters when an OAuth refresh or browser session overlaps with the customer pressing Disconnect.

Revocation cannot recall an API request already dispatched, undo a sent message, or erase account data your application previously retrieved. Your own job cancellation and data-retention behavior must handle those cases.

There is also a difference between revoking in Vault and revoking the grant at the provider. vault.connections.revoke(id) revokes in Vault. The executor's revoke endpoint additionally attempts provider-side revocation where configured; that provider step is best effort. Explain which control your product offers instead of implying every token everywhere disappears.

Let events drive the experience

Vault emits signed connection.ready, connection.reauth_required, and connection.revoked webhooks. Your backend can use them to update the connected-accounts screen, pause scheduled work, or offer a reconnect when the customer next opens the app.

Verify signatures, deduplicate deliveries, and reconcile with current connection state before resuming work. Events help the UI react; the executor's release checks remain the enforcement point if an event arrives late. Payloads carry connection metadata rather than credential values.

The signature check should use the raw request body. This handler skeleton accepts a delivery only after your application durably queues it:

import { verifyWebhook } from "@seekrit/sdk/vault";

async function handleVaultWebhook(request: Request, webhookSecret: string) {
  const event = await verifyWebhook({
    secret: webhookSecret,
    headers: request.headers,
    body: await request.text(),
  });
  if (!event) return new Response("Invalid signature", { status: 401 });
  if (event.type === "ping") return new Response(null, { status: 204 });

  // Application helper: atomically store once by event.id, then enqueue.
  // Throw on failure so the sender can retry instead of losing the event.
  await enqueueVaultEventOnce(event);
  return new Response(null, { status: 204 });
}

webhookSecret is the secret returned when you registered the endpoint. enqueueVaultEventOnce is your durable queue or database integration. Its consumer should fetch current connection state and update your UI or jobs idempotently; a delayed connection.ready must not restart a revoked connection. Signature verification alone does not deduplicate deliveries.

For an agent company, this means you can build the experience of granting, repairing, and withdrawing access around one connection lifecycle. You can explain what the assistant can reach and give the customer a working way to change it. The manage links and webhook guide shows the integration details.