Vercel Logo

Load Files and Add Instructions

In this project, you have 3 dummy call transcripts in the lib/calls directory that you want to load as context to the sandbox before asking the agent a question. You also need clear instructions so the agent knows to use the bash tool to explore the files and answer questions.

Outcome

You have a complete lib/agent.ts that loads call files into the sandbox and instructs the agent to use bash to explore them.

Fast Track

  1. Write a loadSandboxFiles function that reads lib/calls/ and writes each file into the sandbox
  2. Call loadSandboxFiles before creating the agent
  3. Add an INSTRUCTIONS string telling the agent to use bashTool to explore files and answer questions

Hands-on Exercise 2.2

Complete lib/agent.ts by adding file loading and instructions.

Requirements:

  1. Import path and fs/promises for filesystem operations
  2. Write a loadSandboxFiles function that reads every file from lib/calls/ and writes them into the sandbox at calls/<filename>
  3. Call loadSandboxFiles(sandbox) before the agent is created
  4. Add an INSTRUCTIONS constant that tells the agent its role and how to use the bash tool
  5. Pass INSTRUCTIONS to the agent's instructions property

Implementation hints:

  • Use process.cwd() to build the path to lib/calls/
  • fs.readdir returns filenames, fs.readFile returns a buffer
  • sandbox.writeFiles takes an array of { path, content } objects
  • The loadSandboxFiles function can be defined after the agent export (hoisting), but it must be called before the export

Writing files to the sandbox

Create a function called loadSandboxFiles in agent.ts to load the call files into the sandbox:

lib/agent.ts
import path from 'path';
import fs from 'fs/promises';
 
async function loadSandboxFiles(sandbox: Sandbox) {
  const callsDir = path.join(process.cwd(), 'lib', 'calls');
  const callFiles = await fs.readdir(callsDir);
 
  for (const file of callFiles) {
    const filePath = path.join(callsDir, file);
    const buffer = await fs.readFile(filePath);
    await sandbox.writeFiles([{ path: `calls/${file}`, content: buffer }]);
  }
}

What this function does is build the full path of the calls folder (in the same lib directory as agent.ts). Then it reads all filenames in that folder, loads each file as a buffer, and writes them to the sandbox's file system.

Be sure to call the function before the agent is created:

lib/agent.ts
await loadSandboxFiles(sandbox);

Agent instructions

Now that you have everything wired up, write clear instructions for the agent. You want it to use the bash tool to generate and execute commands to explore all the call transcripts to answer the user's questions:

lib/agent.ts
const INSTRUCTIONS = `
You are a helpful assistant that answers questions about customer calls. Use bashTool to explore the files and find relevant information pertaining to the user's query. Using the information you find, craft a response for the user and output it as text.
`;

Add the INSTRUCTIONS to the agent:

lib/agent.ts
export const agent = new ToolLoopAgent({
  instructions: INSTRUCTIONS,
  // ...
});

Try It

  1. Restart the dev server and open http://localhost:3000.

  2. Ask: "what files are available?"

    The agent should call bashTool with ls calls/ and report the three transcript files:

    [bashTool] $ ls calls/
    1.md  2.md  3.md
    
  3. Ask: "summarize the first call"

    The agent should cat calls/1.md (or similar) and produce a summary of the call transcript: participants, topics discussed, outcomes.

  4. Ask: "did anyone mention pricing?"

    The agent should grep across the files for pricing-related content and synthesize an answer.

The agent works!

If the agent lists files, reads transcripts, and answers questions, you've built a working filesystem agent. The next lesson covers testing strategies and extension ideas.

Commit

git add lib/agent.ts
git commit -m "feat(agent): load call files and add instructions"

Done-When

  • loadSandboxFiles reads all files from lib/calls/ and writes them into the sandbox
  • INSTRUCTIONS tells the agent its role and how to use bashTool
  • The agent can list files in the sandbox (ls calls/)
  • The agent can read and summarize call transcripts
  • The agent can search across files to answer questions

Solution

Here's the complete lib/agent.ts file with all the pieces together:

lib/agent.ts
import { ToolLoopAgent } from 'ai';
import { createBashTool } from './tools';
import { Sandbox } from '@vercel/sandbox';
import path from 'path';
import fs from 'fs/promises';
 
const INSTRUCTIONS = `
You are a helpful assistant that answers questions about customer calls. Use bashTool to explore the files and find relevant information pertaining to the user's query. Using the information you find, craft a response for the user and output it as text.
`;
 
const sandbox = await Sandbox.create();
 
const MODEL = 'anthropic/claude-opus-4.6';
 
await loadSandboxFiles(sandbox);
 
export const agent = new ToolLoopAgent({
  model: MODEL,
  instructions: INSTRUCTIONS,
  tools: {
    bashTool: createBashTool(sandbox)
  }
});
 
async function loadSandboxFiles(sandbox: Sandbox) {
  const callsDir = path.join(process.cwd(), 'lib', 'calls');
  const callFiles = await fs.readdir(callsDir);
 
  for (const file of callFiles) {
    const filePath = path.join(callsDir, file);
    const buffer = await fs.readFile(filePath);
    await sandbox.writeFiles([{ path: `calls/${file}`, content: buffer }]);
  }
}

And the agent is complete! There is already a chat input and API route created to kick off the agent and stream back the results.