open-agent-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Open Agent SDK

Open Agent SDK

Skill by ara.so — Daily 2026 Skills collection.
Open Agent SDK (
@shipany/open-agent-sdk
) is a fully open-source, in-process AI agent framework for TypeScript/Node.js. It runs the complete Claude Code agent engine directly — no local CLI subprocess required — making it suitable for cloud servers, serverless functions, Docker containers, and CI/CD pipelines. It is API-compatible with
@anthropic-ai/claude-agent-sdk
.

ara.so开发的Skill — 2026年度Skill合集。
Open Agent SDK(
@shipany/open-agent-sdk
)是面向TypeScript/Node.js的完全开源的进程内AI Agent框架。它直接运行完整的Claude Code Agent引擎,无需本地CLI子进程,因此适用于云服务器、Serverless函数、Docker容器和CI/CD流水线。它与
@anthropic-ai/claude-agent-sdk
的API完全兼容。

Installation

安装

sh
npm install @shipany/open-agent-sdk
Requires Node.js 18+.

sh
npm install @shipany/open-agent-sdk
需要Node.js 18及以上版本。

Authentication & Configuration

认证与配置

Set the Anthropic API key as an environment variable:
sh
export ANTHROPIC_API_KEY=your-api-key
Or use a third-party provider (e.g. OpenRouter):
sh
export ANTHROPIC_BASE_URL=https://openrouter.ai/api
export ANTHROPIC_API_KEY=your-openrouter-key
export ANTHROPIC_MODEL=anthropic/claude-sonnet-4-6
These can also be passed programmatically via
options.env
or
apiKey
/
baseURL
in
createAgent()
.

将Anthropic API密钥设置为环境变量:
sh
export ANTHROPIC_API_KEY=your-api-key
也可以使用第三方服务商(例如OpenRouter):
sh
export ANTHROPIC_BASE_URL=https://openrouter.ai/api
export ANTHROPIC_API_KEY=your-openrouter-key
export ANTHROPIC_MODEL=anthropic/claude-sonnet-4-6
你也可以通过
options.env
或者
createAgent()
中的
apiKey
/
baseURL
参数以编程方式传入这些配置。

Core API

核心API

query({ prompt, options })
— Streaming, compatible with official SDK

query({ prompt, options })
— 流式响应,与官方SDK兼容

Returns an
AsyncGenerator<SDKMessage>
. Drop-in replacement for
@anthropic-ai/claude-agent-sdk
.
typescript
import { query } from '@shipany/open-agent-sdk'

for await (const message of query({
  prompt: 'Find and fix the bug in auth.ts',
  options: {
    allowedTools: ['Read', 'Edit', 'Bash'],
    permissionMode: 'acceptEdits',
  },
})) {
  if (message.type === 'assistant' && message.message?.content) {
    for (const block of message.message.content) {
      if ('text' in block) process.stdout.write(block.text)
      else if ('name' in block) console.log(`\n[Tool used: ${block.name}]`)
    }
  } else if (message.type === 'result') {
    console.log(`\nDone: ${message.subtype}`)
  }
}

返回
AsyncGenerator<SDKMessage>
,可直接替换
@anthropic-ai/claude-agent-sdk
的对应方法。
typescript
import { query } from '@shipany/open-agent-sdk'

for await (const message of query({
  prompt: 'Find and fix the bug in auth.ts',
  options: {
    allowedTools: ['Read', 'Edit', 'Bash'],
    permissionMode: 'acceptEdits',
  },
})) {
  if (message.type === 'assistant' && message.message?.content) {
    for (const block of message.message.content) {
      if ('text' in block) process.stdout.write(block.text)
      else if ('name' in block) console.log(`\n[Tool used: ${block.name}]`)
    }
  } else if (message.type === 'result') {
    console.log(`\nDone: ${message.subtype}`)
  }
}

createAgent(options)
— Reusable agent with session state

createAgent(options)
— 带会话状态的可复用Agent

typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  model: 'claude-sonnet-4-6',
  systemPrompt: 'You are a senior TypeScript engineer. Be concise.',
  maxTurns: 20,
})

// Blocking call
const result = await agent.prompt('Read package.json and describe the project')
console.log(result.text)
console.log(`Tokens used: ${result.usage.input_tokens + result.usage.output_tokens}`)

// Streaming call
for await (const msg of agent.query('Now add JSDoc to all exported functions')) {
  if (msg.type === 'assistant' && msg.message?.content) {
    for (const block of msg.message.content) {
      if ('text' in block) process.stdout.write(block.text)
    }
  }
}

