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
.
Installation
npm
install
@shipany/open-agent-sdk
Requires Node.js 18+.
Authentication & Configuration
Set the Anthropic API key as an environment variable:
export
ANTHROPIC_API_KEY
=
your-api-key
Or use a third-party provider (e.g. OpenRouter):
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()
.
Core API
query({ prompt, options })
— Streaming, compatible with official SDK
Returns an
AsyncGenerator\n[Tool used:
${
block
.
name
}
]
)
}
}
else
if
(
message
.
type
===
'result'
)
{
console
.
log
(
\nDone:
${
message
.
subtype
}
)
}
}
createAgent(options)
— Reusable agent with session state
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
Options Reference
Option
Type
Default
Description
model
string
claude-sonnet-4-6
Claude model ID
apiKey
string
ANTHROPIC_API_KEY
env
API key
baseURL
string
Anthropic API
Override 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-in
Override the full tool list
allowedTools
string[]
all
Whitelist 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
Common Patterns
Multi-turn conversation with context
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
)
Restrict to read-only tools
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'
)
}
Custom tools
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
)
MCP server integration
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
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
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
}
,
}
)
Lifecycle hooks
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
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'
)
Built-in Tools Reference
Tool
Read-only
Description
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
Architecture: How It Differs from Official 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
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
.
Quick Reference
// 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
)
open-agent-sdk
安装
npx skills add https://github.com/aradotso/trending-skills --skill open-agent-sdk