Loading...
Loading...
Build AI agents with in-process agent loops using Anthropic or OpenAI APIs, custom tools, MCP servers, and multi-turn conversations
npx skill4agent add aradotso/ai-agent-skills open-agent-sdk-typescriptSkill by ara.so — AI Agent Skills collection.
npm install @codeany/open-agent-sdkexport CODEANY_API_KEY=your-api-key-hereexport 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-4oexport CODEANY_BASE_URL=https://openrouter.ai/api
export CODEANY_API_KEY=sk-or-your-key
export CODEANY_MODEL=anthropic/claude-sonnet-4anthropic-messagesopenai-completionsgpt-o1o3deepseekqwenmistralopenai-completionsquery()createAgent()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}`);
}
}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}`);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);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();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);
}
}
}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);ReadWriteEditDeleteMoveRenameGlobGrepSearchGitStatusGitDiffGitLogGitCommitGitCheckoutLintSymbolsCodeGraphDependenciesBashBashSessionAskAttemptSkillAgentimport { 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
});simplifycommitreviewdebugtestimport { 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);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);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 connectionsimport { 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",
text: `Status: ${response.status}\n\n${text}`,
},
],
};
}
);
const mcpServer = createSdkMcpServer({
name: "http-tools",
tools: [httpGet],
});
const agent = createAgent({
mcpServers: {
http: mcpServer,
},
});
const result = await agent.prompt("Fetch https://api.github.com/repos/codeany-ai/open-agent-sdk-typescript");
console.log(result.text);import { query } from "@codeany/open-agent-sdk";
for await (const msg of query({
prompt: "Use the security-reviewer to audit src/auth.ts for vulnerabilities",
options: {
agents: {
"security-reviewer": {
description: "Expert security code reviewer",
prompt: "You are a security expert. Analyze code for vulnerabilities, focusing on authentication, authorization, input validation, and data exposure.",
tools: ["Read", "Glob", "Grep", "Symbols"],
},
"performance-optimizer": {
description: "Performance optimization specialist",
prompt: "You optimize code for speed and efficiency. Identify bottlenecks, suggest algorithmic improvements, and recommend caching strategies.",
tools: ["Read", "Symbols", "Dependencies"],
},
},
},
})) {
if (msg.type === "assistant") {
for (const block of msg.message.content) {
if ("text" in block) console.log(block.text);
}
}
}import { createAgent, createHookRegistry } from "@codeany/open-agent-sdk";
const hooks = createHookRegistry({
PreToolUse: [
{
handler: async (input) => {
console.log(`[HOOK] About to use tool: ${input.toolName}`);
console.log(`[HOOK] Arguments:`, input.toolInput);
// Block dangerous operations
if (input.toolName === "Bash" && input.toolInput.command?.includes("rm -rf")) {
console.warn("[HOOK] Blocking dangerous command");
return { block: true };
}
},
},
],
PostToolUse: [
{
handler: async (input) => {
console.log(`[HOOK] Tool ${input.toolName} completed`);
console.log(`[HOOK] Result length:`, input.toolResult.length);
},
},
],
PostToolUseFailure: [
{
handler: async (input) => {
console.error(`[HOOK] Tool ${input.toolName} failed:`, input.error);
},
},
],
SessionStart: [
{
handler: async () => {
console.log("[HOOK] Session started");
},
},
],
SessionEnd: [
{
handler: async () => {
console.log("[HOOK] Session ended");
},
},
],
FileChanged: [
{
handler: async (input) => {
console.log(`[HOOK] File changed: ${input.path}`);
},
},
],
});
const agent = createAgent({
hooks,
model: "claude-sonnet-4-6",
});
const result = await agent.prompt("List files and create a new test file");
console.log(result.text);PreToolUsePostToolUsePostToolUseFailureSessionStartSessionEndStopSubagentStartSubagentStopUserPromptSubmitPermissionRequestPermissionDeniedTaskCreatedTaskCompletedConfigChangeCwdChangedFileChangedNotificationPreCompactPostCompactTeammateIdleimport { createAgent } from "@codeany/open-agent-sdk";
// Bypass all permissions (default)
const autoAgent = createAgent({
permissionMode: "bypassPermissions",
});
// Never ask, deny if permission needed
const denyAgent = createAgent({
permissionMode: "dontAsk",
});
// Ask for permission (requires custom handler)
const askAgent = createAgent({
permissionMode: "ask",
// Implement permission handler via hooks
});
// Change mode mid-session
autoAgent.setPermissionMode("dontAsk");import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({
// API configuration
apiType: "anthropic-messages", // or "openai-completions"
model: "claude-sonnet-4-6",
apiKey: process.env.CODEANY_API_KEY,
baseURL: "https://api.anthropic.com",
// Session
sessionId: "my-session-id",
maxTurns: 10,
// Working directory
cwd: process.cwd(),
// System prompt
systemPrompt: "You are a helpful coding assistant",
appendSystemPrompt: "\n\nAlways explain your reasoning.",
// Tools
tools: [], // Custom tool list
allowedTools: ["Read", "Write", "Glob"],
disallowedTools: ["Bash"],
// Permissions
permissionMode: "bypassPermissions",
// MCP servers
mcpServers: {},
// Subagents
agents: {},
// Hooks
hooks: createHookRegistry({}),
// Model parameters
temperature: 0.7,
maxTokens: 4096,
});import { query } from "@codeany/open-agent-sdk";
for await (const msg of query({
prompt: "Your prompt here",
options: {
model: "gpt-4o",
apiType: "openai-completions",
apiKey: process.env.OPENAI_API_KEY,
cwd: "/path/to/project",
allowedTools: ["Read", "Glob"],
permissionMode: "bypassPermissions",
maxTurns: 5,
temperature: 0.5,
},
})) {
// Handle messages
}import { createAgent, listSessions, forkSession } from "@codeany/open-agent-sdk";
// Create agent with persistent session
const agent = createAgent({
sessionId: "my-project-session",
});
await agent.prompt("Analyze the codebase structure");
await agent.prompt("Now suggest improvements");
// List all sessions
const sessions = await listSessions();
console.log("Saved sessions:", sessions);
// Fork a session for experimentation
const forkedId = await forkSession("my-project-session");
const forkedAgent = createAgent({ sessionId: forkedId });
await forkedAgent.prompt("Try refactoring with a different approach");import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent();
// Start a long-running query
const queryPromise = agent.prompt("Analyze all files in the project");
// Interrupt after 5 seconds
setTimeout(() => {
agent.interrupt();
console.log("Query interrupted");
}, 5000);
try {
const result = await queryPromise;
console.log(result.text);
} catch (error) {
console.log("Query was interrupted");
}import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent({ model: "claude-sonnet-4-6" });
await agent.prompt("Quick analysis");
// Switch to more powerful model for complex task
agent.setModel("claude-opus-4");
await agent.prompt("Perform deep architectural analysis");
// Switch back to cheaper model
agent.setModel("claude-sonnet-4-6");
await agent.prompt("Summarize findings");import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent();
for await (const message of agent.query("Analyze this codebase")) {
switch (message.type) {
case "assistant":
for (const block of message.message.content) {
if ("text" in block) {
process.stdout.write(block.text);
} else if ("tool_use" in block) {
console.log(`\n[Tool: ${block.tool_use.name}]`);
}
}
break;
case "tool_use":
console.log(`\nExecuting: ${message.toolName}`);
break;
case "tool_result":
console.log(`Tool result length: ${message.result.length} chars`);
break;
case "result":
console.log(`\n\nCompleted in ${message.num_turns} turns`);
console.log(`Cost: $${message.total_cost_usd?.toFixed(4)}`);
console.log(`Tokens: ${message.usage.input_tokens + message.usage.output_tokens}`);
break;
case "error":
console.error(`Error: ${message.error}`);
break;
}
}import { createAgent } from "@codeany/open-agent-sdk";
const agent = createAgent();
try {
const result = await agent.prompt("Your prompt here");
console.log(result.text);
} catch (error) {
if (error.message.includes("rate limit")) {
console.error("Rate limit exceeded, retry later");
} else if (error.message.includes("context length")) {
console.error("Prompt too long, try simplifying");
} else {
console.error("Agent error:", error.message);
}
} finally {
await agent.close();
}Error: API key not foundCODEANY_API_KEYapiKeyconst agent = createAgent({
apiKey: process.env.CODEANY_API_KEY,
});Error: Model not found: gpt-4oapiTypeconst agent = createAgent({
apiType: "openai-completions",
model: "gpt-4o",
baseURL: "https://api.openai.com/v1",
});Error: Failed to start MCP servernpm install -g @modelcontextprotocol/server-filesystemconst agent = createAgent({
mcpServers: {
filesystem: {
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
},
},
});Permission denied: Cannot execute Bashconst agent = createAgent({
permissionMode: "bypassPermissions",
allowedTools: ["Bash", "Read", "Write"],
});.codeany/sessions/async function queryWithRetry(agent, prompt, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await agent.prompt(prompt);
} catch (error) {
if (error.message.includes("rate limit") && i < maxRetries - 1) {
const delay = Math.pow(2, i) * 1000;
console.log(`Rate limited, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}npx tsx examples/web/server.tshttp://localhost:8081import { z } from "zod";
import { createAgent, tool, createSdkMcpServer, createHookRegistry } from "@codeany/open-agent-sdk";
// Custom tool for static analysis
const analyzeComplexity = tool(
"analyze_complexity",
"Analyze code complexity metrics",
{
filePath: z.string().describe("Path to file to analyze"),
},
async ({ filePath }) => {
// Simplified complexity analysis
return {
content: [
{
type: "text",
text: JSON.stringify({
cyclomaticComplexity: 12,
cognitiveComplexity: 8,
linesOfCode: 245,
}),
},
],
};
}
);
const mcpServer = createSdkMcpServer({
name: "code-analysis",
tools: [analyzeComplexity],
});
// Hook to log all tool usage
const hooks = createHookRegistry({
PreToolUse: [
{
handler: async (input) => {
console.log(`[Review] Using tool: ${input.toolName}`);
},
},
],
PostToolUse: [
{
handler: async (input) => {
console.log(`[Review] Tool ${input.toolName} completed`);
},
},
],
});
const agent = createAgent({
model: "claude-sonnet-4-6",
systemPrompt: "You are an expert code reviewer. Focus on code quality, security, performance, and maintainability.",
allowedTools: ["Read", "Glob", "Grep", "Symbols", "analyze_complexity"],
mcpServers: { analysis: mcpServer },
hooks,
permissionMode: "bypassPermissions",
});
async function reviewCode(pattern) {
console.log(`\n=== Starting code review for: ${pattern} ===\n`);
const result = await agent.prompt(`
Review all files matching ${pattern}. For each file:
1. Analyze code quality and structure
2. Check for security vulnerabilities
3. Assess performance implications
4. Suggest improvements
Use analyze_complexity to get metrics.
Provide a summary with prioritized recommendations.
`);
console.log("\n=== Review Results ===\n");
console.log(result.text);
console.log(`\n=== Stats: ${result.num_turns} turns, ${result.usage.input_tokens + result.usage.output_tokens} tokens ===`);
}
reviewCode("src/**/*.ts").then(() => agent.close());