// Session management
const history = agent.getMessages()  // full conversation history
agent.clear()                        // reset session

typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  model: 'claude-sonnet-4-6',
  systemPrompt: 'You are a senior TypeScript engineer. Be concise.',
  maxTurns: 20,
})

// 阻塞调用
const result = await agent.prompt('Read package.json and describe the project')
console.log(result.text)
console.log(`Tokens used: ${result.usage.input_tokens + result.usage.output_tokens}`)

// 流式调用
for await (const msg of agent.query('Now add JSDoc to all exported functions')) {
  if (msg.type === 'assistant' && msg.message?.content) {
    for (const block of msg.message.content) {
      if ('text' in block) process.stdout.write(block.text)
    }
  }
}

// 会话管理
const history = agent.getMessages()  // 完整对话历史
agent.clear()                        // 重置会话

Options Reference

选项参考

OptionTypeDefaultDescription
model
string
claude-sonnet-4-6
Claude model ID
apiKey
string
ANTHROPIC_API_KEY
env
API key
baseURL
string
Anthropic APIOverride for third-party providers
cwd
string
process.cwd()
Working directory for file/shell tools
systemPrompt
string
Custom system prompt prepended to agent
tools
Tool[]
All built-inOverride the full tool list
allowedTools
string[]
allWhitelist specific tools by name
permissionMode
string
bypassPermissions
acceptEdits
,
bypassPermissions
,
plan
,
default
maxTurns
number
100
Maximum agentic loop iterations
maxBudgetUsd
number
Spend cap in USD
mcpServers
object
MCP server configs (stdio/SSE/HTTP)
agents
object
Named subagent definitions
hooks
object
Lifecycle hooks:
PreToolUse
,
PostToolUse
,
Stop
thinking
object
Extended thinking config
env
object
Environment variables passed to tools
resume
string
Resume prior session by session ID
canUseTool
function
Custom permission callback
(tool, input) => boolean
includePartialMessages
boolean
false
Emit raw streaming events

选项类型默认值描述
model
string
claude-sonnet-4-6
Claude模型ID
apiKey
string
ANTHROPIC_API_KEY
环境变量
API密钥
baseURL
string
Anthropic官方API地址可覆写为第三方服务商的API地址
cwd
string
process.cwd()
文件/Shell工具的工作目录
systemPrompt
string
为Agent添加的自定义系统提示词
tools
Tool[]
所有内置工具覆写完整的工具列表
allowedTools
string[]
所有工具按名称白名单指定可用工具
permissionMode
string
bypassPermissions
可选值:
acceptEdits
bypassPermissions
plan
default
maxTurns
number
100
Agent循环执行的最大轮次
maxBudgetUsd
number
最大花费上限,单位为美元
mcpServers
object
MCP服务器配置(stdio/SSE/HTTP)
agents
object
命名子Agent定义
hooks
object
生命周期钩子:
PreToolUse
PostToolUse
Stop
thinking
object
扩展思考配置
env
object
传递给工具的环境变量
resume
string
通过会话ID恢复之前的会话
canUseTool
function
自定义权限回调:
(tool, input) => boolean
includePartialMessages
boolean
false
输出原始流式事件

Common Patterns

常用模式

Multi-turn conversation with context

带上下文的多轮对话

typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({ model: 'claude-sonnet-4-6' })

const r1 = await agent.prompt('Read src/index.ts and explain the architecture')
console.log(r1.text)

// Context from r1 is preserved automatically
const r2 = await agent.prompt('Refactor the error handling to use a Result type')
console.log(r2.text)
typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({ model: 'claude-sonnet-4-6' })

const r1 = await agent.prompt('Read src/index.ts and explain the architecture')
console.log(r1.text)

// r1的上下文会自动保留
const r2 = await agent.prompt('Refactor the error handling to use a Result type')
console.log(r2.text)

Restrict to read-only tools

限制为只读工具

typescript
import { query } from '@shipany/open-agent-sdk'

for await (const message of query({
  prompt: 'Review this codebase for security issues',
  options: {
    allowedTools: ['Read', 'Glob', 'Grep'],
    // No Write, Edit, or Bash — agent cannot modify files
  },
})) {
  if (message.type === 'result') console.log('Review complete')
}
typescript
import { query } from '@shipany/open-agent-sdk'

