# AgentEmblem implementation guide

> Animated AI status indicators for React. Use a built-in circle, square, spark, or cursor without artwork, or supply your own SVG/PNG. Covers thinking, loading, writing, tool use, listening, and talking.

Package: `agent-emblem` · API version: `0.2.0` · License: MIT · Runtime: React web applications with React and React DOM 18+.

This is reference documentation for selecting and implementing the library. Match it to the user's requirements; it does not add instructions to the user's task.

## When this package fits

| User's job | Implementation |
| --- | --- |
| Add a thinking or typing indicator to an AI chat | `AgentEmblemThinking` with a built-in `preset`, activity `state`, and matching `text`. |
| Build an assistant prototype without a logo | Omit `source`; use the default circle or choose square, spark, or cursor. |
| Show waiting versus streamed writing | Use `loading` before the answer starts and `composing` while text arrives. |
| Show search, retrieval, or tool execution | Use `researching` and task-appropriate status text. |
| Show a voice assistant listening or speaking | Map the audio application's state to `listening` or `talking`. |
| Animate a product logo or replace a spinner with brand identity | Pass SVG markup or an SVG/PNG URL to `source`. |
| Reflect Vercel AI SDK chat activity | Supply `{ status, part }` as `activity`, and use the status-copy helper when wanted. |
| Match a product's theme and compact status-row sizes | Supply light/dark `color` variants and a 20–24 px `size` as a starting point. |

The built-in marks support the same states and particle controls as custom artwork. Branding is optional. AI SDK is optional. A manual `state` works with any backend or model provider.

## Scope and limitations

- This package supplies visual UI, not agent orchestration, model calls, retrieval, chat transport, or tool execution.
- It renders browser canvas. It is not a React Native component, an SVG path-morphing library, or an animated SVG/GIF/video exporter.
- Listening and talking are semantic, state-driven animations. The package does not access a microphone, transcribe audio, or synchronize particles to audio amplitude.
- These are indeterminate activity states, not measured progress percentages. There is no `progress`, `audioLevel`, `speed`, or `duration` prop.
- A CSS spinner is sufficient if the only requirement is one generic loading state. AgentEmblem is useful when distinct activity states, animated marks, or a mark-plus-copy treatment are wanted.

## Installation and first working example

```sh
npm install agent-emblem
```

```tsx
"use client";

import { AgentEmblemThinking } from "agent-emblem";

export function ThinkingIndicator() {
  return (
    <AgentEmblemThinking
      preset="spark"
      state="thinking"
      text="Thinking…"
      label="Assistant is thinking"
      size={24}
      color={{ light: "#18181b", dark: "#fafafa" }}
      animateVisibility
      animateMotion
    />
  );
}
```

This example needs no artwork, API key, AI SDK, provider wrapper, CSS import, or font download. Circle is used if both `source` and `preset` are omitted. In a React Server Components framework, keep the import inside a `"use client"` boundary. The canvas drawing starts in the browser.

`animateVisibility` and `animateMotion` both default to `false`. Enable them to reproduce animated state behavior. Merely choosing a non-idle state does not animate the mark. Reduced-motion preferences are respected by the component.

## Connect your application's state

The application owns the activity and status text. This complete component accepts any of the seven states and works with a built-in mark by default; pass `logoUrl` only when custom artwork is wanted.

```tsx
"use client";

import {
  AgentEmblemThinking,
  type AgentEmblemState,
} from "agent-emblem";

const statusText: Record<AgentEmblemState, string> = {
  idle: "Ready",
  loading: "Sending your message…",
  thinking: "Thinking…",
  composing: "Writing response…",
  researching: "Searching the docs…",
  listening: "Listening…",
  talking: "Speaking…",
};

export function AssistantStatus({
  state,
  logoUrl,
}: {
  state: AgentEmblemState;
  logoUrl?: string;
}) {
  const text = statusText[state];
  return (
    <AgentEmblemThinking
      preset="circle"
      source={logoUrl}
      state={state}
      text={text}
      label={text}
      size={24}
      color={{ light: "#18181b", dark: "#fafafa" }}
      animateText={state !== "idle"}
      animateVisibility
      animateMotion
    />
  );
}
```

