Open Agent SDK (TypeScript)

April 3, 2026 · View on GitHub

npm version Node.js License: MIT

Open-source Agent SDK that runs the full agent loop in-process — no subprocess or CLI required. Supports both Anthropic and OpenAI-compatible APIs. Deploy anywhere: cloud, serverless, Docker, CI/CD.

Also available in Go: open-agent-sdk-go

Get started

npm install @codeany/open-agent-sdk

Set your API key:

export CODEANY_API_KEY=your-api-key

OpenAI-compatible models

Works with OpenAI, DeepSeek, Qwen, Mistral, or any OpenAI-compatible endpoint:

export CODEANY_API_TYPE=openai-completions
export CODEANY_API_KEY=sk-...
export CODEANY_BASE_URL=https://api.openai.com/v1
export CODEANY_MODEL=gpt-4o

Third-party Anthropic-compatible providers

export CODEANY_BASE_URL=https://openrouter.ai/api
export CODEANY_API_KEY=sk-or-...
export CODEANY_MODEL=anthropic/claude-sonnet-4

Quick start

One-shot query (streaming)

import { query } from "@codeany/open-agent-sdk";

for await (const message of query({
  prompt: "Read package.json and tell me the project name.",
  options: {
    allowedTools: ["Read", "Glob"],
    permissionMode: "bypassPermissions",
  },
})) {
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if ("text" in block) console.log(block.text);
    }
  }
}

Simple blocking prompt

import { createAgent } from "@codeany/open-agent-sdk";

const agent = createAgent({ model: "claude-sonnet-4-6" });
const result = await agent.prompt("What files are in this project?");

console.log(result.text);
console.log(
  `Turns: ${result.num_turns}, Tokens: ${result.usage.input_tokens + result.usage.output_tokens}`,
);

OpenAI / GPT models

import { createAgent } from "@codeany/open-agent-sdk";

const agent = createAgent({
  apiType: "openai-completions",
  model: "gpt-4o",
  apiKey: "sk-...",
  baseURL: "https://api.openai.com/v1",
});

const result = await agent.prompt("What files are in this project?");
console.log(result.text);

The apiType is auto-detected from model name — models containing gpt-, o1, o3, deepseek, qwen, mistral, etc. automatically use openai-completions.

Multi-turn conversation

import { createAgent } from "@codeany/open-agent-sdk";

const agent = createAgent({ maxTurns: 5 });

const r1 = await agent.prompt(
  'Create a file /tmp/hello.txt with "Hello World"',
);
console.log(r1.text);

const r2 = await agent.prompt("Read back the file you just created");
console.log(r2.text);

console.log(`Session messages: ${agent.getMessages().length}`);

Custom tools (Zod schema)

import { z } from "zod";
import { query, tool, createSdkMcpServer } from "@codeany/open-agent-sdk";

const getWeather = tool(
  "get_weather",
  "Get the temperature for a city",
  { city: z.string().describe("City name") },
  async ({ city }) => ({
    content: [{ type: "text", text: `${city}: 22°C, sunny` }],
  }),
);

const server = createSdkMcpServer({ name: "weather", tools: [getWeather] });

for await (const msg of query({
  prompt: "What is the weather in Tokyo?",
  options: { mcpServers: { weather: server } },
})) {
  if (msg.type === "result")
    console.log(`Done: $${msg.total_cost_usd?.toFixed(4)}`);
}

Custom tools (low-level)

import {
  createAgent,
  getAllBaseTools,
  defineTool,
} from "@codeany/open-agent-sdk";

const calculator = defineTool({
  name: "Calculator",
  description: "Evaluate a math expression",
  inputSchema: {
    type: "object",
    properties: { expression: { type: "string" } },
    required: ["expression"],
  },
  isReadOnly: true,
  async call(input) {
    const result = Function(`'use strict'; return (${input.expression})`)();
    return `${input.expression} = ${result}`;
  },
});

const agent = createAgent({ tools: [...getAllBaseTools(), calculator] });
const r = await agent.prompt("Calculate 2**10 * 3");
console.log(r.text);

Skills

Skills are reusable prompt templates that extend agent capabilities. Five bundled skills are included: simplify, commit, review, debug, test.

import {
  createAgent,
  registerSkill,
  getAllSkills,
} from "@codeany/open-agent-sdk";

// Register a custom skill
registerSkill({
  name: "explain",
  description: "Explain a concept in simple terms",
  userInvocable: true,
  async getPrompt(args) {
    return [
      {
        type: "text",
        text: `Explain in simple terms: ${args || "Ask what to explain."}`,
      },
    ];
  },
});

console.log(`${getAllSkills().length} skills registered`);