for await (const message of query({
  prompt: 'Review this codebase for security issues',
  options: {
    allowedTools: ['Read', 'Glob', 'Grep'],
    // 没有Write、Edit或Bash权限,Agent无法修改文件
  },
})) {
  if (message.type === 'result') console.log('Review complete')
}

Custom tools

自定义工具

typescript
import { createAgent, getAllBaseTools } from '@shipany/open-agent-sdk'

const dbQueryTool = {
  name: 'QueryDatabase',
  description: 'Run a read-only SQL query and return results as JSON',
  inputJSONSchema: {
    type: 'object',
    properties: {
      sql: { type: 'string', description: 'The SQL query to run' },
    },
    required: ['sql'],
  },
  get inputSchema() {
    return { safeParse: (v: unknown) => ({ success: true, data: v }) }
  },
  async prompt() { return this.description },
  async call(input: { sql: string }) {
    // Replace with your actual DB client
    const rows = [{ id: 1, name: 'Example' }]
    return { data: JSON.stringify(rows) }
  },
  userFacingName: () => 'QueryDatabase',
  isReadOnly: () => true,
  isConcurrencySafe: () => true,
  mapToolResultToToolResultBlockParam: (data: string, id: string) => ({
    type: 'tool_result' as const,
    tool_use_id: id,
    content: data,
  }),
}

const agent = createAgent({
  tools: [...getAllBaseTools(), dbQueryTool],
})

const result = await agent.prompt('How many users signed up in the last 7 days?')
console.log(result.text)
typescript
import { createAgent, getAllBaseTools } from '@shipany/open-agent-sdk'

const dbQueryTool = {
  name: 'QueryDatabase',
  description: 'Run a read-only SQL query and return results as JSON',
  inputJSONSchema: {
    type: 'object',
    properties: {
      sql: { type: 'string', description: 'The SQL query to run' },
    },
    required: ['sql'],
  },
  get inputSchema() {
    return { safeParse: (v: unknown) => ({ success: true, data: v }) }
  },
  async prompt() { return this.description },
  async call(input: { sql: string }) {
    // 替换为实际的数据库客户端
    const rows = [{ id: 1, name: 'Example' }]
    return { data: JSON.stringify(rows) }
  },
  userFacingName: () => 'QueryDatabase',
  isReadOnly: () => true,
  isConcurrencySafe: () => true,
  mapToolResultToToolResultBlockParam: (data: string, id: string) => ({
    type: 'tool_result' as const,
    tool_use_id: id,
    content: data,
  }),
}

const agent = createAgent({
  tools: [...getAllBaseTools(), dbQueryTool],
})

const result = await agent.prompt('How many users signed up in the last 7 days?')
console.log(result.text)

MCP server integration

MCP服务器集成

typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  mcpServers: {
    filesystem: {
      command: 'npx',
      args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
    },
    playwright: {
      command: 'npx',
      args: ['@playwright/mcp@latest'],
    },
  },
})

const result = await agent.prompt('List all .json files in /tmp')
console.log(result.text)
typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  mcpServers: {
    filesystem: {
      command: 'npx',
      args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
    },
    playwright: {
      command: 'npx',
      args: ['@playwright/mcp@latest'],
    },
  },
})

const result = await agent.prompt('List all .json files in /tmp')
console.log(result.text)

Subagents for parallel / delegated work

用于并行/委派任务的子Agent

typescript
import { query } from '@shipany/open-agent-sdk'

for await (const message of query({
  prompt: 'Use the security-auditor agent to audit src/ for vulnerabilities',
  options: {
    allowedTools: ['Read', 'Glob', 'Grep', 'Agent'],
    agents: {
      'security-auditor': {
        description: 'Expert security auditor for TypeScript codebases.',
        prompt: 'Identify OWASP Top 10 vulnerabilities and suggest fixes.',
        tools: ['Read', 'Glob', 'Grep'],
      },
    },
  },
})) {
  if (message.type === 'assistant' && message.message?.content) {
    for (const block of message.message.content) {
      if ('text' in block) console.log(block.text)
    }
  }
}
typescript
import { query } from '@shipany/open-agent-sdk'

