Build Your First Agent
End-to-end guide that extends the quickstart with sandbox, custom tools, context, approvals, and deployment.
This guide picks up where the Quickstart left off. Complete the quickstart first — you should have an agent file and working chat helpers.
This guide adds:
- Sandbox configuration
- Per-request context for secrets
- A custom tool
- Approval gating
- Deployment
1. Add a Sandbox
Update your agent to run tools in a Vercel Sandbox:
import { agent } from "experimental-agent";
import { vercelSandbox } from "experimental-agent/sandbox";
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
system: "You are a helpful coding assistant. Be concise and accurate.",
sandbox: vercelSandbox(),
});In development, the sandbox runs on the host filesystem. In production, it runs inside a Vercel Sandbox.
You can also configure one-time setup for the sandbox (installing dependencies, cloning repos). See Sandbox Setup & Snapshots.
2. Add Context for Per-Request Secrets
Context is transient per-request data passed to tools. It is not persisted. Use it for auth tokens or request-scoped values.
Add contextSchema to your agent:
import { agent } from "experimental-agent";
import { vercelSandbox } from "experimental-agent/sandbox";
import { z } from "zod";
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
system: "You are a helpful coding assistant.",
sandbox: vercelSandbox(),
contextSchema: z.object({
authToken: z.string().optional(),
tenantId: z.string().optional(),
}),
});Pass context when sending a message:
await session.send(message, {
context: {
authToken,
tenantId,
},
});Custom tools receive context via ToolContext.
3. Add a Custom Tool
Define a tool using tool() from the ai package:
import { agent } from "experimental-agent";
import { tool } from "ai";
import { z } from "zod";
const GetGreeting = tool({
description: "Returns a greeting with the given name",
parameters: z.object({
name: z.string().describe("The name to greet"),
}),
execute: async ({ name }) => {
return { greeting: `Hello, ${name}!` };
},
});
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
system: "You are a helpful assistant. Use the GetGreeting tool when asked to greet someone.",
sandbox: vercelSandbox(),
tools: {
GetGreeting,
},
});The tool is now available alongside the 8 built-in tools. See Build Your First Tool for a deeper guide covering ToolContext, sandbox access, and typed output schemas.
4. Configure Approvals
Gate tools behind human approval with needsApproval. Map tool names to true, false, or a function:
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
system: "You are a helpful assistant.",
sandbox: vercelSandbox(),
tools: { GetGreeting },
needsApproval: {
Bash: (input) => input.command.startsWith("rm"),
Write: true,
},
});Bash— Requires approval when the command starts withrmWrite— Requires approval on every call
When approval is needed, the workflow suspends until resolved. Add a backend helper to resolve approvals:
import { myAgent } from "@/agent";
export async function resolveApproval({
chatId,
approvalId,
approved,
reason,
}: {
chatId: string;
approvalId: string;
approved: boolean;
reason?: string;
}) {
const session = myAgent.session(chatId);
await session.send({
type: "approval",
approval: { approvalId, approved, reason },
});
return { success: true };
}See Approvals for frontend integration and tool invocation states.
5. Test It
Send a message that triggers a built-in tool:
curl http://localhost:3000/api/chat/my-first-session \
-H "Content-Type: application/json" \
-d '{"message": "What files are in the current directory?"}'Send a message that triggers the custom tool:
curl http://localhost:3000/api/chat/my-first-session \
-H "Content-Type: application/json" \
-d '{"message": "Greet Alice"}'6. Deploy to Vercel
- Push your code to GitHub.
- Import the project in Vercel.
- Add environment variables:
ANTHROPIC_API_KEY(orOPENAI_API_KEYfor OpenAI models)
- Deploy.
Storage defaults to Vercel managed storage in production (when VERCEL_OIDC_TOKEN is set). The sandbox uses Vercel Sandbox.
Next Steps
- Build Your First Tool — Custom tools with ToolContext, sandbox access, and typed output
- Frontend Integration — React UI with
useChat - API Reference — Full
agent()documentation
Streaming
Real-time streaming with the AI SDK's UIMessageStream protocol. Reconnect on disconnect, handle status updates, and integrate with useChat.
Build Your First Tool
Step-by-step guide to creating a custom tool with typed input and output. Use tool() from the AI SDK, wire it into your agent, and access ToolContext.