AI SDK file tools in Next.js
Build AI SDK tools that create and read a persistent note on mountable.io from a Next.js server.
Your Next.js process can stop between an agent writing a note and another run needing it. mountable.io is a persistent filesystem for AI agents. Store the note there, then read the same file after restarting your app.
The community starter
is maintained by mountable.io, independently of Vercel. It defines two AI
SDK tools backed by the TypeScript mountable-sdk. Its web buttons call the
tools directly. Its command-line check runs generateText with a scripted
test provider that requests a tool call. Neither makes a paid model request.
Setup
Use Node 24+ and an existing mountable.io account with a saved payment method, a filesystem, and an API key with access to it. The example creates no account, filesystem or credits. Storage and file operations follow the usage prices.
git clone https://github.com/writeitai/mountable.git
cd mountable/examples/vercel-ai-workspace
npm ci
cp .env.example .env.local
openssl rand -hex 32In .env.local, set MOUNTABLE_API_KEY, MOUNTABLE_FILESYSTEM_ID,
MOUNTABLE_NOTE_PATH and DEMO_ACCESS_TOKEN. Use a new path like
notes/brief.md. Set the operator token to the random string you generated.
Keep this file private. The API key stays on the server.
npm run devOpen http://127.0.0.1:3000 and enter the operator token, never your API key.
The app holds that token in browser memory. Every storage call requires it.
The local server binds to loopback.
Create a note and read it after restarting
Enter a short note and select Create note once. The tool stores the file
and returns stored. Select Read stored note to read its contents through
a separate read-only filesystem handle.
Stop and restart Next.js. Open the page, enter the operator token again and select Read stored note. The note comes from the filesystem.
The backend selects one filesystem and note path. The model-facing create tool accepts only text; the read tool accepts no arguments. Do not take a filesystem ID or a path from the model. In a multi-user app, authenticate the user and look up their filesystem in trusted server code.
Use the definitions with your model
The starter's workspaceTools function returns these AI SDK tool definitions:
const tools = workspaceTools(
client.filesystem(filesystemId),
client.filesystem(filesystemId, "ro"),
"notes/brief.md",
);Pass them to generateText with your own configured model:
const result = await generateText({
model: yourConfiguredModel,
tools,
prompt: "Read the stored note using read_note.",
maxRetries: 0,
});Your model provider bills separately. A filesystem spending cap does not limit that bill. Keep the tools and API key on your trusted server.
Keep writes bounded
A note is UTF-8 text up to 16 KiB. Writes use If-None-Match: *, so an
existing note stays untouched. After a timeout, read the path before
writing again. The example does not delete notes for you.
A 402 stops that user's billable storage work. The app does not retry
a refused write. Keep each user's spending cap and quota under backend
control; see limits per end user.
The web app is a single-operator starter. Before serving several users, replace its shared operator check with your authentication and server-side user mapping. Keep paid file operations behind that boundary.
Check the AI SDK pipeline
Export the mountable.io variables in your private shell environment. Use a
new MOUNTABLE_NOTE_PATH for the write. These commands do not load
.env.local.
npm run check:live -- create
npm run check:live -- readThey start separate processes. generateText uses the scripted AI SDK test
provider to request create_note or read_note and checks the tool result.
The read command expects the default note text unless you set NOTE_TEXT.
Run the offline checks with npm test. They cover rejected paths, the UTF-8
byte limit, authentication, create-only writes and a billing refusal.
Sources: AI SDK tools, AI SDK testing, mountable.io TypeScript SDK.