for await (const message of query({
  prompt: 'Use the security-auditor agent to audit src/ for vulnerabilities',
  options: {
    allowedTools: ['Read', 'Glob', 'Grep', 'Agent'],
    agents: {
      'security-auditor': {
        description: 'Expert security auditor for TypeScript codebases.',
        prompt: 'Identify OWASP Top 10 vulnerabilities and suggest fixes.',
        tools: ['Read', 'Glob', 'Grep'],
      },
    },
  },
})) {
  if (message.type === 'assistant' && message.message?.content) {
    for (const block of message.message.content) {
      if ('text' in block) console.log(block.text)
    }
  }
}

Custom permission callback

自定义权限回调

typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  canUseTool: (toolName: string, input: unknown) => {
    // Prevent deletion commands
    if (toolName === 'Bash') {
      const cmd = (input as { command?: string }).command ?? ''
      if (cmd.includes('rm ') || cmd.includes('drop table')) return false
    }
    return true
  },
})
typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  canUseTool: (toolName: string, input: unknown) => {
    // 阻止删除命令
    if (toolName === 'Bash') {
      const cmd = (input as { command?: string }).command ?? ''
      if (cmd.includes('rm ') || cmd.includes('drop table')) return false
    }
    return true
  },
})

Lifecycle hooks

生命周期钩子

typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  hooks: {
    PreToolUse: async ({ tool, input }) => {
      console.log(`About to run tool: ${tool} with input:`, input)
    },
    PostToolUse: async ({ tool, output }) => {
      console.log(`Tool ${tool} finished`)
    },
    Stop: async ({ result }) => {
      console.log('Agent stopped. Final result:', result)
    },
  },
})
typescript
import { createAgent } from '@shipany/open-agent-sdk'

const agent = createAgent({
  hooks: {
    PreToolUse: async ({ tool, input }) => {
      console.log(`About to run tool: ${tool} with input:`, input)
    },
    PostToolUse: async ({ tool, output }) => {
      console.log(`Tool ${tool} finished`)
    },
    Stop: async ({ result }) => {
      console.log('Agent stopped. Final result:', result)
    },
  },
})

Resume a previous session

恢复之前的会话

typescript
import { createAgent } from '@shipany/open-agent-sdk'

// First session
const agent1 = createAgent({ model: 'claude-sonnet-4-6' })
const r1 = await agent1.prompt('Read ARCHITECTURE.md')
const sessionId = r1.sessionId  // save this

// Later — resume where you left off
const agent2 = createAgent({
  model: 'claude-sonnet-4-6',
  resume: sessionId,
})
const r2 = await agent2.prompt('Now implement the TODO in section 3')

typescript
import { createAgent } from '@shipany/open-agent-sdk'

// 第一个会话
const agent1 = createAgent({ model: 'claude-sonnet-4-6' })
const r1 = await agent1.prompt('Read ARCHITECTURE.md')
const sessionId = r1.sessionId  // 保存这个ID

// 后续可以从断开的位置恢复会话
const agent2 = createAgent({
  model: 'claude-sonnet-4-6',
  resume: sessionId,
})
const r2 = await agent2.prompt('Now implement the TODO in section 3')
console.log(r2.text)

Built-in Tools Reference

内置工具参考

ToolRead-onlyDescription
Read
Read files, images, PDFs with line numbers
Glob
Find files by glob pattern
Grep
Search file contents with regex (uses ripgrep)
WebFetch
Fetch and parse web pages
WebSearch
Web search
Write
Create or overwrite files
Edit
Precise string replacement in files
Bash
Execute shell commands
Agent
Spawn subagents
TodoWrite
Manage todo lists
NotebookEdit
Edit Jupyter notebooks
TaskCreate/Update/List
Task management
TeamCreate/Delete
Agent team management
EnterPlanMode/ExitPlanMode
Plan approval workflow
EnterWorktree/ExitWorktree
Git worktree isolation
ListMcpResources/ReadMcpResource
MCP resource access

工具只读描述
Read
读取文件、图片、PDF,带行号
Glob
按glob模式查找文件
Grep
用正则搜索文件内容(基于ripgrep)
WebFetch
抓取并解析网页
WebSearch
网页搜索
Write
创建或覆盖文件
Edit
精确替换文件中的字符串
Bash
执行Shell命令
Agent
生成子Agent
TodoWrite
管理待办列表
NotebookEdit
编辑Jupyter笔记本
TaskCreate/Update/List
任务管理
TeamCreate/Delete
Agent团队管理
EnterPlanMode/ExitPlanMode
计划审批工作流
EnterWorktree/ExitWorktree
Git工作树隔离
ListMcpResources/ReadMcpResource
MCP资源访问

