Agent Inbox / Decision Inbox
Preview: Board
All background agent tasks in one place, grouped by what they need from you. A task's title opens it (`onOpen`) in both views.
Import
import { AgentInbox } from '@marbleui/ui'Props
<AgentInbox>
| Prop | Type | Default | Description |
|---|---|---|---|
| tasks *required | AgentTask[] | — | |
| className | string | — | |
| onOpen | (id: string) => void | — | |
| onViewChange | (v: 'board' | 'list') => void | — | |
| view | 'board' | 'list' | 'board' |
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: React Aria Button. Follow the primitive's docs for the full keyboard map.
Usage notes
Background agent tasks grouped into Needs you, Running and Done, as a board or a list. For one task’s steps use AgentPlan.
<AgentInbox
tasks={[
{ id: 'mig', title: 'Migrate users table', state: 'needs-you', meta: 'Waiting for you', actions: <Button size="sm" onPress={() => approve('mig')}>Approve</Button> },
{ id: 'pr', title: 'Review PR #482', state: 'running', meta: '3m 41s', counts: { tools: 12, files: 21 } },
]}
view={view} onViewChange={setView} onOpen={openTask}
/>
viewis controlled; the Board/List toggle appears only whenonViewChangeis set.actionsare yours to render and handle. Tasks move between groups only when you change theirstate.- With
onOpen, the task title is a button in both views; without it the title is plain text. - The board is always three columns, so use
view="list"in narrow spaces. Tool and file counts show as ⚙/✎ glyphs and are read as “N tool calls” and “N files”; the header badge reads “N need you”.
Example source · show· hide
import { useState } from 'react'
import { Button } from '../button'
import { AgentInbox, type AgentTask } from './agent-inbox'
const actions = <><Button size="sm" variant="ghost">Reject</Button><Button size="sm">Approve</Button></>
const tasks: AgentTask[] = [
{ id: '1', title: 'Migrate users table', summary: 'Split users into accounts and profiles on Postgres 17. The dry run passed; production needs approval.', state: 'needs-you', meta: 'Waiting for you', counts: { tools: 9, files: 14 }, actions },
{ id: '2', title: 'Clean up CRM contacts', summary: 'Found 312 duplicates; wants to merge them.', state: 'needs-you', meta: 'Waiting for you', counts: { tools: 4 }, actions },
{ id: '3', title: 'Review PR #482', summary: 'Billing webhooks: reading the diff and the test run, writing review comments.', state: 'running', meta: '3m 41s', counts: { tools: 12, files: 21 } },
{ id: '4', title: 'Release notes v2.4', summary: 'Grouping 23 merged pull requests into features and fixes.', state: 'running', meta: '1m 19s', counts: { tools: 23, files: 5 } },
{ id: '5', title: 'Weekly metrics digest', summary: 'Pulled numbers from three dashboards and posted the summary.', state: 'done', meta: '4m 12s', counts: { tools: 3, files: 8 } },
]
function Demo() {
const [view, setView] = useState<'board' | 'list'>('board')
return <AgentInbox className="w-[52rem]" tasks={tasks} view={view} onViewChange={setView} />
}
export const styles = { Board: Demo, List: () => <AgentInbox className="w-[40rem]" tasks={tasks} view="list" /> }Source: packages/ui/src/agent-inbox/agent-inbox.tsx
Catalog
- Category
- ai-agents
- Priority
- Pro
- Primitive
- composed
- React Aria
- GridList