From aradotso-trending-skills-37
Runs Claude-powered agent loops in-process without CLI dependencies. Supports streaming queries, multi-turn agents, custom Zod-validated tools, and in-process MCP servers.
How this skill is triggered — by the user, by Claude, or both
Slash command
/aradotso-trending-skills-37:open-agent-sdk-typescriptThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```markdown
---
name: open-agent-sdk-typescript
description: TypeScript SDK for running Claude-powered agent loops in-process without CLI dependencies
triggers:
- use open agent sdk
- run agent loop in typescript
- claude agent without cli
- open-agent-sdk setup
- create ai agent typescript
- agent sdk streaming query
- mcp server integration typescript
- subagent definition sdk
---
# Open Agent SDK (TypeScript)
> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.
Open Agent SDK runs the full agentic loop **in-process** — no subprocess, no CLI wrapper. It's a drop-in open-source alternative to `claude-agent-sdk` that works in cloud, serverless, Docker, and CI/CD environments.
## Installation
```bash
npm install @codeany/open-agent-sdk
Required environment variable:
export CODEANY_API_KEY=your-api-key
Optional — use third-party providers (e.g. OpenRouter):
export CODEANY_BASE_URL=https://openrouter.ai/api
export CODEANY_API_KEY=sk-or-...
export CODEANY_MODEL=anthropic/claude-sonnet-4
query() — one-shot streaming generator; yields SDKMessage objectscreateAgent() — reusable agent with session persistence and multi-turn supporttool() / defineTool() — register custom tools (Zod or raw JSON schema)createSdkMcpServer() — bundle tools as an in-process MCP servergetAllBaseTools() — returns all 34 built-in file/shell toolsimport { 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)}`);
}
}
createAgentimport { 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}`);
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}`);
await agent.close(); // persists session, closes MCP connections
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 and London?",
options: { mcpServers: { weather: server } },
})) {
if (msg.type === "result") console.log(`Done: $${msg.total_cost_usd?.toFixed(4)}`);
}
defineToolimport { 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);
import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({
mcpServers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
},
github: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-github"],
env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN! },
},
},
});
const result = await agent.prompt("List files in /tmp");
console.log(result.text);
await agent.close();
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 === "assistant") {
for (const block of msg.message.content) {
if ("text" in block) process.stdout.write(block.text);
}
}
}
| Mode | Behavior |
|---|---|
bypassPermissions | All tools allowed without prompting (default) |
acceptEdits | Auto-accept file edits, prompt for others |
dontAsk | Silently skip disallowed tools |
default | Prompt user for each sensitive operation |
plan | Plan only, no writes |
// Read-only analysis agent
for await (const msg of query({
prompt: "Review src/ for security issues.",
options: {
allowedTools: ["Read", "Glob", "Grep"],
permissionMode: "dontAsk",
},
})) { /* ... */ }
// Custom permission callback
const agent = createAgent({
canUseTool: async (tool, input) => {
if (tool.name === "Write") return { granted: false, reason: "Read-only mode" };
return { granted: true };
},
});
import {
createAgent,
listSessions,
getSessionMessages,
forkSession,
} from "@codeany/open-agent-sdk";
// Resume a previous session
const agent = createAgent({ resume: "session-id-here" });
// Continue most recent session
const agent2 = createAgent({ continue: true });
// List all persisted sessions
const sessions = await listSessions();
// Retrieve messages from a session
const messages = await getSessionMessages("session-id");
// Fork a session for branching experiments
const forkedId = await forkSession("session-id");
// Disable persistence
const ephemeral = createAgent({ persistSession: false });
import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({
outputFormat: {
type: "json_schema",
schema: {
type: "object",
properties: {
summary: { type: "string" },
issues: { type: "array", items: { type: "string" } },
severity: { type: "string", enum: ["low", "medium", "high"] },
},
required: ["summary", "issues", "severity"],
},
},
});
const result = await agent.prompt("Review src/auth.ts for security issues");
const parsed = JSON.parse(result.text);
console.log(parsed.severity, parsed.issues);
import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({
hooks: {
preToolCall: [
{
matcher: { toolName: "Write" },
callback: async (tool, input) => {
console.log(`Writing to: ${input.path}`);
},
},
],
postToolCall: [
{
matcher: { toolName: "*" },
callback: async (tool, input, output) => {
console.log(`Tool ${tool.name} completed`);
},
},
],
},
});
const agent = createAgent({ maxTurns: 10, model: "claude-sonnet-4-6" });
// Streaming
for await (const msg of agent.query("Explain this codebase")) { /* ... */ }
// Blocking
const result = await agent.prompt("Write tests for utils.ts");
// Session control
agent.getMessages(); // full conversation history
agent.clear(); // reset session
agent.interrupt(); // abort current query
agent.setModel("claude-opus-4");
agent.setPermissionMode("dontAsk");
await agent.close(); // persist + cleanup
createAgent({
model: "claude-sonnet-4-6", // LLM model
apiKey: process.env.CODEANY_API_KEY, // or set env var
baseURL: process.env.CODEANY_BASE_URL,
cwd: "/path/to/project", // working directory
systemPrompt: "You are a...", // override system prompt
appendSystemPrompt: "Always...", // append to default
maxTurns: 10,
maxBudgetUsd: 0.50, // spending cap
thinking: { type: "adaptive" }, // extended thinking
effort: "high", // low | medium | high | max
env: { MY_VAR: "value" }, // env vars for tools
abortController: new AbortController(),
});
npx tsx examples/web/server.ts
# Open http://localhost:8081
// Message types yielded by query() and agent.query()
type SDKMessage =
| { type: "assistant"; message: { content: ContentBlock[] } }
| { type: "user"; message: { content: ContentBlock[] } }
| { type: "result"; total_cost_usd?: number; usage: Usage }
| { type: "system"; subtype: string; [key: string]: unknown };
// Check for text content
if (message.type === "assistant") {
for (const block of message.message.content) {
if ("text" in block) console.log(block.text);
if (block.type === "tool_use") console.log(`Using: ${block.name}`);
}
}
Error: CODEANY_API_KEY is not set
→ Export the env var: export CODEANY_API_KEY=your-key
Agent runs too many turns / hits limit
→ Increase maxTurns or check if the task is resolvable with given allowedTools
MCP server not connecting
→ Ensure the MCP server binary is installed (npx -y @modelcontextprotocol/server-*), call await agent.close() to clean up
Tools not available
→ By default all 34 built-in tools are available; if you pass tools: [...] it replaces them. Use [...getAllBaseTools(), myTool] to extend
Session not persisting
→ Confirm persistSession: true (default) and that agent.close() is awaited
Custom base URL with OpenRouter
→ Set CODEANY_BASE_URL=https://openrouter.ai/api and CODEANY_MODEL=anthropic/claude-sonnet-4 alongside your OpenRouter API key
npx claudepluginhub aradotso/trending-skillsProvides in-process AI agent framework for TypeScript/Node.js, allowing Claude agent to run without CLI subprocess for serverless and cloud environments.
Builds programmatic AI agents using the Claude Agent SDK (Python/TypeScript) with tools for file reading, code editing, shell commands, and web search. Useful when automating tasks or integrating Claude into workflows.
Implements Anthropic Claude Agent SDK for autonomous agents, subagents, tool orchestration, MCP servers, and multi-step workflows. Useful for session management, permissions, and errors like CLI not found or context exceeded.