Plan Card
Show the agent's proposed plan before it executes. Users see the trajectory before anything happens.
Install
npx ax-depute@latest add plan-cardpnpm dlx ax-depute@latest add plan-cardyarn dlx ax-depute@latest add plan-cardbunx ax-depute@latest add plan-cardOverview
Plan Card implements the plan-first pattern: show the trajectory, then execute. Before an agent takes any action, it proposes a plan — a numbered list of steps with confidence scores and assumptions.
This lowers fear and increases informed consent. Users can see where they're going before anything happens.
Customer Analysis Pipeline
- Fetch customer data from CRM
- Cross-reference billing records
- Generate summary report
- Send notification to stakeholders
Basic usage
<PlanCard
steps={agent.proposedPlan}
assumptions={agent.assumptions}
/>With mock data
import { generateMockPlan } from '@/utils/mockData';
const plan = generateMockPlan(4); // 4-step plan
<PlanCard
steps={plan.steps}
assumptions={plan.assumptions}
/>Live execution state
When the agent is running, pass activeStepId to highlight the current step:
<PlanCard
steps={agent.plan}
activeStepId={agent.currentStepId}
/>Streaming state
When steps are still being generated by a streaming backend, pass isStreaming. This adds data-streaming="true" to the root element — no built-in animation. Style it however the host product expects:
<PlanCard
title={agent.planTitle}
steps={agent.partialSteps}
isStreaming={agent.isStreaming}
mode="indeterminate"
/>/* Host product controls the visual */
[data-streaming="true"] .plan-card-title::after {
content: "…";
animation: pulse 1s infinite;
}Per-step reasoning
When each PlanStep has a reasoning string, opt-in to collapsible reasoning toggles with showReasoning. Set defaultExpandedStepId to pre-expand a specific step on mount:
<PlanCard
title={agent.planTitle}
steps={agent.planSteps} // steps with .reasoning populated
showReasoning
defaultExpandedStepId={agent.activeStepId}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | PlanStep[] | Required | Ordered list of plan steps |
title | string | Required | Title of the plan |
assumptions | string[] | undefined | Agent's stated assumptions |
reasoning | string | undefined | Agent's overall reasoning (collapsible) |
activeStepId | string | undefined | ID of the currently executing step |
showConfidence | boolean | false | Show confidence badge per step |
isStreaming | boolean | false | Signals that steps are still being generated. Adds data-streaming="true" to the root element — no built-in animation; style via CSS. |
showReasoning | boolean | false | Renders a collapsible reasoning toggle on each step that has a reasoning string. |
defaultExpandedStepId | string | undefined | ID of the step whose reasoning is expanded by default (uncontrolled). Follows the activeStepId pattern. |
PlanStep type
interface PlanStep {
id: string;
label: string;
status: 'pending' | 'active' | 'completed' | 'failed';
confidence?: number; // 0–1
}When to use
- The agent is about to take a multi-step or multi-tool action and the user should be aware of the trajectory before it begins
- Trust is low or the action surface is new — surfacing the plan early builds informed consent
- The agent's intent is ambiguous without a plan (e.g., "refactor this codebase" covers too many possibilities)
- You want to give the user a natural moment to abort before any irreversible step starts
When not to use
- The agent is performing a single, trivially understood action (e.g., "look up the weather") — a full plan card adds friction without value
- The agent's actions are happening fully in the background with no synchronous human checkpoint; use
Tool Tracefor passive monitoring instead - You are already showing a
Decision Recordthat captures the full approved plan — avoid duplicating plan state in both components
Accessibility
- Uses semantic
<ol>for step lists; each step renders as<li>withrole="listitem" - Active step is annotated with
aria-current="step"to assist screen reader navigation - Completed and failed steps carry
aria-labelvalues that include their status (e.g., "Step 2: Complete. Write schema migration.") - Streaming state is announced via
aria-live="polite"on the container whenisStreamingis true - All collapsible reasoning toggles use
<button aria-expanded>with accessible toggle labels
Solution Patterns
Plan Card is always the first primitive in a single-agent flow:
Plan Card → Approval Gate → Run Controls → Tool Trace → Artifact CardShow it before the agent runs. Once execution starts, it updates step statuses live.
Design rationale
Why show the plan before execution? Claude Cowork (Anthropic) shows the full plan in a "Progress" panel before any action is taken — validating the plan-first pattern. The core idea: agents that propose concrete work before asking for permission feel collaborative rather than autonomous. Users who can see a trajectory are far more likely to engage with it critically than users who are handed a fait accompli.