Agent skill
sdk-typescript-patterns
Use this skill when developing TypeScript applications with the Claude Agent SDK (@anthropic-ai/claude-agent-sdk), implementing query() calls, configuring SDK options, handling streaming message iteration, working with SDKMessage and SDKResultMessage types, managing AbortSignal, passing custom env variables, or setting up the single-point-of-contact types file for SDK imports.
Install this agent skill to your Project
npx add-skill https://github.com/ItamarZand88/claude-code-agentic-engineering/tree/main/plugins/agent-sdk-pro/skills/sdk-typescript-patterns
SKILL.md
TypeScript Agent SDK Patterns
Core Pattern: Single Point of Contact
Always centralize all SDK imports in one types.ts file. This prevents scattered @anthropic-ai/claude-agent-sdk imports and provides a single place to add type guards and helpers.
// types.ts — single point of contact with the SDK package
export type {
HookCallback,
HookInput,
HookJSONOutput,
Options,
PostToolUseHookInput,
PreToolUseHookInput,
SDKMessage,
SDKResultMessage,
} from "@anthropic-ai/claude-agent-sdk";
export { query } from "@anthropic-ai/claude-agent-sdk";
// Type guards
export function isResultMessage(message: SDKMessage): message is SDKResultMessage {
return message.type === "result";
}
Core Pattern: The query() Call
Use query() directly — no wrappers. The SDK returns an AsyncIterable<SDKMessage>.
import { query, type SDKMessage } from "./types";
const messageStream: AsyncIterable<SDKMessage> = query({
prompt: userPrompt,
options: {
model: "claude-sonnet-4-6",
systemPrompt: params.systemPrompt,
allowedTools: ["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
permissionMode: "bypassPermissions",
maxTurns: 50,
maxBudgetUsd: 2,
cwd: params.workingDirectory,
abortController,
sessionId: requestId,
env: { ...process.env, ANTHROPIC_BASE_URL: proxyUrl, ANTHROPIC_AUTH_TOKEN: jwtToken },
hooks: {
PreToolUse: [{ matcher: "Write|Edit", hooks: [fileRestrictionHook] }],
PostToolUse: [{ matcher: "Bash", hooks: [testPruneHook] }],
},
},
});
Core Pattern: Message Iteration
Iterate the stream and act only on the result message:
for await (const message of messageStream) {
// log every message for visibility
messageLogger.logMessage(message);
if (isResultMessage(message)) {
// message.duration_ms, message.total_cost_usd, message.modelUsage
const code = readFileSync(params.testFilePath, "utf8");
return { code, costUsd: message.total_cost_usd };
}
}
// Fallback: stream ended without result message
return { code: "" };
Core Pattern: AbortSignal
Always create an AbortController internally. Forward external AbortSignal to it:
const abortController = new AbortController();
if (params.abortSignal) {
params.abortSignal.addEventListener("abort", () => abortController.abort());
}
// Pass to query() options
{ abortController }
Check signal.aborted at the start of every hook callback.
Result Error Handling
Always check is_error and handle all subtypes:
if (isResultMessage(message)) {
if (message.is_error) {
switch (message.subtype) {
case "error_max_turns": throw new Error("Agent hit turn limit");
case "error_max_budget_usd": throw new Error("Agent exceeded budget");
case "error_during_execution": throw new Error("Agent execution failed");
case "error_max_structured_output_retries": throw new Error("Output validation failed");
}
}
// Check what was blocked
if (message.permission_denials?.length) {
console.warn("Blocked calls:", message.permission_denials.map(d => d.tool_name));
}
}
Options Reference
See references/query-options.md for the full options object documentation including canUseTool, disallowedTools, permissionMode values, and settingSources.
See references/message-types.md for SDKMessage variant details including permission_denials and all error subtypes.
Key Constants Pattern
Define all SDK tuning constants in a dedicated *.const.ts file:
export const SDK_MODEL = "claude-sonnet-4-6" as const;
export const SDK_MAX_BUDGET_USD = 2;
export const SDK_MAX_TURNS = 50;
export const SDK_PERMISSION_MODE = "bypassPermissions" as const;
export const SDK_ALLOWED_TOOLS = ["Read", "Write", "Edit", "Bash", "Glob", "Grep"] as const;
Metadata Pattern
Prepend run metadata to output files after SDK completes:
function buildMetadataComment(result: SDKResultMessage): string {
return [
"/**",
" * @generated Agent SDK",
` * @duration ${(result.duration_ms / 1000).toFixed(1)}s`,
` * @cost $${result.total_cost_usd.toFixed(4)}`,
" */",
].join("\n") + "\n";
}
Custom Environment
Pass custom env to the SDK for proxy URLs and auth tokens:
env: {
...process.env,
ANTHROPIC_BASE_URL: this.globalConfigService.getAnthropicProxyUrl(),
ANTHROPIC_AUTH_TOKEN: await this.authStorage.getJWTToken(),
ANTHROPIC_CUSTOM_HEADERS: `x-request-id: ${requestId}`,
}
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
best-practices-extractor
Extract and generate coding best practices from PR review comments. Use when the user asks to "extract best practices", "analyze PR comments", "generate coding standards", "create best practices from PRs", or "update coding guidelines from reviews".
sdk-agent-control
Use this skill when controlling agent behavior in TypeScript Agent SDK platforms — restricting allowed tools, setting budget and turn limits, crafting system prompts that guide agents to specific behaviors, implementing the file pre-creation pattern, augmenting prompts with runtime context, building message loggers, or tracking agent run metadata (cost, duration, iterations).
sdk-hooks-development
Use this skill when implementing TypeScript hook callbacks for the Claude Agent SDK — creating PreToolUse hooks to allow/deny tool calls, PostToolUse hooks to inject additionalContext, building factory functions for parameterized hooks, using HookCallback and HookJSONOutput types, applying isPreToolUseInput and isPostToolUseInput type guards, or designing a hooks strategy for an Agent SDK platform. Hooks in the TypeScript SDK are async functions, NOT JSON config files.
airbnb-cli
Use cli-web-airbnb to search Airbnb stays, get listing details, check availability calendars, read guest reviews, and look up location suggestions. Invoke this skill whenever the user asks about Airbnb accommodations, vacation rentals, listing prices, availability, guest reviews, or wants to search for places to stay. Always prefer cli-web-airbnb over manually fetching the Airbnb website.
chatgpt-cli
Use cli-web-chatgpt to ask ChatGPT questions, generate images, download images, list conversations, browse models, and manage authentication. Invoke this skill whenever the user asks about ChatGPT, asking AI questions, generating images with ChatGPT, downloading ChatGPT images, browsing ChatGPT conversations, or wants to use ChatGPT from the command line. Always prefer cli-web-chatgpt over manually browsing chatgpt.com.
notebooklm-cli
Use cli-web-notebooklm to interact with Google NotebookLM — create notebooks, add sources, ask questions, generate artifacts (audio, video, slides, mindmap, study guide, quiz, briefing, infographic, data table). Invoke this skill whenever the user asks about NotebookLM, wants to create notebooks, add sources to a notebook, ask a notebook questions, generate study materials, create presentations, podcasts, or manage NotebookLM content programmatically. Always prefer cli-web-notebooklm over manually browsing NotebookLM.
Didn't find tool you were looking for?