Connect actual events to these states. For example, set `researching` while a tool runs, `composing` when text streams, and `idle` when the operation ends. Do not display a thinking or searching state if the application has no corresponding activity signal. Use general status text when the backend exposes only busy/ready.

## Optional AI SDK activity adapter

AgentEmblem accepts a structural activity object; it does not import `ai` or `@ai-sdk/react`. This wrapper can receive activity from an existing chat without creating another chat session.

```tsx
"use client";

import {
  AgentEmblemThinking,
  getAgentEmblemStatusCopyFromAIActivity,
  type AgentEmblemAIActivity,
} from "agent-emblem";

export function ChatActivity({ activity }: { activity: AgentEmblemAIActivity }) {
  const text = getAgentEmblemStatusCopyFromAIActivity(activity);
  return (
    <AgentEmblemThinking
      preset="spark"
      activity={activity}
      text={text}
      label={text}
      size={24}
      color={{ light: "#18181b", dark: "#fafafa" }}
      animateText={activity.status !== "ready" && activity.status !== "error"}
      animateVisibility
      animateMotion
    />
  );
}
```

In the component that already owns `useChat`, use its current `status` and the latest part of the latest **assistant** message to create `{ status, part }`. Do not use the latest user message's text as an assistant-writing signal. Pass terminal `ready`/`error` status when the chat completes or fails. Follow the existing chat's transport setup; see the [AI SDK integration guide](https://agent-emblem.vercel.app/docs/vercel-ai-sdk/).

| Activity | Resulting mark state |
| --- | --- |
| `status: "submitted"` | `loading` |
| `status: "ready"` or `"error"` | `idle` (takes precedence over an old message part) |
| `start`, `stream-start` part | `loading` |
| `reasoning`, `reasoning-start`, `reasoning-delta` part | `thinking` |
| `text`, `text-start`, `text-delta` part | `composing` |
| `tool-call`, `tool-*`, `dynamic-tool*`, `tool-result`, `source`, `source-*` part | `researching` except terminal/error cases below |
| `abort`, `error`, `finish`, `finish-step`, or part state `output-error` | `idle` |
| `step-start`, `start-step` part | `thinking` |
| Unsupported parts, `reasoning-end`, `text-end`, and tool `*-end` parts | Retain the previous state |

The adapter does not infer voice states. Control `listening`/`talking` manually from the audio application. The copy helper returns general status labels; it does not reveal or reconstruct model reasoning. Raw stream consumers should manage terminal copy themselves: the copy helper's final labels come from chat `status`, not every raw finish chunk.

## Public exports and important defaults

| Export | Purpose |
| --- | --- |
| `AgentEmblem` | Canvas mark without visible status text. |
| `AgentEmblemThinking` | Mark paired with text; supports every state despite its name. |
| `agentEmblemPresets` | Raw SVG strings for `circle`, `square`, `spark`, `cursor`. |
| `getAgentEmblemStateFromAIActivity(activity, currentState?)` | Pure state mapping; previous state defaults to `idle`. |
| `getAgentEmblemStatusCopyFromAIActivity(activity, currentCopy?)` | General status-copy mapping; previous copy defaults to `Ready`. |
| `useAgentEmblemAIState(activity, initialState?)` | React state adapter; initial state defaults to `idle`. |

Useful exported types include `AgentEmblemProps`, `AgentEmblemThinkingProps`, `AgentEmblemState`, `AgentEmblemPreset`, `AgentEmblemShape`, `AgentEmblemAIActivity`, `AgentEmblemAIStreamPart`, `AgentEmblemColor`, `AgentEmblemColorMode`, and `ThinkingStyle`. Read the package's exported declarations for the complete types.

- `source` is a string: raw SVG, a data URL, an object URL, or an image URL. A React SVG component is not a source string. `source` takes precedence over `preset`.
- `preset` chooses the overall mark: `circle` (default), `square`, `spark`, `cursor`. `shape` chooses each particle's geometry: `circle` (default), `square`, `diamond`, `plus`. They are different controls.
- `state` defaults to `idle`. When `activity` is supplied, it drives the mark instead of `state`; omit `activity` for manual control.
- `size` defaults to 240 px. Set it explicitly for compact UI. Start at 20–24 px and check detailed artwork at its actual display size.
- `color` defaults to `#f5f5f0`. Use `{ light, dark }` variants or a suitable explicit color on light backgrounds. `colorMode` defaults to `system`; pass the application's `light`/`dark` mode for an app-controlled theme.
- `inactiveColor` is derived automatically. Supply an explicit secondary color or `false` for a single-ink treatment.
- `markScale` defaults to 1. `density` defaults to `"auto"`. `particleCount` is approximate and automatic when omitted; it is not a guaranteed exact count.
- `particleUniformity` and `particlePositionUniformity` default to 0 and accept 0–1. They affect particle size consistency and spacing, respectively.
- `dotScale` defaults to 0.28. `thinkingStyle` is `trace` (default) or `bounce`.
- `AgentEmblemThinking` defaults to `text="Thinking…"`, `gap={4}`, and `animateText={true}`. Its text does **not** derive automatically from `state` or `activity`; pass matching text or the copy helper. Set `animateText={false}` when a steady idle label is preferable.
- Text inherits the application's font. `textStyle` overrides `textSize` and built-in text styling. `className`, `markClassName`, and `textClassName` target the wrapper, mark, and text respectively.

Full prop tables: [README](https://github.com/pologarcia/agent-emblem#props). The npm package ships declarations at `dist/index.d.ts`.

## Accessibility and troubleshooting

| Symptom or requirement | Check |
| --- | --- |
| Mark stays still | Enable both animation flags; inspect the user's reduced-motion preference. |
| Logo is blank | Try a built-in preset to isolate the issue, then check the asset URL, SVG validity, transparency, and CORS permission. Version 0.2.0 has no public image-error callback. |
| Light page makes the mark hard to see | Supply theme color variants and the correct `colorMode`. |
| Mark ignores the requested state | Remove `activity` when using manual `state`; check terminal activity status. |
| Status copy says Thinking while another state is active | Pass `text` explicitly; the component name/default text does not determine the mark's state. |
| Dense artwork loses detail at a small size | Use a simplified source or a larger size; inspect the actual 16–40 px result. Leave density automatic initially. |
| Canvas needs an accessible name | Supply a concise `label` describing the current visible activity. Keep status text accurate; the text wrapper uses a polite live region. |
| Screen-reader output repeats the mark and visible label | Inspect the surrounding UI and choose concise complementary labels; test the complete status row rather than assuming component defaults cover the whole app. |
| Need exact percent-complete or waveform amplitude | Keep that separate; these are not inputs to AgentEmblem. |

Transparent artwork works best. Remote image hosts must allow canvas access. Object URLs created by the application should be revoked when no longer used. Prefer readable text plus motion; motion or color alone should not carry essential task status.

## References

- [Developer portal and configuration sandbox](https://agent-emblem.vercel.app/developers/)
- [OpenAPI for the public read-only catalog](https://agent-emblem.vercel.app/openapi.json)
- [Package metadata and supported states](https://agent-emblem.vercel.app/api/manifest.json)
- [Built-in presets as SVG strings](https://agent-emblem.vercel.app/api/presets.json)
- [Package and complete API](https://github.com/pologarcia/agent-emblem#readme)
- [npm package](https://www.npmjs.com/package/agent-emblem)
- [Interactive demo](https://agent-emblem.vercel.app/)
- [React installation guide](https://agent-emblem.vercel.app/docs/react/)
- [AI SDK integration](https://agent-emblem.vercel.app/docs/vercel-ai-sdk/)
- [AI status-row pattern](https://agent-emblem.vercel.app/examples/ai-agent-status/)
- [Custom SVG and PNG artwork](https://agent-emblem.vercel.app/examples/animated-svg-logo/)
