- name
- open-agent-sdk-typescript
- description
- Build AI agents with in-process agent loops using Anthropic or OpenAI APIs, custom tools, MCP servers, and multi-turn conversations
- triggers
- ["create an AI agent with open-agent-sdk","set up agent with custom tools and MCP","build a conversational agent loop","use open-agent-sdk with OpenAI or Anthropic","implement agent skills and subagents","add lifecycle hooks to my agent","create streaming agent queries","integrate MCP servers with my agent"]
# Open Agent SDK (TypeScript)
> Skill by [ara.so](https://ara.so) — AI Agent Skills collection.
Open Agent SDK is a TypeScript library that runs full AI agent loops **in-process** without CLI dependencies or subprocesses. It supports both Anthropic and OpenAI-compatible APIs, provides 35+ built-in tools, MCP server integration, custom tool creation, skills system, subagents, and lifecycle hooks. Deploy anywhere: cloud, serverless, Docker, or CI/CD.
## Installation
```bash
npm install @codeany/open-agent-sdk
```
Set your API key as an environment variable:
```bash
export CODEANY_API_KEY=your-api-key-here
```
For OpenAI-compatible models:
```bash
export CODEANY_API_TYPE=openai-completions
export CODEANY_API_KEY=sk-your-key
export CODEANY_BASE_URL=https://api.openai.com/v1
export CODEANY_MODEL=gpt-4o
```
For third-party Anthropic-compatible providers:
```bash
export CODEANY_BASE_URL=https://openrouter.ai/api
export CODEANY_API_KEY=sk-or-your-key
export CODEANY_MODEL=anthropic/claude-sonnet-4
```
## Core Concepts
### API Types
The SDK supports two API types:
- **`anthropic-messages`**: Anthropic Claude models (default)
- **`openai-completions`**: OpenAI, DeepSeek, Qwen, Mistral, or any OpenAI-compatible API
API type is auto-detected from model name. Models containing `gpt-`, `o1`, `o3`, `deepseek`, `qwen`, or `mistral` automatically use `openai-completions`.
### Agent vs Query
- **`query()`**: One-shot streaming query, no session persistence
- **`createAgent()`**: Reusable agent with multi-turn conversation history
## Quick Start Examples
### One-Shot Streaming Query
```typescript
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);
}
}
}
if (message.type === "result") {
console.log(`Cost: $${message.total_cost_usd?.toFixed(4)}`);
console.log(`Turns: ${message.num_turns}`);
}
}
```
### Simple Blocking Prompt
```typescript
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}`);
console.log(`Tokens: ${result.usage.input_tokens + result.usage.output_tokens}`);
```
### OpenAI / GPT Models
```typescript
import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({
apiType: "openai-completions",
model: "gpt-4o",
apiKey: process.env.OPENAI_API_KEY,
baseURL: "https://api.openai.com/v1",
});
const result = await agent.prompt("Analyze the code structure of this project");
console.log(result.text);
```
### Multi-Turn Conversation
```typescript
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("Response 1:", r1.text);
const r2 = await agent.prompt("Read back the file you just created");
console.log("Response 2:", r2.text);
const r3 = await agent.prompt("Delete the file");
console.log("Response 3:", r3.text);
console.log(`Total messages in session: ${agent.getMessages().length}`);
// Clean up
await agent.close();
```
## Custom Tools
### Using Zod Schema (Recommended)
```typescript
import { z } from "zod";
import { query, tool, createSdkMcpServer } from "@codeany/open-agent-sdk";
const getWeather = tool(
"get_weather",
"Get the current weather for a city",
{
city: z.string().describe("City name"),
unit: z.enum(["celsius", "fahrenheit"]).optional().describe("Temperature unit"),
},
async ({ city, unit = "celsius" }) => {
// Simulate API call
const temp = unit === "celsius" ? 22 : 72;
return {
content: [
{
type: "text",
text: `Weather in ${city}: ${temp}°${unit === "celsius" ? "C" : "F"}, sunny`,
},
],
};
}
);
const calculator = tool(
"calculate",
"Perform mathematical calculations",
{
expression: z.string().describe("Mathematical expression to evaluate"),
},
async ({ expression }) => {
try {
const result = Function(`'use strict'; return (${expression})`)();
return {
content: [{ type: "text", text: `${expression} = ${result}` }],
};
} catch (error) {
return {
content: [{ type: "text", text: `Error: ${error.message}` }],
isError: true,
};
}
}
);
const server = createSdkMcpServer({
name: "custom-tools",
tools: [getWeather, calculator],
});
for await (const msg of query({
prompt: "What's the weather in Tokyo? Also calculate 2**16.",
options: { mcpServers: { "custom-tools": server } },
})) {
if (msg.type === "assistant") {
for (const block of msg.message.content) {
if ("text" in block) console.log(block.text);
}
}
}
```
### Low-Level Tool Definition
```typescript
import { createAgent, getAllBaseTools, defineTool } from "@codeany/open-agent-sdk";
const databaseQuery = defineTool({
name: "DatabaseQuery",
description: "Execute SQL queries against the database",
inputSchema: {
type: "object",
properties: {
query: {
type: "string",
description: "SQL query to execute",
},
readonly: {
type: "boolean",
description: "Whether this is a read-only query",
},
},
required: ["query"],
},
isReadOnly: false,
async call(input) {
// Validate read-only
if (!input.readonly && /^\s*(SELECT|SHOW|DESCRIBE)/i.test(input.query)) {
return "Error: Use readonly=true for SELECT queries";
}
// Execute query (simulated)
return JSON.stringify({
rows: [{ id: 1, name: "Example" }],
rowCount: 1,
});
},
});
const agent = createAgent({
tools: [...getAllBaseTools(), databaseQuery],
});
const result = await agent.prompt(
"Query the users table and show me all records"
);
console.log(result.text);
```
## Built-in Tools
The SDK includes 35+ built-in tools. Common ones include:
- **File operations**: `Read`, `Write`, `Edit`, `Delete`, `Move`, `Rename`
- **Search**: `Glob`, `Grep`, `Search`
- **Git**: `GitStatus`, `GitDiff`, `GitLog`, `GitCommit`, `GitCheckout`
- **Analysis**: `Lint`, `Symbols`, `CodeGraph`, `Dependencies`
- **Shell**: `Bash`, `BashSession`
- **Utility**: `Ask`, `Attempt`, `Skill`, `Agent` (subagents)
### Restricting Tools
```typescript
import { createAgent } from "@codeany/open-agent-sdk";
// Read-only agent
const readOnlyAgent = createAgent({
allowedTools: ["Read", "Glob", "Grep", "Search"],
permissionMode: "dontAsk",
});
// Agent without shell access
const noShellAgent = createAgent({
disallowedTools: ["Bash", "BashSession"],
});
// Minimal tool set
const minimalAgent = createAgent({
tools: [], // No tools at all
});
```
## Skills
Skills are reusable prompt templates. Five built-in skills: `simplify`, `commit`, `review`, `debug`, `test`.
### Using Built-in Skills
```typescript
import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent();
// The agent can invoke skills via the Skill tool
const result = await agent.prompt(
'Use the "review" skill to review src/index.ts'
);
console.log(result.text);
```
### Creating Custom Skills
```typescript
import { registerSkill, getAllSkills, createAgent } from "@codeany/open-agent-sdk";
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."}`,
},
];
},
});
registerSkill({
name: "optimize",
description: "Optimize code for performance",
userInvocable: true,
async getPrompt(args) {
return [
{
type: "text",
text: `Analyze and optimize the following for performance:\n${args}\n\nProvide specific improvements and benchmarks.`,
},
];
},
});
console.log(`${getAllSkills().length} skills registered`);
const agent = createAgent();
const result = await agent.prompt(
'Use the "optimize" skill on src/heavy-computation.ts'
);
console.log(result.text);
```
## MCP Server Integration
### External MCP Servers
```typescript
import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({
mcpServers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
},
postgres: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-postgres"],
env: {
DATABASE_URL: process.env.DATABASE_URL,
},
},
},
});
const result = await agent.prompt("List files in /tmp and query the database");
console.log(result.text);
await agent.close(); // Important: closes MCP connections
```
### In-Process MCP Servers
```typescript
import { z } from "zod";
import { createAgent, tool, createSdkMcpServer } from "@codeany/open-agent-sdk";
const httpGet = tool(
"http_get",
"Make HTTP GET requests",
{
url: z.string().url().describe("URL to fetch"),
headers: z.record(z.string()).optional().describe("HTTP headers"),
},
async ({ url, headers }) => {
const response = await fetch(url, { headers });
const text = await response.text();
return {
content: [
{
type: "text",
Auf GitHub ansehen