// The model can invoke skills via the Skill tool
const agent = createAgent();
const result = await agent.prompt('Use the "explain" skill to explain git rebase');
console.log(result.text);

Hooks (lifecycle events)

import { createAgent, createHookRegistry } from "@codeany/open-agent-sdk";

const hooks = createHookRegistry({
  PreToolUse: [
    {
      handler: async (input) => {
        console.log(`About to use: ${input.toolName}`);
        // Return { block: true } to prevent tool execution
      },
    },
  ],
  PostToolUse: [
    {
      handler: async (input) => {
        console.log(`Tool ${input.toolName} completed`);
      },
    },
  ],
});

20 lifecycle events: PreToolUse, PostToolUse, PostToolUseFailure, SessionStart, SessionEnd, Stop, SubagentStart, SubagentStop, UserPromptSubmit, PermissionRequest, PermissionDenied, TaskCreated, TaskCompleted, ConfigChange, CwdChanged, FileChanged, Notification, PreCompact, PostCompact, TeammateIdle.

MCP server integration

import { createAgent } from "@codeany/open-agent-sdk";

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

const result = await agent.prompt("List files in /tmp");
console.log(result.text);
await agent.close();

Subagents

import { query } from "@codeany/open-agent-sdk";

for await (const msg of query({
  prompt: "Use the code-reviewer agent to review src/index.ts",
  options: {
    agents: {
      "code-reviewer": {
        description: "Expert code reviewer",
        prompt: "Analyze code quality. Focus on security and performance.",
        tools: ["Read", "Glob", "Grep"],
      },
    },
  },
})) {
  if (msg.type === "result") console.log("Done");
}

Permissions

import { query } from "@codeany/open-agent-sdk";

// Read-only agent — can only analyze, not modify
for await (const msg of query({
  prompt: "Review the code in src/ for best practices.",
  options: {
    allowedTools: ["Read", "Glob", "Grep"],
    permissionMode: "dontAsk",
  },
})) {
  // ...
}

Web UI

A built-in web chat interface is included for testing:

npx tsx examples/web/server.ts
# Open http://localhost:8081

API reference

Top-level functions

FunctionDescription
query({ prompt, options })One-shot streaming query, returns AsyncGenerator<SDKMessage>
createAgent(options)Create a reusable agent with session persistence
tool(name, desc, schema, handler)Create a tool with Zod schema validation
createSdkMcpServer({ name, tools })Bundle tools into an in-process MCP server
defineTool(config)Low-level tool definition helper
getAllBaseTools()Get all 35+ built-in tools
registerSkill(definition)Register a custom skill
getAllSkills()Get all registered skills
createProvider(apiType, opts)Create an LLM provider directly
createHookRegistry(config)Create a hook registry for lifecycle events
listSessions()List persisted sessions
forkSession(id)Fork a session for branching

Agent methods

MethodDescription
agent.query(prompt)Streaming query, returns AsyncGenerator<SDKMessage>
agent.prompt(text)Blocking query, returns Promise<QueryResult>
agent.getMessages()Get conversation history
agent.clear()Reset session
agent.interrupt()Abort current query
agent.setModel(model)Change model mid-session
agent.setPermissionMode(mode)Change permission mode
agent.getApiType()Get current API type
agent.close()Close MCP connections, persist session

Options

OptionTypeDefaultDescription
apiTypestringauto-detected'anthropic-messages' or 'openai-completions'
modelstringclaude-sonnet-4-6LLM model ID
apiKeystringCODEANY_API_KEYAPI key
baseURLstringCustom API endpoint
cwdstringprocess.cwd()Working directory
systemPromptstringSystem prompt override
appendSystemPromptstringAppend to default system prompt
toolsToolDefinition[]All built-inAvailable tools
allowedToolsstring[]Tool allow-list
disallowedToolsstring[]Tool deny-list
permissionModestringbypassPermissionsdefault / acceptEdits / dontAsk / bypassPermissions / plan
canUseToolfunctionCustom permission callback
maxTurnsnumber10Max agentic turns
maxBudgetUsdnumberSpending cap
thinkingThinkingConfig{ type: 'adaptive' }Extended thinking
effortstringhighReasoning effort: low / medium / high / max
mcpServersRecord<string, McpServerConfig>MCP server connections
agentsRecord<string, AgentDefinition>Subagent definitions
hooksRecord<string, HookCallbackMatcher[]>Lifecycle hooks
resumestringResume session by ID
continuebooleanfalseContinue most recent session
persistSessionbooleantruePersist session to disk
sessionIdstringautoExplicit session ID
outputFormat{ type: 'json_schema', schema }Structured output
sandboxSandboxSettingsFilesystem/network sandbox
settingSourcesSettingSource[]Load AGENT.md, project settings
envRecord<string, string>Environment variables
abortControllerAbortControllerCancellation controller

