Guides

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:

src/agent.ts
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:

src/agent.ts
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:

src/chat.ts
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:

src/agent.ts
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:

src/agent.ts
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 with rm
  • Write — Requires approval on every call

When approval is needed, the workflow suspends until resolved. Add a backend helper to resolve approvals:

src/chat.ts
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

  1. Push your code to GitHub.
  2. Import the project in Vercel.
  3. Add environment variables:
    • ANTHROPIC_API_KEY (or OPENAI_API_KEY for OpenAI models)
  4. Deploy.

Storage defaults to Vercel managed storage in production (when VERCEL_OIDC_TOKEN is set). The sandbox uses Vercel Sandbox.

Next Steps