Architecture: How It Differs from Official SDK

架构:与官方SDK的差异

Official
@anthropic-ai/claude-agent-sdk
:
Your code → SDK → spawn cli.js subprocess → stdin/stdout JSON → Anthropic API
Open Agent SDK:
Your code → SDK → QueryEngine (in-process) → Anthropic API (direct HTTP)
This means:
  • No CLI installation required in the deployment environment
  • Works in serverless (AWS Lambda, Vercel, Cloudflare Workers with Node.js compat)
  • Works in Docker with just
    npm install
  • Works in CI/CD without CLI setup steps
  • Programmatic access to the full agent engine

官方
@anthropic-ai/claude-agent-sdk
你的代码 → SDK → 启动cli.js子进程 → stdin/stdout传输JSON → Anthropic API
Open Agent SDK:
你的代码 → SDK → QueryEngine(进程内) → 直接调用Anthropic API(HTTP)
这种架构的优势:
  • 部署环境无需安装CLI
  • 可在Serverless环境运行(AWS Lambda、Vercel、兼容Node.js的Cloudflare Workers)
  • 仅需
    npm install
    即可在Docker中运行
  • 无需CLI配置步骤即可在CI/CD中运行
  • 可通过编程方式访问完整的Agent引擎

Troubleshooting

问题排查

Error: ANTHROPIC_API_KEY is not set
→ Export the env var or pass
apiKey
directly in
createAgent({ apiKey: process.env.MY_KEY })
.
Agent exceeds
maxTurns
without completing
→ Increase
maxTurns
or narrow the task. Check
message.subtype === 'max_turns'
in the result.
Tool not found /
allowedTools
not working
→ Tool names are case-sensitive:
'Read'
,
'Edit'
,
'Bash'
,
'Glob'
,
'Grep'
,
'WebFetch'
, etc.
Using with OpenRouter or other providers → Set
ANTHROPIC_BASE_URL
to the provider's base URL and use their model string format, e.g.
anthropic/claude-sonnet-4-6
for OpenRouter.
Agent modifies files unexpectedly → Use
allowedTools: ['Read', 'Glob', 'Grep']
to restrict to read-only tools, or set
permissionMode: 'plan'
to require approval before edits.
MCP server fails to start → Ensure the MCP server package is installed or accessible via
npx
. Check
command
and
args
match what the MCP package expects.
TypeScript types missing → The package ships its own types. Ensure
"moduleResolution": "bundler"
or
"node16"
in
tsconfig.json
and
"esModuleInterop": true
.

错误:ANTHROPIC_API_KEY is not set
→ 导出对应的环境变量,或者直接在
createAgent({ apiKey: process.env.MY_KEY })
中传入
apiKey
参数。
Agent未完成任务就超出
maxTurns
限制
→ 调高
maxTurns
的值,或者缩小任务范围。你可以在结果中检查
message.subtype === 'max_turns'
来判断是否是因为超出轮次限制终止。
找不到工具 /
allowedTools
配置不生效
→ 工具名称区分大小写:
'Read'
'Edit'
'Bash'
'Glob'
'Grep'
'WebFetch'
等。
配合OpenRouter或其他服务商使用 → 将
ANTHROPIC_BASE_URL
设置为服务商的基础URL,并使用他们的模型字符串格式,例如OpenRouter使用
anthropic/claude-sonnet-4-6
Agent意外修改文件 → 使用
allowedTools: ['Read', 'Glob', 'Grep']
限制为只读工具,或者设置
permissionMode: 'plan'
要求编辑前先获得审批。
MCP服务器启动失败 → 确保MCP服务器包已安装,或者可以通过
npx
访问。检查
command
args
是否与MCP包的要求一致。
缺少TypeScript类型定义 → 包本身自带类型定义。确保
tsconfig.json
中设置了
"moduleResolution": "bundler"
"node16"
,并且开启了
"esModuleInterop": true

Quick Reference

快速参考

typescript
// Minimal one-shot agent
import { createAgent } from '@shipany/open-agent-sdk'
const agent = createAgent({ model: 'claude-sonnet-4-6' })
const { text } = await agent.prompt('Summarize README.md in 3 bullet points')
console.log(text)
typescript
// 极简一次性Agent示例
import { createAgent } from '@shipany/open-agent-sdk'
const agent = createAgent({ model: 'claude-sonnet-4-6' })
const { text } = await agent.prompt('Summarize README.md in 3 bullet points')
console.log(text)