@21st-sdk/agent
v0.0.16
Published
Define AI agents and tools with full type inference for 21st Agents
Readme
@21st-sdk/agent
Define AI agents with full type inference. The config layer for 21st Agents.
Install
npm install @21st-sdk/agent zodQuick Start
Create src/agent.ts:
import { agent, tool } from "@21st-sdk/agent"
import { z } from "zod"
export default agent({
model: "claude-sonnet-4-6",
systemPrompt: "You are a helpful coding assistant.",
tools: {
greet: tool({
description: "Greet a user by name",
inputSchema: z.object({ name: z.string() }),
execute: async ({ name }) => ({
content: [{ type: "text", text: `Hello, ${name}!` }],
}),
}),
},
})Then deploy with the 21st SDK CLI:
npx @21st-sdk/cli login
npx @21st-sdk/cli deployAPI
agent(config)
Creates an agent configuration. Returns the config with a _type: "agent" tag for the runtime.
export default agent({
// Model to use (default: "claude-sonnet-4-6")
model: "claude-sonnet-4-6",
// For "claude-code" runtime, string prompts are appended
// to Claude Code's preset system prompt by default.
systemPrompt: "You are a PR reviewer...",
// Custom tools the agent can use
tools: {
lint: tool({ ... }),
test: tool({ ... }),
},
// Runtime: "claude-code" (default) or "codex"
runtime: "claude-code",
// Permission mode: "default", "acceptEdits", or "bypassPermissions"
permissionMode: "default",
// Max turns before stopping (default: 50)
maxTurns: 50,
// Max budget in USD
maxBudgetUsd: 5,
// Lifecycle hooks
onStart: async () => { ... },
onToolCall: async ({ toolName, input }) => { ... },
onToolResult: async ({ toolName, input, output }) => { ... },
onStepFinish: async ({ step }) => { ... },
onFinish: async ({ result }) => { ... },
onError: async ({ error }) => { ... },
})tool(definition)
Creates a tool definition with Zod schema validation.
import { tool } from "@21st-sdk/agent"
import { z } from "zod"
const myTool = tool({
description: "What this tool does",
inputSchema: z.object({
path: z.string(),
verbose: z.boolean().optional(),
}),
execute: async (args) => {
// args is fully typed from the schema
return {
content: [{ type: "text", text: "result" }],
}
},
})Hooks
onToolCall
Runs before a tool executes. Return false to block it.
onToolCall: async ({ toolName, input }) => {
if (toolName === "Bash" && input.command?.includes("rm -rf")) {
return false // blocked
}
}onFinish
Runs when the agent completes successfully.
onFinish: async ({ result }) => {
await fetch("https://my-api.com/webhook", {
method: "POST",
body: JSON.stringify({ done: true }),
})
}How It Works
agent() and tool() are identity functions — they return exactly what you pass in, with type inference added. The actual execution happens in the 21st Agents runtime (E2B sandbox) using the Claude Agent SDK.
Your code runs in a secure cloud sandbox with full access to Node.js, git, and system tools.
For runtime: "claude-code", omitting systemPrompt uses Claude Code's default preset system prompt. If you pass a string, it is appended to that preset automatically. You can also pass the preset object directly:
systemPrompt: {
type: "preset",
preset: "claude_code",
append: "Your extra instructions here",
}License
MIT