Environment variables

VariableDescription
CODEANY_API_KEYAPI key (required)
CODEANY_API_TYPEanthropic-messages (default) or openai-completions
CODEANY_MODELDefault model override
CODEANY_BASE_URLCustom API endpoint
CODEANY_AUTH_TOKENAlternative auth token

Built-in tools

ToolDescription
BashExecute shell commands
ReadRead files with line numbers
WriteCreate / overwrite files
EditPrecise string replacement in files
GlobFind files by pattern
GrepSearch file contents with regex
WebFetchFetch and parse web content
WebSearchSearch the web
NotebookEditEdit Jupyter notebook cells
AgentSpawn subagents for parallel work
SkillInvoke registered skills
TaskCreate/List/Update/Get/Stop/OutputTask management system
TeamCreate/DeleteMulti-agent team coordination
SendMessageInter-agent messaging
EnterWorktree/ExitWorktreeGit worktree isolation
EnterPlanMode/ExitPlanModeStructured planning workflow
AskUserQuestionAsk the user for input
ToolSearchDiscover lazy-loaded tools
ListMcpResources/ReadMcpResourceMCP resource access
CronCreate/Delete/ListScheduled task management
RemoteTriggerRemote agent triggers
LSPLanguage Server Protocol (code intelligence)
ConfigDynamic configuration
TodoWriteSession todo list

Bundled skills

SkillDescription
simplifyReview changed code for reuse, quality, and efficiency
commitCreate a git commit with a well-crafted message
reviewReview code changes for correctness, security, and performance
debugSystematic debugging using structured investigation
testRun tests and analyze failures

Register custom skills with registerSkill().

Architecture

┌──────────────────────────────────────────────────────┐
│                   Your Application                    │
│                                                       │
│   import { createAgent } from '@codeany/open-agent-sdk' │
└────────────────────────┬─────────────────────────────┘

              ┌──────────▼──────────┐
              │       Agent         │  Session state, tool pool,
              │  query() / prompt() │  MCP connections, hooks
              └──────────┬──────────┘

              ┌──────────▼──────────┐
              │    QueryEngine      │  Agentic loop:
              │   submitMessage()   │  API call → tools → repeat
              └──────────┬──────────┘

         ┌───────────────┼───────────────┐
         │               │               │
   ┌─────▼─────┐  ┌─────▼─────┐  ┌─────▼─────┐
   │  Provider  │  │  35 Tools │  │    MCP     │
   │ Anthropic  │  │ Bash,Read │  │  Servers   │
   │  OpenAI    │  │ Edit,...  │  │ stdio/SSE/ │
   │ DeepSeek   │  │ + Skills  │  │ HTTP/SDK   │
   └───────────┘  └───────────┘  └───────────┘

Key internals:

ComponentDescription
Provider layerAbstracts Anthropic / OpenAI API differences
QueryEngineCore agentic loop with auto-compact, retry, tool orchestration
Skill systemReusable prompt templates with 5 bundled skills
Hook system20 lifecycle events integrated into the engine
Auto-compactSummarizes conversation when context window fills up
Micro-compactTruncates oversized tool results
RetryExponential backoff for rate limits and transient errors
Token estimationRough token counting with pricing for Claude, GPT, DeepSeek models
File cacheLRU cache (100 entries, 25 MB) for file reads
Session storagePersist / resume / fork sessions on disk
Context injectionGit status + AGENT.md automatically injected into system prompt

Examples

#FileDescription
01examples/01-simple-query.tsStreaming query with event handling
02examples/02-multi-tool.tsMulti-tool orchestration (Glob + Bash)
03examples/03-multi-turn.tsMulti-turn session persistence
04examples/04-prompt-api.tsBlocking prompt() API
05examples/05-custom-system-prompt.tsCustom system prompt
06examples/06-mcp-server.tsMCP server integration
07examples/07-custom-tools.tsCustom tools with defineTool()
08examples/08-official-api-compat.tsquery() API pattern
09examples/09-subagents.tsSubagent delegation
10examples/10-permissions.tsRead-only agent with tool restrictions
11examples/11-custom-mcp-tools.tstool() + createSdkMcpServer()
12examples/12-skills.tsSkill system usage
13examples/13-hooks.tsLifecycle hooks
14examples/14-openai-compat.tsOpenAI / DeepSeek models
webexamples/web/Web chat UI for testing

Run any example:

npx tsx examples/01-simple-query.ts

Start the web UI:

npx tsx examples/web/server.ts

Star History

Star History Chart

License

MIT