# Connection Card

> Pattern 03 · Granting access · part of Agent Consent Patterns.
> Human page: https://agentconsent.dev/patterns/connection-card/

Keep a standing grant visible after the moment of consent: the tile where a connected agent shows what it can do, when it last did it, and how to pause or revoke it.

## Problem

Consent has a half-life. The Scoped Grant screen gets a careful read at connect time and is never seen again. The connection recedes into a settings page nobody visits, quietly retaining capabilities the user has forgotten about. Months later the agent still holds write access to a mailbox for a task that ended in March. Nothing surfaces that the grant is still live, still in use, still exposed if the integration is breached. The dangerous state isn't the grant; it's the grant that has gone invisible. Users can't reconsider what they can't see, and they can't revoke what they've forgotten exists.

## Solution

Give every standing grant a durable home that answers the questions a user would ask if they remembered to: what can this agent do, is it still active, when did it last act, and how do I stop it. The Connection Card is that surface: a settings tile per connection that shows:

- **Current grant state.** The active capabilities, each with its access level, so the standing permission is legible at a glance rather than buried in an OAuth record.
- **Status.** Active, paused, needs re-auth, or expired, as text, so a lapsed or paused connection announces itself.
- **Recency.** When the agent last used the connection, and ideally what it did, linking forward to the [Action Receipt](/patterns/action-receipt/).
- **Reversal.** Pause (a reversible stop) and revoke (disconnect), so backing out is always one affordance away.

> **Live demo** — an interactive Connection Card demo runs on the page: https://agentconsent.dev/patterns/connection-card/

The demo is the `ConnectionCard` component from `@agentconsent/react`. Pause flips the status badge and the recency line; revoke disconnects. Unlike the decision-flow patterns, the card takes no approve/reject callbacks of its own. You wire its management buttons to your own handlers.

## Anatomy

> **Anatomy** — a labeled breakdown of the Connection Card component's parts is shown on the interactive page: https://agentconsent.dev/patterns/connection-card/

## When to use it

- **Any standing agent connection** the user might later want to review, pause, or revoke: the settings-page representation of a grant made through Scoped Grant.
- **A connections list**, where each integration is one card and the set is scannable for "what does this agent still have access to?"
- **Surfacing lifecycle changes.** An expired token or a scope that now needs re-consent should show up here as a status, not as a silent failure the user discovers when the agent stops working.

## When not to use it

- **At the moment of granting.** The card reflects an existing grant; it is not the consent screen. Use Scoped Grant to establish access and Progressive Scope to widen it.
- **For one-off, session-scoped permissions** that expire when the task ends. A card implies a standing grant worth managing; a transient allowance doesn't need a home in settings.
- **As the audit log.** The card shows *current* state and last use, not the full history of what the agent did. That record is the [Action Receipt](/patterns/action-receipt/).

## Real-world examples

- **Google Account → "Third-party apps & services."** One entry per connection: what the app can access, when access was granted, and a single **Remove access** action. The closest shipped ancestor of this pattern, standing grants made visible and revocable in one place.
- **GitHub's authorized applications.** Settings → Applications lists every OAuth and GitHub App with its scopes and a revoke action, plus when it was last used. The last-used date is the load-bearing detail: it's what lets a user spot the connection that no longer earns its authority.
- **Agent-product connector settings.** Claude's and ChatGPT's connector pages carry the same anatomy into agent-native products, each connected tool or MCP server listed with what it reaches and a disconnect control. The connections list is becoming the agent era's permission manager.

*Annotated screenshots of these flows are being collected. Products are credited, annotations follow the site-wide callout conventions, and any screenshot is removed on request. See [About](/about/).*

## Accessibility

- The card is an `<article>` labeled by its title, so screen-reader users can navigate a connections list card by card and hear which connection each one is.
- The title is a plain element with an id (not a fixed heading level), so the card slots into a settings list at whatever heading depth the surrounding page uses without breaking heading order.
- **Status is text, not a colored dot**, "Needs re-auth" is announced; the badge color is redundant reinforcement.
- Active capabilities are a real list, each access level rendered as a text badge, so the standing grant is enumerable by assistive tech rather than implied by iconography.
- Recency and dates are a definition list (`<dl>`), keeping each label bound to its value.
- Management actions are ordinary buttons in a consistent order; the destructive revoke is distinguished by more than color (position, label, and a `data-tone` hook you can pair with a confirmation).

## Anti-patterns

- **The write-only grant.** Access requested through a rich consent screen, then represented afterward by nothing at all, or a bare "Connected ✓" with no way to see or change scopes. The grant outlives the screen; its representation must too.
- **Revoke buried or absent.** If disconnecting takes a support ticket, the grant is effectively permanent. Revoke belongs on the card.
- **Status by color alone.** A green or red dot with no words fails anyone who can't distinguish them and communicates nothing precise to anyone who can.
- **Stale recency.** "Last used" that never updates, or is absent, hides exactly the signal that tells a user a forgotten grant is still being exercised.
- **Silent lapse.** Letting a connection expire or fall out of authorization without ever surfacing it, so the first sign of trouble is the agent failing mid-task. Show "needs re-auth" as a status.

## Code

```tsx
import { ConnectionCard } from "@agentconsent/react";
import "@agentconsent/react/theme.css";

<ConnectionCard.Root status="active">
  <ConnectionCard.Header>
    <ConnectionCard.Icon>✉</ConnectionCard.Icon>
    <ConnectionCard.Title>Inbox Assistant → Gmail</ConnectionCard.Title>
    <ConnectionCard.Status />
  </ConnectionCard.Header>

  <ConnectionCard.Scopes>
    <ConnectionCard.Scope access="read">Read “Board 2026” label</ConnectionCard.Scope>
    <ConnectionCard.Scope access="write">Send replies</ConnectionCard.Scope>
  </ConnectionCard.Scopes>

  <ConnectionCard.Meta>
    <ConnectionCard.MetaItem label="Last used">
      2 hours ago, sent 1 reply
    </ConnectionCard.MetaItem>
    <ConnectionCard.MetaItem label="Connected">Mar 3, 2026</ConnectionCard.MetaItem>
  </ConnectionCard.Meta>

  <ConnectionCard.Actions>
    <ConnectionCard.Action onClick={openScopeManager}>Manage</ConnectionCard.Action>
    <ConnectionCard.Action onClick={pause}>Pause</ConnectionCard.Action>
    <ConnectionCard.Action tone="danger" onClick={revoke}>Revoke</ConnectionCard.Action>
  </ConnectionCard.Actions>
</ConnectionCard.Root>
```

`Status` renders the label for the `status` prop by default (`active`, `paused`, `needs-reauth`, `expired`); pass children to override the wording. This is a display surface, so the management buttons are yours to wire. A consequential revoke is a natural place to compose the Irreversibility Gate. All parts are unstyled primitives with `data-acp` attributes; skip `theme.css` and style them yourself, or override the `--acp-*` tokens to retheme.
