Claude Agent SDK

Free · MIT

Turns Claude Agent SDK events into Candor messages, waiting approvals and usage. Pure, so it can run on every render; useClaudeAgent calls it for you.

Markdown

Preview

It's types and helpers, listed below.

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/claude-agent-sdk

Brings in: chat, safe-markdown · npm: @anthropic-ai/claude-agent-sdk@^0.3.318

Functions

fromClaudeAgentEvents(events: AgentEvent[], options: FromClaudeAgentOptions)

Turns Claude Agent SDK events into Candor messages, waiting approvals and usage. Pure, so it can run on every render; useClaudeAgent calls it for you.

claudeQuestions(input: unknown)

The questions in an AskUserQuestion call, ready for ClarifyingQuestions; undefined when the input isn't one. Option ids are their labels, which is what the SDK takes back.

claudePermissionResult(request: Answerable, answer: ClaudeApprovalAnswer)

What to hand back to the SDK for a person's answer: the PermissionResult canUseTool resolves with. Pure, so it works wherever the answer lands (your own route, a queue, a workflow signal). Questions become AskUserQuestion's answers, keyed by question text, several choices joined with ", " and the person's own words used as they are. Only the suggestions the person picked are kept, and none when the request offers no "always allow".

claudeSuggestions(updates: PermissionUpdate[] | undefined)

The SDK's suggested permission updates as plain parts PermissionPrompt shows, in the same order, so the indexes a person ticks are the ones alwaysAllow sends back.

Types

ClaudePermissionMode
How the agent's tool calls are approved, as the SDK names it: "default" (ask for anything not allowed already), "acceptEdits", "plan", "auto" (a classifier decides), "dontAsk" (deny what isn't allowed already) and "bypassPermissions". Kept open: a newer SDK's mode passes through as its name.
"default" | "acceptEdits" | "plan" | "auto" | "dontAsk" | "bypassPermissions" | (string & {})
ClaudeQuestion
One of the agent's questions (the SDK's AskUserQuestion), shaped for ClarifyingQuestions. Options' ids are their labels.
{ /** The question's text, which is also how its answer is keyed back to the SDK. */ id: string kind: "choice" prompt: string /** The SDK's short header ("Library", "Approach"). */ tag?: string | undefined options: { id: string; label: string; detail?: string | undefined }[] multiple: boolean /** The SDK always lets the person answer in their own words. */ other: true }
ClaudeQuestionAnswer
A person's answer to one ClaudeQuestion: the chosen labels, their own words, or both. Same shape as ClarifyingAnswer.
{ questionId: string; choice?: string[] | undefined; text?: string | undefined }
ClaudeApprovalAnswer
How a person answered a permission request.
{ approved: boolean /** Why it was denied, sent to the agent. */ reason?: string | undefined /** The tool's input as the person edited it before allowing it. The tool runs with exactly this. */ updatedInput?: Record<string, unknown> | undefined /** Answers to the agent's questions, when the request is one (`questions`). */ answers?: ClaudeQuestionAnswer[] | undefined /** Which of the request's `su
CandorAgentEvent
Events of Candor's own, mixed into the SDK's stream.
| { type: "candor_user"; id: string; text: string; references?: EntityRef[] | undefined } /** A tool call is waiting for a person to allow or deny it. */ | { type: "candor_approval" id: string toolUseId: string tool: string input: unknown /** The SDK's own sentence for the request, e.g. "Claude wants to edit notes.md". */ title?: string | undefined description?: string | undefined /** Why the SDK
AgentEvent
SDKMessage | CandorAgentEvent
ClaudeApproval
Omit<Extract<CandorAgentEvent, { type: "candor_approval" }>, "type">
ClaudeAgentUsage
What the SDK measured for the session so far. Cost is its estimate, not a bill.
{ costUsd: number; inputTokens: number; outputTokens: number; turns: number }
FromClaudeAgentOptions
{ /** Who the agent is. Candor always names the agent. */ agent: AgentIdentity /** A request is open now: the last reply is still streaming and its approvals can be answered. */ running?: boolean | undefined /** A plain-words title for a tool call: "Read notes.md". */ toolTitle?: ((tool: string, input: unknown) => string | undefined) | undefined /** * The sources a tool's result supports, for the
ClaudeRecalledMemory
A memory the SDK recalled for a reply: the file (or URL) it came from, and whose memory it is.
{ path: string; scope: "personal" | "team" | "organization"; content?: string | undefined }
ClaudeAgentState
{ messages: Message[] /** Tool calls waiting on a person, oldest first. Empty once the request has ended. */ approvals: ClaudeApproval[] /** Send it back with the next message to continue the same session (the SDK's `resume`). */ sessionId?: string | undefined usage?: ClaudeAgentUsage | undefined /** A passing problem the agent is handling itself, such as a retried API call. */ notice?: string | u
ClaudeSuggestion
A "don't ask again" rule in plain parts, for PermissionPrompt's `suggestions`.
{ action: "allow" | "deny" | "ask" | "remove" | "mode" | "directories" | "other"; what: string; scope?: string | undefined }