Agent Steps and Confirm
The tool calls an agent made and a human-in-the-loop confirm before it acts. A step list with arguments, results and retry, plus a diff review with per-change ticks, risk, and Apply or Reject.
Code
<AgentSteps steps={steps} redactKeys={["token", "password"]} onRetry={(id) => retry(id)} renderConfirm={() => ( <AgentConfirm changes={changes} summary="I will rename 2 tags and delete 1 duplicate." onApply={async (ids) => api.apply(ids)} onReject={async (reason) => api.reject(reason)} /> )}/>AI Agents · beta
Live examples and controls: Agent Steps and Confirm in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/agent-steps.jsonTwo pieces for agentic features. AgentSteps shows what the agent did or plans to do, one tool call per row.
AgentConfirm stops before the change lands: it shows each proposed change as a diff and waits for a person to apply
or reject. Neither runs anything itself.
When to use
- An assistant that calls tools and you want the run to be inspectable.
- Any agent action that edits data, sends messages or spends money and needs a yes first.
When not to use
- A queue of requests from many people to approve: use
ApprovalQueue. - History of finished runs: use
RunHistory. - Editing a workflow by hand: use
StepEditor.
Import
import { AgentSteps, AgentConfirm } from "@fadymondy/nasaq/web";Quick start
<AgentSteps
steps={steps}
redactKeys={["token", "password"]}
onRetry={(id) => retry(id)}
renderConfirm={() => (
<AgentConfirm
changes={changes}
summary="I will rename 2 tags and delete 1 duplicate."
onApply={async (ids) => api.apply(ids)}
onReject={async (reason) => api.reject(reason)}
/>
)}
/>API
AgentStep
id, label, tool?, status (pending, running, awaiting, done, error, skipped), args?, result?
(text or a JSON string), resultLanguage?, error?, durationMs?.
AgentSteps
| Prop | Type | Notes |
|---|---|---|
steps | AgentStep[] | In order. |
title | string? | Heading. |
redactKeys | string[] | Argument keys masked at any depth, case-insensitive. |
renderConfirm | (step) => ReactNode | Shown under a step that is awaiting. |
onRetry | (stepId) => void | Adds a Retry button on failed steps. |
defaultOpenIds | string[] | Steps whose details start open. |
labels | Partial<AgentStepsLabels> |
AgentChange
id, title, target?, description?, before?, after?, risk? (low, medium, high). No before means a
new item, no after means a deletion.
AgentConfirm
| Prop | Type | Notes |
|---|---|---|
changes | AgentChange[] | |
onApply | (ids) => Promise<void | { error? }> | Gets the ticked ids. A rejection or { error } shows the failure and keeps the choice open. |
onReject | (reason?) => Promise<...> | |
summary | ReactNode | The agent's one-line intent. |
requireReason | boolean | Reason is mandatory on reject. |
defaultUnchecked | string[] | Ids that start unticked. |
onDecided | (decision) => void | After success. |
AgentDiff on its own takes before, after and context.
Examples
- Read only run log:
AgentStepswithoutrenderConfirm. - Destructive change: mark
risk: "high", and Apply stays disabled until the person ticks the acknowledgement.
Accessibility
- The run summary is a polite live region: "Waiting for you", "Failed", "Done".
- Each step is a disclosure button with its status in text, not only an icon.
- Diff lines carry
+and-marks, so colour is not the only signal. - Reject opens a dialog that traps focus and returns it on close.
RTL and i18n
- English and Arabic through
useOptionalNasaq(), overridable withlabels. - Tool names, arguments, results and diffs stay left to right; the surrounding text follows the page direction.
- Progress arrows and chevrons flip in RTL.
Styling and tokens
Status uses the --nq-success, --nq-warning, --nq-danger and --nq-accent families. Diff rows use the same tints
as VersionHistory.
Do / Don't
- Do let the person leave single changes out.
- Do mask secrets with
redactKeysbefore they reach the screen. - Don't apply anything before
onApplyis called. Confirm is the only gate. - Don't hide the diff for high risk changes.
Related
AgentPersonaEditor
Editor for an AI agent persona with name, tagline, colour, icon, traits, model, greeting and a markdown persona with write and preview tabs, section chips, counts, save and revert.
AiModelPicker
Choose the model, its reasoning effort and a required agent or skill, as cards or one compact toolbar row, plus a PersonaPicker with prompt starters and the compact AiModelSelect that CopilotChat uses.