AG-UI React HITL Human-in-the-loop approval primitive. Blocks on pending agent actions. Supports diff, JSON, and text preview modes. Keyboard shortcuts, edit-before-approve, dark mode. Zero external deps.
Click any card to open the modal. Use Approve, Reject, or Edit & Approve to see the resolved state.
config/production.yaml to update the database connection pool settings.#eng-alerts via the Slack API with incident details.// ── Controlled usage ────────────────────────────────────────────── import { HumanApprovalModal } from './HumanApprovalModal.jsx'; const approval = { id: 'approval-001', title: 'Write production config', agentName: 'DevOps Agent', description: 'I want to update the database pool settings in config/production.yaml.', previewMode: 'diff', // 'text' | 'diff' | 'json' preview: '- pool_size: 5\n+ pool_size: 20\n- timeout: 30\n+ timeout: 60', highStakes: false, }; <HumanApprovalModal approval={approval} onApprove={(id) => console.log('approved', id)} onReject={(id, reason) => console.log('rejected', id, reason)} onEdit={(id, payload) => console.log('edited', id, payload)} theme="light" /> // ── AG-UI auto-wiring ───────────────────────────────────────────── import { HumanApprovalContainer } from './HumanApprovalModal.jsx'; const bus = new EventTarget(); // Your agent runtime emits STATE_DELTA when approval is pending: bus.dispatchEvent(new CustomEvent('STATE_DELTA', { detail: { path: 'pendingApproval', value: { id: 'a-001', title: 'Write production config', agentName: 'DevOps Agent', description: 'I want to update pool settings.', previewMode: 'diff', preview: '- pool_size: 5\n+ pool_size: 20', } } })); // Clear approval after decision: bus.dispatchEvent(new CustomEvent('STATE_DELTA', { detail: { path: 'pendingApproval', value: null } })); // Container listens to the bus and emits USER_MESSAGE on decision: <HumanApprovalContainer eventSource={bus} theme="dark" />