claude-agent-ts-sdk/SKILL.md
Build Claude agents using TypeScript with the @anthropic-ai/claude-agent-sdk. Use this skill when implementing conversational agents, building tools for agents, setting up streaming responses, or debugging agent implementations. Covers the tool wrapping pattern, SDK initialization, agent architecture, and best practices.
npx skillsauth add szweibel/claude-skills claude-agent-ts-sdkInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build production-ready Claude agents using TypeScript and the @anthropic-ai/claude-agent-sdk. This skill provides battle-tested patterns for creating modular, composable agent tools.
import { query, createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
import { z } from 'zod';
// 1. Define tools
const greetTool = tool(
'greet',
'Greet a user by name',
z.object({
name: z.string().describe('User name'),
}).shape,
async ({ name }) => ({
content: [{ type: 'text', text: `Hello, ${name}!` }],
})
);
// 2. Create MCP server
const server = createSdkMcpServer({
name: 'my-agent',
version: '1.0.0',
tools: [greetTool],
});
// 3. Query with streaming
const messages = query({
prompt: 'Greet Alice',
options: {
systemPrompt: 'You are a helpful agent.',
permissionMode: 'bypassPermissions',
mcpServers: { 'my-agent': server },
},
});
// 4. Process stream
for await (const event of messages) {
if (event.type === 'assistant') {
for (const content of event.message.content) {
if (content.type === 'text') {
console.log(content.text);
}
}
}
}
Use when:
Tools are the building blocks of agent capabilities. Use the tool() function to create them:
import { tool } from '@anthropic-ai/claude-agent-sdk';
import { z } from 'zod';
const myTool = tool(
'tool_name', // Name (lowercase, underscores)
'What it does', // Clear description
z.object({ // Zod schema for validation
param: z.string().describe('Parameter description'),
}).shape,
async (params) => { // Implementation
return {
content: [{ type: 'text', text: 'Result' }],
};
}
);
Key Points:
{ content: [{ type: 'text', text: string }] }Wrap tools in MCP servers for query execution:
import { createSdkMcpServer } from '@anthropic-ai/claude-agent-sdk';
const server = createSdkMcpServer({
name: 'server-name',
version: '1.0.0',
tools: [tool1, tool2],
});
Important: Create servers at query time, not module level (enables dynamic tool selection).
Execute agent queries with real-time streaming:
import { query } from '@anthropic-ai/claude-agent-sdk';
const messages = query({
prompt: 'User request here',
options: {
systemPrompt: 'Agent role and instructions',
permissionMode: 'bypassPermissions', // For standalone servers
mcpServers: {
'server-name': server,
},
},
});
for await (const event of messages) {
// Process events: 'assistant', 'user', 'error'
}
For streaming patterns and event handling, see references/streaming.md
System prompts define agent behavior (100-170+ lines recommended):
const SYSTEM_PROMPT = `You are a specialized agent that...
## Available Tools
[Detailed tool descriptions]
## Workflow
[Step-by-step instructions]
## Output Format
[Expected response structure]
`;
For system prompt best practices, see references/system-prompts.md
Choose the pattern that fits your use case:
Best for: Command-line tools, batch processing
export async function runAgent(userPrompt: string) {
const server = createSdkMcpServer({ name: 'cli-agent', version: '1.0.0', tools });
const messages = query({ prompt: userPrompt, options: { systemPrompt, permissionMode: 'bypassPermissions', mcpServers: { 'cli-agent': server } } });
for await (const event of messages) {
if (event.type === 'assistant') {
for (const content of event.message.content) {
if (content.type === 'text') process.stdout.write(content.text);
}
}
}
}
Best for: Web applications, APIs, real-time UIs
app.post('/agent/stream', async (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
const server = createSdkMcpServer({ name: 'web-agent', version: '1.0.0', tools });
const messages = query({ prompt: req.body.prompt, options: { systemPrompt, mcpServers: { 'web-agent': server } } });
for await (const event of messages) {
res.write(`data: ${JSON.stringify(event)}\n\n`);
}
res.end();
});
Best for: Extensible systems, plugin architectures
export class AgentEngine {
async stream(prompt: string) {
const tools = this.plugin.getTools();
const server = createSdkMcpServer({ name: this.plugin.name, version: '1.0.0', tools });
const messages = query({ prompt, options: { systemPrompt: this.plugin.systemPrompt, permissionMode: 'bypassPermissions', mcpServers: { [this.plugin.name]: server } } });
for await (const event of messages) {
await this.plugin.handleEvent(event);
}
}
}
For complete architecture patterns including monorepo setup, see references/patterns.md
{
"name": "my-agent",
"type": "module",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.1.14",
"zod": "^3.23.8"
},
"devDependencies": {
"typescript": "^5.3.3",
"tsx": "^4.7.0"
}
}
my-agent/
├── src/
│ ├── index.ts # Entry point
│ ├── agent.ts # Agent implementation
│ ├── tools/ # Tool definitions
│ └── prompts/ # System prompts
├── package.json
└── tsconfig.json
For complete project setup including TypeScript config, see references/project-setup.md
const readFile = tool('read_file', 'Read file contents',
z.object({ path: z.string() }).shape,
async ({ path }) => ({ content: [{ type: 'text', text: await fs.readFile(path, 'utf-8') }] })
);
const writeFile = tool('write_file', 'Write to file',
z.object({ path: z.string(), content: z.string() }).shape,
async ({ path, content }) => { await fs.writeFile(path, content); return { content: [{ type: 'text', text: 'Done' }] }; }
);
const SYSTEM_PROMPT = `You are a file management agent.
When user asks to edit a file:
1. read_file to see current contents
2. Propose changes
3. write_file to save changes`;
const server = createSdkMcpServer({ name: 'files', version: '1.0.0', tools: [readFile, writeFile] });
const messages = query({ prompt: userRequest, options: { systemPrompt: SYSTEM_PROMPT, permissionMode: 'bypassPermissions', mcpServers: { 'files': server } } });
Create tool factories that close over session-specific data:
function createSessionTools(userId: string) {
return [
tool('get_user_data', 'Get user data', {}, async () => {
const data = await db.getUser(userId); // Closure over userId
return { content: [{ type: 'text', text: JSON.stringify(data) }] };
})
];
}
// Per-session tools
app.post('/agent', async (req, res) => {
const tools = createSessionTools(req.session.userId);
const server = createSdkMcpServer({ name: 'session', version: '1.0.0', tools });
// ... rest of agent setup
});
permissionMode: 'bypassPermissions' for standalone servers"type": "module" consistentlyinteractive permission mode in standalone serversNo configuration required! The SDK automatically uses Claude Code's authentication. Your agent works seamlessly within Claude Code without any API key setup.
const messages = query({
prompt,
options: {
systemPrompt,
mcpServers,
onToolCall: (name, params) => console.log(`[CALL] ${name}`, params),
onToolResult: (name, result) => console.log(`[RESULT] ${name}`, result),
},
});
// Test before integrating
const result = await myTool.execute({ param: 'test' });
console.log('Tool output:', result);
"Claude Code process exited with code 1"
permissionMode: 'bypassPermissions' for standalone serversTools not being called
Import errors
"type": "module" in package.json.js extensions in imports (Node16 resolution)This skill includes detailed reference documentation:
development
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
development
Use OCLC WorldCat APIs to search for books and scholarly materials, retrieve bibliographic metadata, check library holdings worldwide, and get classification data. Use when working with ISBNs, DOIs, OCLC numbers, library catalogs, or institutional holdings.
tools
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
development
Complete guide for Svelte 5 runes ($state, $derived, $effect, $props, $bindable). Use for any Svelte 5 project or when code contains $ prefixed runes. Essential for reactive state management, computed values, side effects, and component props. Covers migration from Svelte 4 reactive statements.