Give Your Agent a Computer — Nico Albanese, Vercel
Nico Albanese from Vercel demonstrates how to build a stateful, learning AI agent from scratch using AI SDK v6. The workshop covers the core components: a tool loop, provider-executed tools like web search, end-to-end type safety, and Vercel's new persistent named sandboxes, which give the agent a file system to persist state, memory, and even self-generated tools across sessions.
Building a Modern Agent with AI SDK v6
The latest versions of the Vercel AI SDK move towards a more object-oriented, reusable approach to building agents. The toolLoopAgent is a central piece of this, abstracting away the complexities of managing tool calls and state.
A basic agent can be defined in a few lines of code, separating the agent’s logic from the API endpoint that serves it.
// lib/agent.ts
import { toolLoop } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
export const agent = toolLoop({
model: createOpenAI()('gpt-4-turbo'),
});
The AI SDK v6 introduces the concept of a “global provider,” which defaults to the Vercel AI Gateway. This allows you to specify models using simple strings (e.g., 'openai:gpt-4-turbo') without instantiating a provider for every call, simplifying the setup.
The frontend is powered by the useChat hook, which manages message state and communication with the Next.js route handler. The handler itself becomes very lean, primarily using createAgentUIStreamResponse to stream the agent’s output back to the client.
Core Building Blocks for Advanced Agents
The workshop identifies three essential components for building capable agents in 2024:
- An Agent Runtime: A framework for managing the execution loop, context, and tools (e.g.,
toolLoopAgent). - Tools: Functions and capabilities the agent can call upon to interact with the outside world.
- A Computer: A sandboxed file system where the agent can persist state, execute code, and build upon its work across multiple sessions.
Adding Tools and End-to-End Type Safety
The AI SDK supports three categories of tools:
- Custom Tools: Arbitrary functions you define with a description, an input schema (using Zod), and an
executefunction. - Provider-Defined Tools: Tools that a model provider has fine-tuned their models to use effectively, such as Anthropic’s
bashtool. You define the execution logic, but the provider has optimized the model’s ability to call it correctly. - Provider-Executed Tools: Tools that exist entirely within the LLM provider’s infrastructure, like OpenAI’s
webSearch. You simply “opt-in” to allow the agent to use them, and the provider handles the execution and returns the result. This is a fast way to add capabilities like RAG.
A major challenge in building agent UIs is the lack of type information for tool calls, leading to poor developer experience and generic UIs. The AI SDK solves this with an end-to-end type system. By defining the agent’s tools in a central location, you can infer the exact shape of the UI messages.
// lib/agent.ts
import { inferAgentMessage } from 'ai';
import { agent } from './agent';
// Create a type-safe message specific to our agent's tools
export type AgentMessage = inferAgentMessage<typeof agent>;
This AgentMessage type can then be passed to the useChat hook. This provides type-safe access to tool calls and their arguments directly in your client-side components, allowing you to build rich, custom UI for each tool’s lifecycle (e.g., showing a “Searching the web…” state).
The Key Insight: Persistent Sandboxes
The most significant shift in agent capability comes from providing it with a persistent file system. Vercel’s internal research showed that when an agent could read and write files, its behavior fundamentally changed. It began to follow long-term plans, stay on track, and build on its own previous work without getting lost in an ever-expanding context window.
This workshop uses Vercel’s new persistent named sandboxes. The key features are:
- Persistence by Name: You reference a sandbox by a unique name (e.g., tied to a user ID).
- Managed Lifecycle: Vercel automatically handles spinning the sandbox up and down. After a period of inactivity, the sandbox is paused, and its file system is snapshotted. The next time it’s requested, a new instance is spun up with the exact same file state, making it feel continuously available.
- Simplified Code: This abstracts away the complex lifecycle management of creating, tracking, storing, and rehydrating sandbox states.
Integrating the Sandbox
The sandbox is integrated into the agent via two main AI SDK features:
callOptionSchema: This allows you to define a Zod schema for structured, type-safe inputs that can be passed to the agent at runtime. Here, it’s used to require a sandbox instance for every agent invocation.- Agent
context: Similar to React Context, this is a mechanism to provide arbitrary data, functions, or instances to all tools within the agent’s runtime. TheprepareCallfunction, which runs once at the start of an agent’s run, is used to take the sandbox instance from the call options and inject it into this context.
A custom bash tool can then access this sandbox from its context to execute commands, giving the agent full control over its environment.
Creating a Learning, Self-Extending Agent
With a persistent file system, you can implement more advanced behaviors.
Persistent Memory
Instead of relying on complex memory management systems, a simple and effective approach is to use a file.
- Instruct the Agent: The system prompt directs the agent to store important facts and user preferences in a
memories.mdfile. - Inject into Context: The
prepareCallfunction is updated to readmemories.mdfrom the sandbox at the start of each session. - Update the Prompt: The content of the memory file is injected directly into the system prompt, giving the agent immediate access to its accumulated knowledge.
Self-Generated Tools
The agent can be instructed to become more efficient over time. The system prompt can include a directive: “If you perform a repeatable task, write a Python script to automate it and save it. Describe the script in your memories.md file.”
The agent can then:
- Receive a request (e.g., “Get the weather in London”).
- Write a
weather.pyscript using thebashtool (echo "..." > weather.py). - Execute it (
python weather.py London). - Add a note to its
memories.mdfile: “I have a tool calledweather.pythat can fetch the weather.”
On subsequent requests, the agent will consult its memory, find the tool it created, and execute it directly, demonstrating a powerful loop of learning and self-improvement.
Advanced Topic: Context Window Management
In a Q&A session, a key topic was managing the context window. The speaker’s “hot take” is that with modern million-token context windows, aggressive summarization or “compaction” is often counterproductive. Every time you alter the message history, you invalidate the provider’s input cache, which can increase cost and latency.
A better approach for complex, long-running tasks is to use sub-agents. A main agent can delegate a specific task to a sub-agent that runs in a separate thread with its own context. The sub-agent completes its work and returns only a concise summary or result, keeping the main agent’s context window clean and efficient. The AI SDK’s prepareStep callback also provides a hook for developers to implement custom context management strategies, like a sliding window, before each step of an agent’s execution.