# Agent status
URL: /elements/agent-status

One pill that always answers: what is it doing, and for how long.

> For AI agents: a documentation index is available at [llms.txt](/llms.txt). Use `.md` for canonical markdown pages; `.mdx` is kept as a backwards-compatible alias on supported URL paths.

A rounded pill with a state dot, a label that crossfades when it changes, an elapsed time while the agent is still going, and a trailing icon. With a runtime the state and label track a tool call's own lifecycle; standalone you hold all three and update them yourself.

## Getting started

**With a runtime:**

The pill maps naturally onto a single tool call: what the call is doing is the label, and whether it is still running, waiting on something, or finished is the state.

1. ### Render the tool call

   ```
   "use client";

   import { defineToolkit } from "@assistant-ui/react";
   import { AgentStatus } from "@/components/assistant-ui/elements/agent-status";

   export const toolkit = defineToolkit({
     report_status: {
       type: "backend",
       render: ({ args, status }) => (
         <AgentStatus
           state={
             status.type === "requires-action"
               ? "waiting"
               : status.type === "running"
                 ? "working"
                 : "done"
           }
           label={args.label}
           elapsed={args.elapsed}
         />
       ),
     },
   });
   ```

   `state` follows the call's own status: `requires-action` reads as waiting, `running` as working, and both `complete` and `incomplete` read as done, since either way the call is no longer active. `label` and `elapsed` are whatever the call's `args` carry, so your server formats `elapsed` (`"2m14s"`) the way you want it shown.

2. ### Register the toolkit

   ```
   import { AssistantRuntimeProvider, AuiConfig, Tools } from "@assistant-ui/react";
   import { toolkit } from "./toolkit";

   const config = AuiConfig({ tools: Tools({ toolkit }) });

   export function MyRuntimeProvider({ children }: { children: React.ReactNode }) {
     return (
       <AssistantRuntimeProvider runtime={runtime} config={config}>
         {children}
       </AssistantRuntimeProvider>
     );
   }
   ```

**Standalone (no runtime):**

Standalone, the element is a controlled display: you own `state`, `label`, and `elapsed`, and update them as the agent's work moves along.

1. ### Hold the status state

   ```
   "use client";

   import { useState } from "react";
   import {
     AgentStatus,
     type AgentState,
   } from "@/components/assistant-ui/elements/agent-status";

   export function Status() {
     const [state, setState] = useState<AgentState>("working");
     const [label, setLabel] = useState("Refactoring composer");
     const [elapsed, setElapsed] = useState("0:04");

     return <AgentStatus state={state} label={label} elapsed={elapsed} />;
   }
   ```

2. ### Move through the run

   ```
   setState("waiting");
   setLabel("Waiting for approval");
   // later
   setState("done");
   setLabel("Finished, 2 files changed");
   ```

   Changing `label` alone still animates: the text fades and blurs between values because the element keys the label on its own content.

## Anatomy

```
<div data-slot="agent-status">
  <span>{/* check, a pulsing dot, or an outlined one */}</span>
  <span>{/* visually hidden state */}</span>
  <span>{/* label */}</span>
  <span>{/* elapsed, only while state !== "done" */}</span>
  <span aria-hidden>{/* decorative trailing icon */}</span>
</div>
```

The leading indicator is a check once `state` is `"done"`, otherwise a dot: filled blue and pulsing while `"working"`, a static muted outline while `"waiting"`, so the two states differ in shape and motion and not only in color. The state is also rendered as visually hidden text, so it is exposed to assistive technology rather than carried by the dot's color alone. `elapsed` only renders when it is supplied and `state` is not `"done"`. The trailing icon swaps between the pause and replay treatments based on `state`, and is decorative: it carries no hover or press treatment and is hidden from assistive technology. Props spread onto the root pill.

## Examples

### Restyle the pill

Both lanes take `className` on the root. The elapsed text uses the `mono` token from `surfaces.tsx`.

```
<AgentStatus className="gap-3" state={state} label={label} elapsed={elapsed} />
```

### A pill with no elapsed time

Omit `elapsed` for work that is not worth timing, like a wait state with no useful duration.

```
<AgentStatus state="waiting" label="Waiting for approval" />
```

## API reference

**With a runtime:**

### Render props

| Source         | Type                                                           | Description                                                                                     |
| -------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `status.type`  | `"running" \| "requires-action" \| "incomplete" \| "complete"` | Drives `state`: `requires-action` to `"waiting"`, `running` to `"working"`, otherwise `"done"`. |
| `args.label`   | `string`                                                       | What the agent is doing right now.                                                              |
| `args.elapsed` | `string \| undefined`                                          | Preformatted elapsed time, shown only while the mapped `state` is not `"done"`.                 |

**Standalone (no runtime):**

### AgentStatus

| Prop        | Type                               | Default  | Description                                                                  |
| ----------- | ---------------------------------- | -------- | ---------------------------------------------------------------------------- |
| `state`     | `"working" \| "waiting" \| "done"` | required | Drives the leading indicator, visually hidden state text, and trailing icon. |
| `label`     | `string`                           | required | Crossfades in whenever its value changes.                                    |
| `elapsed`   | `string`                           |          | Shown only while `state` is not `"done"`.                                    |
| `className` | `string`                           |          | Merged onto the root.                                                        |

All other `div` props are forwarded to the root.