All Docs
FeaturesSidekickUpdated March 11, 2026

Action Cards: Approve, Edit, or Reject Agent Actions Without Leaving Chat

Action Cards: Approve, Edit, or Reject Agent Actions Without Leaving Chat

Starting with v1.0.35, Sidekick surfaces proposed agent actions as interactive Action Cards directly inside your chat conversation. When the AI decides it should send an email, file a GitHub issue, book a meeting, or post a message on your behalf, you see a structured preview of exactly what it intends to do — and you decide what happens next.

How It Works

  1. You give Sidekick a task (or it picks one up autonomously from your connected services).
  2. Before executing, the agent emits an Action Card into the chat thread at the point in the conversation where the action was proposed.
  3. You review the preview, read the agent's reasoning, and choose: Approve, Edit, or Reject.
  4. The card updates in place — no page navigation, no separate approvals inbox.

The Card Interface

Per-Type Previews

Each Action Card shows a structured preview tailored to the action type:

Action TypePreview Fields
EmailTo, Subject, Body
Calendar eventTitle, Time, Attendees
GitHub issueRepository, Issue Title, Description
MessagePlatform, Recipient, Body
GenericAction summary

Controls

  • Approve — confirms the action and queues it for execution. The card transitions to Executing… and then to Done (or Failed) once the adapter runs.
  • Edit — opens an inline form with type-aware fields populated from the proposed action. Modify any field, save, and then approve. Your edits are stored in editedPayload so the original proposal is preserved for the audit trail.
  • Reject — dismisses the action. The card transitions to Dismissed and the action is not executed.

Agent Reasoning

Each card has an expandable Reasoning section showing why the agent proposed the action. This is especially useful in supervised mode when the agent is managing a high volume of tasks.

Status Badges

BadgeMeaning
⚡ Awaiting Approval (pulse)Card is pending your decision
Executing…Approved, adapter running
✅ DoneAction completed successfully
❌ FailedAction ran but encountered an error
DismissedYou rejected the action

When an action produces a result (for example, a newly filed GitHub issue), a View link appears on the card pointing directly to the resource.

Pending Actions Badge

The chat header shows a ShieldCheck badge with a count of how many actions are currently awaiting your approval. The count updates in real time as you approve or reject cards.

Delivery: Real-Time and Polling

Action Cards reach the chat interface through two complementary channels:

  • SSE (Server-Sent Events) — cards are pushed into the stream immediately when the agent emits them during a chat response. They appear at the correct position in the conversation timeline without any delay.
  • 15-second polling — a background query fetches all pending cards every 15 seconds. This catches cards created outside the active chat session (e.g. from an autonomous background task) and removes cards that are no longer pending.

Autonomy Modes

Action Cards behave differently depending on your configured autonomy level:

manual and supervised

A card is created with status pending. The action does not run until you approve it. This is the default for most users and integrations.

autonomous

The action executes immediately without waiting for your approval. A card is still created, but its initial status is executed — it acts as an audit record so you can see what the agent did and when.

Act-then-report

If the agent has already executed an action before card creation (e.g. during a background run), the card is created with alreadyExecuted: true and status executed. Same audit behaviour as autonomous mode.

tRPC API Reference

If you are building on top of Sidekick or writing custom skills, you can interact with Action Cards programmatically through the actionCards tRPC router.

actionCards.list

Returns a paginated list of Action Cards, optionally filtered by status.

const { items, nextCursor } = await trpc.actionCards.list.query({
  limit: 20,
  status: "pending", // "pending" | "approved" | "rejected" | "executed" | "failed"
  cursor: undefined,  // pass nextCursor for pagination
});

actionCards.byId

Fetch a single card by its ID.

const card = await trpc.actionCards.byId.query({ id: "card_abc123" });

actionCards.approve

Approve a pending card. Transitions status pending → approved and logs to agentDecisions.

await trpc.actionCards.approve.mutate({ id: "card_abc123" });

actionCards.reject

Reject a pending card. Transitions status pending → rejected and logs to agentDecisions.

await trpc.actionCards.reject.mutate({ id: "card_abc123" });

actionCards.edit

Save a modified payload before approving. The original proposed action is preserved; the edited version is stored in editedPayload.

await trpc.actionCards.edit.mutate({
  id: "card_abc123",
  editedPayload: { subject: "Updated subject line" },
});

actionCards.markExecuted

Mark an approved card as executed (or failed) after the adapter has run.

await trpc.actionCards.markExecuted.mutate({
  id: "card_abc123",
  status: "executed", // or "failed"
  executionResult: { url: "https://github.com/org/repo/issues/42" },
  executionError: null,
});

actionCards.stats

Returns counts grouped by status — useful for badge rendering or dashboards.

const stats = await trpc.actionCards.stats.query();
// { pending: 3, approved: 1, rejected: 0, executed: 14, failed: 1 }

Database Schema

Action Cards are persisted in the actionCards table:

ColumnTypeDescription
iduuidPrimary key
actionjsonbThe UnifiedAction object describing what to do
previewjsonbPer-type structured preview shown in the UI
agentReasoningtextWhy the agent proposed this action
statusaction_card_statuspending | approved | rejected | executed | failed
editedPayloadjsonbUser-modified fields (null if unedited)
executionResultjsonbAdapter result including optional URL
executionErrortextError message if execution failed
resolvedAttimestampWhen approved or rejected
executedAttimestampWhen the adapter completed execution