# AI disclosure

A plain notice that the person is interacting with an AI system: a first line in the thread (`variant="line"`) or a compact "AI" badge for a thread header (`variant="badge"`) that opens to the app's own explanation. It helps an app tell people they're talking to an AI, as transparency rules such as Article 50(1) of the EU AI Act ask; whether a given placement meets those rules, and what else applies, stays the deployer's call. The agent's name and any details come from the app, never from model text. It's static: read in place, never announced as a live update.

- Registry name: `ai-disclosure` (`@candor/ai-disclosure`)
- Tier: Free (MIT). No licence key needed.
- Docs: https://candor.themethodic.com/docs/ai-disclosure

## Install

```bash
npx candor-ui add ai-disclosure
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/ai-disclosure`.
It brings in: button, chat, locale, popover, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { AiDisclosure } from "@/components/ai-disclosure"
import type { AgentIdentity } from "@/lib/chat"

const agent: AgentIdentity = { id: "support", name: "Support assistant", role: "specialist" }

export default function Example() {
  return (
    <div className="flex max-w-xl flex-col gap-4">
      <div className="flex items-center gap-2 border-b pb-2 text-sm font-medium">
        Support assistant
        <AiDisclosure
          agent={agent}
          variant="badge"
          details="Run by the support team. It reads your past tickets to answer; a person reviews refunds."
          onLearnMore={() => {}}
        />
      </div>
      <AiDisclosure agent={agent} details="Ask for a person at any time." onLearnMore={() => {}} />
      <AiDisclosure />
    </div>
  )
}
```

## <AiDisclosure>

Props:

- `agent?: AgentIdentity | string | undefined`: The agent, named by the app: an AgentIdentity or a plain name. Left out, the notice says "an AI system". Never model text.
- `variant?: "line" | "badge" | undefined` (default `"line"`): "line" (the default) for a first line in the thread; "badge" for a compact mark in a header, e.g. ThreadHeader's. Place each where it fits.
- `details?: string | undefined`: The app's own plain text about the system: who operates it, what data it uses, how to reach a person. Shown under the line, or in the badge's explanation.
- `onLearnMore?: (() => void) | undefined`: Opens the app's own page or dialog about its AI use. A callback, never a URL from the model. Shows a "Learn more" button.
- `className?: string | undefined`

## Strings (`aiDisclosure`)

The fixed words, English by default. Override any of them under `aiDisclosure` in `<LocaleProvider strings={{ aiDisclosure: { … } }}>`; the table is exported as `aiDisclosureStrings`.

- `line`: {name} is an AI system, not a person.
- `lineUnnamed`: You're interacting with an AI system, not a person.
- `badge`: AI
- `badgeLabel`: {name} is an AI system
- `badgeLabelUnnamed`: AI system
- `about`: About {name}
- `aboutUnnamed`: About this AI system
- `learnMore`: Learn more

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
