从现在起你可以基于ClaudeCodeSDK构建自己的智能体了附大量例子
99% 的 Agent 创业公司,都可以扔掉你的代码了转用 Claude Code SDK 来实现了。

刚刚,Claude Code SDK 发布了支持自定义工具和钩子函数的更新:

Claude Code 开发者 Thariq(@trq212) 宣布:
Claude Code SDK 现在支持直接在代码中使用自定义工具和钩子。此外,我们刷新了所有文档,包含完整的参考和 10 个新指南。
虽然 Claude Code 并不开源,甚至还莫名降智,但这不妨碍它性能强大,我每天都会用来做各种编程之外的事。
而基于 Claude Code SDK,再结合 MCP、工具、命令、钩子等周边功能,可以说,这能帮我们解决绝大多数在电脑上需要做的事情,和绝大多数所谓 Agent 公司们在做的事情。
自定义工具的实现
自定义工具的实现方式很简单: 定义一个函数,将其注册为 SDK 的 in-process MCP 服务器,Claude Code 就能调用它。
这种「 进程内 MCP 」的设计让扩展变得异常优雅。
来看实现代码。
(又是这个获取天气的示例……,好在后面有更多例子)
TypeScript 版本 :
import { query, tool, createSdkMcpServer } from"@anthropic-ai/claude-code";import { z } from"zod";// 创建一个带有自定义工具的 SDK MCP 服务器const customServer = createSdkMcpServer({ name: "my-custom-tools", version: "1.0.0", tools: [ tool( "get_weather", "Get current weather for a location", { location: z.string().describe("City name or coordinates"), units: z.enum(["celsius", "fahrenheit"]).default("celsius").describe("Temperature units") }, async (args) => { // 调用天气 API const response = await fetch( `https://api.weather.com/v1/current?q=${args.location}&units=${args.units}` ); const data = await response.json(); return { content: [{ type: "text", text: `Temperature: ${data.temp}°nConditions: ${data.conditions}nHumidity: ${data.humidity}%` }] }; } ) ]});
Python 版本 :
from claude_code_sdk import tool, create_sdk_mcp_serverfrom typing import Anyimport aiohttp# 使用装饰器定义自定义工具@tool("get_weather", "Get current weather for a location", {"location": str, "units": str})asyncdef get_weather(args: dict[str, Any]) -> dict[str, Any]: units = args.get('units', 'celsius') asyncwith aiohttp.ClientSession() as session: asyncwith session.get( f"https://api.weather.com/v1/current?q={args['location']}&units={units}" ) as response: data = await response.json() return { "content": [{ "type": "text", "text": f"Temperature: {data['temp']}°nConditions: {data['conditions']}nHumidity: {data['humidity']}%" }] }# 创建服务器custom_server = create_sdk_mcp_server( name="my-custom-tools", version="1.0.0", tools=[get_weather])
使用自定义工具
重要提示 :自定义 MCP 工具需要流式输入模式。必须使用异步生成器作为 prompt 参数,简单的字符串不能与 MCP 服务器配合使用。
工具名称遵循特定格式: mcp__{server_name}__{tool_name} 。例如, my-custom-tools 服务器中的 get_weather 工具会变成 mcp__my-custom-tools__get_weather 。
TypeScript 调用示例 :
import { query } from"@anthropic-ai/claude-code";// 使用异步生成器进行流式输入asyncfunction* generateMessages() {yield { type: "user"asconst, message: { role: "user"asconst, content: "What's the weather in San Francisco?" } };}forawait (const message of query({ prompt: generateMessages(), // 使用异步生成器 options: { mcpServers: { "my-custom-tools": customServer // 作为对象传递,不是数组 }, // 可选:指定 Claude 可以使用哪些工具 allowedTools: [ "mcp__my-custom-tools__get_weather", ], maxTurns: 3 }})) {if (message.type === "result" && message.subtype === "success") { console.log(message.result); }}
Python 调用示例 :
from claude_code_sdk import query, ClaudeCodeOptionsasyncdef message_generator(): yield { "type": "user", "message": { "role": "user", "content": "What's the weather in San Francisco?" } }asyncfor message in query( prompt=message_generator(), # 使用异步生成器 options=ClaudeCodeOptions( mcp_servers={"my-custom-tools": custom_server}, allowed_tools=[ "mcp__my-custom-tools__get_weather", ], max_turns=3 )): if hasattr(message, 'result'): print(message.result)
权限系统架构
SDK 提供了四层互补的权限控制机制,让我们能够精确控制工具的使用。

权限模式
模式
描述
工具行为
default
标准权限行为
正常权限检查
plan
规划模式
只能使用只读工具,执行前展示计划
acceptEdits
自动接受文件编辑
文件编辑和文件系统操作自动批准
bypassPermissions
绕过所有权限检查
所有工具无需权限提示运行(谨慎使用)
设置权限模式的代码:
// 初始配置const result = await query({ prompt: "Help me refactor this code", options: { permissionMode: 'default' }});// 动态更改(仅流式模式)asyncfunction* streamInput() {yield { type: 'user', message: { role: 'user', content: "Let's start with default permissions" } };}const q = query({ prompt: streamInput(), options: { permissionMode: 'default' }});// 动态切换模式await q.setPermissionMode('acceptEdits');
canUseTool 回调
canUseTool 回调在 Claude Code 需要显示权限提示时触发,可以实现交互式工具批准:
async function promptForToolApproval(toolName: string, input: any) {console.log("n🔧 Tool Request:");console.log(` Tool: ${toolName}`);// 显示工具参数if (input && Object.keys(input).length > 0) { console.log(" Parameters:"); for (const [key, value] of Object.entries(input)) { let displayValue = value; if (typeof value === 'string' && value.length > 100) { displayValue = value.substring(0, 100) + "..."; } elseif (typeof value === 'object') { displayValue = JSON.stringify(value, null, 2); } console.log(` ${key}: ${displayValue}`); } }// 获取用户批准const approved = await getUserApproval();if (approved) { console.log(" ✅ Approvedn"); return { behavior: "allow", updatedInput: input }; } else { console.log(" ❌ Deniedn"); return { behavior: "deny", message: "User denied permission for this tool" }; }}// 使用权限回调const result = await query({ prompt: "Help me analyze this codebase", options: { canUseTool: async (toolName, input) => { return promptForToolApproval(toolName, input); } }});
钩子函数
钩子提供了对工具执行各个阶段的程序化控制:
const result = await query({ prompt: "Help me refactor this code", options: { hooks: { PreToolUse: [{ hooks: [async (input, toolUseId, { signal }) => { console.log(`Tool request: ${input.tool_name}`); // 自定义验证逻辑 if (input.tool_name === "Bash") { const command = input.tool_input.command; if (command.startsWith("rm -rf")) { return { decision: "block", reason: "Dangerous command blocked" }; } } return { continue: true }; }] }], PostToolUse: [{ hooks: [async (input, toolUseId, { signal }) => { console.log(`Tool completed: ${input.tool_name}`); // 记录或审计工具结果 return { continue: true }; }] }] } }});
Python 版本钩子实现:
from claude_code_sdk import query, ClaudeCodeOptions, HookMatcher, HookContextasyncdef pre_tool_hook( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: print(f"Tool request: {input_data['tool_name']}") if input_data['tool_name'] == 'Bash': command = input_data['tool_input'].get('command', '') if command.startswith('rm -rf'): return { 'hookSpecificOutput': { 'hookEventName': 'PreToolUse', 'permissionDecision': 'deny', 'permissionDecisionReason': 'Dangerous command blocked' } } return {}options = ClaudeCodeOptions( hooks={ 'PreToolUse': [ HookMatcher(matcher='Bash', hooks=[pre_tool_hook]) ] })
权限规则
在 settings.json 中配置声明式权限规则:
{ "permissions": { "allow": [ "Bash(npm run lint)", "Bash(npm run test:*)", "Read(~/.zshrc)" ], "deny": [ "Bash(curl:*)", "Read(./.env)", "Read(./secrets/**)", "WebFetch" ], "ask": [ "Bash(git push:*)", "Write(./production/**)" ] }}
规则语法说明:
Bash 规则 :使用前缀匹配。例如 Bash(npm:*) 匹配任何以 "npm" 开头的命令
文件规则 :支持 glob 模式。例如 Read(./src/**/*.ts) 匹配 src 目录下的所有 TypeScript 文件
工具规则 :省略括号控制整个工具。例如 WebFetch 阻止所有网络获取
实用工具示例
数据库查询工具
const databaseServer = createSdkMcpServer({ name: "database-tools", version: "1.0.0", tools: [ tool( "query_database", "Execute a database query", { query: z.string().describe("SQL query to execute"), params: z.array(z.any()).optional().describe("Query parameters") }, async (args) => { const results = await db.query(args.query, args.params || []); return { content: [{ type: "text", text: `Found ${results.length} rows:n${JSON.stringify(results, null, 2)}` }] }; } ) ]});
API 网关工具
这个工具可以调用多个外部服务:
const apiGatewayServer = createSdkMcpServer({ name: "api-gateway", version: "1.0.0", tools: [ tool( "api_request", "Make authenticated API requests to external services", { service: z.enum(["stripe", "github", "openai", "slack"]).describe("Service to call"), endpoint: z.string().describe("API endpoint path"), method: z.enum(["GET", "POST", "PUT", "DELETE"]).describe("HTTP method"), body: z.record(z.any()).optional().describe("Request body"), query: z.record(z.string()).optional().describe("Query parameters") }, async (args) => { const config = { stripe: { baseUrl: "https://api.stripe.com/v1", key: process.env.STRIPE_KEY }, github: { baseUrl: "https://api.github.com", key: process.env.GITHUB_TOKEN }, openai: { baseUrl: "https://api.openai.com/v1", key: process.env.OPENAI_KEY }, slack: { baseUrl: "https://slack.com/api", key: process.env.SLACK_TOKEN } }; const { baseUrl, key } = config[args.service]; const url = new URL(`${baseUrl}${args.endpoint}`); if (args.query) { Object.entries(args.query).forEach(([k, v]) => url.searchParams.set(k, v)); } const response = await fetch(url, { method: args.method, headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" }, body: args.body ? JSON.stringify(args.body) : undefined }); const data = await response.json(); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }; } ) ]});
计算器工具
包含基础运算和复利计算:
const calculatorServer = createSdkMcpServer({ name: "calculator", version: "1.0.0", tools: [ tool( "calculate", "Perform mathematical calculations", { expression: z.string().describe("Mathematical expression to evaluate"), precision: z.number().optional().default(2).describe("Decimal precision") }, async (args) => { try { // 生产环境使用安全的数学计算库 const result = eval(args.expression); // 仅示例! const formatted = Number(result).toFixed(args.precision); return { content: [{ type: "text", text: `${args.expression} = ${formatted}` }] }; } catch (error) { return { content: [{ type: "text", text: `Error: Invalid expression - ${error.message}` }] }; } } ), tool( "compound_interest", "Calculate compound interest for an investment", { principal: z.number().positive().describe("Initial investment amount"), rate: z.number().describe("Annual interest rate (as decimal)"), time: z.number().positive().describe("Investment period in years"), n: z.number().positive().default(12).describe("Compounding frequency per year") }, async (args) => { const amount = args.principal * Math.pow(1 + args.rate / args.n, args.n * args.time); const interest = amount - args.principal; return { content: [{ type: "text", text: `Investment Analysis:n` + `Principal: $${args.principal.toFixed(2)}n` + `Rate: ${(args.rate * 100).toFixed(2)}%n` + `Time: ${args.time} yearsn` + `Compounding: ${args.n} times per yearnn` + `Final Amount: $${amount.toFixed(2)}n` + `Interest Earned: $${interest.toFixed(2)}n` + `Return: ${((interest / args.principal) * 100).toFixed(2)}%` }] }; } ) ]});
多工具协同
当 MCP 服务器有多个工具时,可以选择性地允许它们:
const multiToolServer = createSdkMcpServer({ name: "utilities", version: "1.0.0", tools: [ tool("calculate", "Perform calculations", { /* ... */ }, async (args) => { /* ... */ }), tool("translate", "Translate text", { /* ... */ }, async (args) => { /* ... */ }), tool("search_web", "Search the web", { /* ... */ }, async (args) => { /* ... */ }) ]});// 只允许特定工具asyncfunction* generateMessages() {yield { type: "user"asconst, message: { role: "user"asconst, content: "Calculate 5 + 3 and translate 'hello' to Spanish" } };}forawait (const message of query({ prompt: generateMessages(), options: { mcpServers: { utilities: multiToolServer }, allowedTools: [ "mcp__utilities__calculate", // 允许计算器 "mcp__utilities__translate", // 允许翻译器 // "mcp__utilities__search_web" 不被允许 ] }})) {// 处理消息}
错误处理
优雅地处理错误,可以提供有意义的反馈:
tool( "fetch_data","Fetch data from an API", { endpoint: z.string().url().describe("API endpoint URL") },async (args) => { try { const response = await fetch(args.endpoint); if (!response.ok) { return { content: [{ type: "text", text: `API error: ${response.status} ${response.statusText}` }] }; } const data = await response.json(); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Failed to fetch data: ${error.message}` }] }; } })
Python 类型安全
Python 版本支持多种模式定义方法:
# 简单类型映射 - 推荐用于大多数情况@tool( "process_data", "Process structured data with type safety", { "name": str, "age": int, "email": str, "preferences": list # 可选参数可以在函数中处理 })asyncdef process_data(args: dict[str, Any]) -> dict[str, Any]: name = args["name"] age = args["age"] email = args["email"] preferences = args.get("preferences", []) print(f"Processing {name}'s data (age: {age})") return { "content": [{ "type": "text", "text": f"Processed data for {name}" }] }# 对于更复杂的模式,可以使用 JSON Schema 格式@tool( "advanced_process", "Process data with advanced validation", { "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "integer", "minimum": 0, "maximum": 150}, "email": {"type": "string", "format": "email"}, "format": {"type": "string", "enum": ["json", "csv", "xml"], "default": "json"} }, "required": ["name", "age", "email"] })asyncdef advanced_process(args: dict[str, Any]) -> dict[str, Any]: return { "content": [{ "type": "text", "text": f"Advanced processing for {args['name']}" }] }
完整功能支持
SDK 提供了对所有 Claude Code 默认功能的访问,通过相同的文件系统配置:
子智能体 :存储在 ./.claude/agents/ 的专用智能体
钩子 :在 ./.claude/settings.json 中配置的自定义命令
斜杠命令 :定义在 ./.claude/commands/ 的 Markdown 文件
记忆(CLAUDE.md) :通过 CLAUDE.md 文件维护项目上下文
这些功能通过读取相同的文件系统位置来工作,与 Claude Code 对应功能完全一致。
可以构建什么
根据文档,基于 Claude Code SDK 我们可以构建各类 Agent,包括但不限于:
编码智能体 :
SRE 智能体诊断和修复生产问题
安全审查机器人审计代码漏洞
值班工程助手分类事件
代码审查智能体执行风格和最佳实践
业务智能体 :
法律助手审查合同和合规性
财务顾问分析报告和预测
客户支持智能体解决技术问题
营销团队的内容创建助手
现在,所有这些 Agent 都可以通过 Claude Code SDK 轻松实现,而不需要从零开始构建复杂的基础设施了。
封装一下业务 API,弄弄数据,搞搞 UI,就可以了。

顺便,我还让 Claude 给做了个 《基于 Claude Code SDK 开发 Agent》的PPT,贴上来供参考:



















[1]
自定义工具文档: https://docs.anthropic.com/en/docs/claude-code/sdk/custom-tools
[2]
SDK 权限文档: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-permissions
[3]
SDK 概览: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-overview
[4]
子智能体指南: https://docs.anthropic.com/en/docs/claude-code/sdk/subagents
[5]
斜杠命令指南: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-slash-commands
[6]
版权声明:
作者:shadowrocket
链接:https://www.shadowrocket9.top/92.html
来源:Shadowrocket官网
文章版权归作者所有,未经允许请勿转载。


共有 0 条评论