Package Exports
- ctx-zip
Readme
ctx-zip
Keep your AI agent context small and cheap by managing tool bloat and large outputs. ctx-zip provides two complementary techniques: Tool Discovery (transform MCP servers and tools into explorable code) and Output Compaction (persist large results to storage with smart retrieval).
Works with the AI SDK for agents and loop control. See: AI SDK – Loop Control: Context Management.
Installation
npm i ctx-zip
# or
pnpm add ctx-zipWhat It Does
ctx-zip tackles two major context problems:
1. Tool Discovery & Code Generation
Transforms MCP servers and AI SDK tools into inspectable TypeScript code in a sandbox. Instead of loading hundreds of tool schemas upfront, agents explore tools on-demand using filesystem operations.
The Problem:
Context Rot
- Tool schemas consume thousands of tokens before your prompt
- Every tool output is pulled into the model context
- Every tool definition passes through model context
- Agents can't inspect implementations to understand behavior
The Solution:
- Tools are transformed to importable code that live in the sandbox filesystem (not in context)
- Progressive Exploration: Agents explore the file system on-demand with
sandbox_ls,sandbox_cat,sandbox_grep - Agents write and execute code that combines multiple tools
- Result: Higher reliability, fast and ~80%+ token reduction for multi-tool workflows
2. Output Compaction with Smart Retrieval
Automatically persists large tool outputs to the sandbox filesystem and replaces them with concise references. Agents can retrieve content on-demand using the same sandbox exploration tools.
The Problem:
Context Rot
- Large tool outputs (search results, file contents, API responses) bloat context
- Conversation history accumulates thousands of unused tokens
- Context windows exhaust, costs increase, performance degrades
The Solution:
- Tool outputs are automatically written to the sandbox filesystem
- Replaced with short references in conversation
- Agents retrieve data on-demand with sandbox exploration tools (
sandbox_ls,sandbox_cat,sandbox_grep,sandbox_find) - Result: ~60-90% token reduction for tool-heavy conversations
How It Works
Technique 1: Tool Discovery & Code Generation
Transform tools into explorable code that agents can inspect and execute:
import { generateText, tool } from "ai";
import { z } from "zod";
import { SandboxManager, E2BSandboxProvider } from "ctx-zip";
// Step 1: Create a sandbox
const sandboxProvider = await E2BSandboxProvider.create();
const manager = await SandboxManager.create({ sandboxProvider });
// Step 2: Register MCP servers and/or AI SDK tools
await manager.register({
servers: [
{ name: "grep-app", url: "https://mcp.grep.app" },
{
name: "linear",
url: "https://mcp.linear.app/mcp",
headers: { Authorization: `Bearer ${process.env.LINEAR_TOKEN}` }
},
],
standardTools: {
weather: tool({
description: "Get the weather in a location",
inputSchema: z.object({
location: z.string(),
}),
async execute({ location }) {
const temp = 72 + Math.floor(Math.random() * 21) - 10;
return { location, temperature: temp, units: "°F" };
},
}),
},
});
// Step 3: Get exploration and execution tools
const tools = manager.getAllTools();
// Available: sandbox_ls, sandbox_cat, sandbox_grep, sandbox_find, sandbox_exec
// Step 4: Agent explores and uses tools
const result = await generateText({
model: "openai/gpt-4.1-mini",
tools,
prompt: "Search the codebase, check the weather, and create a Linear issue",
});
console.log(result.text);
// Cleanup
await manager.cleanup();What Gets Generated:
The register() call creates a directory structure in the sandbox:
/workspace/
├── servers/ # MCP tool implementations
│ ├── grep-app/
│ │ ├── search.ts
│ │ ├── index.ts
│ │ └── _types.ts
│ ├── linear/
│ │ ├── createIssue.ts
│ │ ├── searchIssues.ts
│ │ └── index.ts
│ └── _client.ts # MCP routing client
├── local-tools/ # AI SDK tool implementations
│ ├── weather.ts
│ └── index.ts
├── user-code/ # Agent execution workspace
└── compact/ # Tool output storage (for compaction)Exploration Tools:
Once tools are registered, agents can explore them:
sandbox_ls(path)- List directory contentssandbox_cat(path)- Read file contentssandbox_grep(pattern, path)- Search in filessandbox_find(pattern, path)- Find files by namesandbox_exec(code)- Execute TypeScript code
Example Agent Workflow:
// Agent explores available tools
await sandbox_ls("/workspace/mcp")
// → ["grep-app/", "linear/", "_client.ts"]
await sandbox_ls("/workspace/local-tools")
// → ["weather.ts", "index.ts"]
// Agent inspects a tool
await sandbox_cat("/workspace/mcp/grep-app/search.ts")
// → Full TypeScript source with types and documentation
// Agent writes code to use multiple tools together
await sandbox_exec(`
import { search } from './mcp/grep-app/index.ts';
import { createIssue } from './mcp/linear/index.ts';
import { weather } from './local-tools/index.ts';
const results = await search({ query: 'authentication bug' });
const topResult = results[0];
const weatherData = await weather({ location: 'San Francisco' });
await createIssue({
title: 'Fix auth bug from codebase search',
description: \`Found issue: \${topResult.content}\nWeather: \${weatherData.temperature}\`,
});
return { created: true, result: topResult.file };
`);API Reference:
// Create manager
const manager = await SandboxManager.create({
sandboxProvider?: SandboxProvider, // E2B, Vercel, or Local
sandboxOptions?: LocalSandboxOptions, // If no provider
});
// Register tools
await manager.register({
servers?: MCPServerConfig[], // MCP servers to connect
standardTools?: Record<string, Tool>, // AI SDK tools
standardToolOptions?: {
title?: string,
outputDir?: string,
},
});
// Get tools
manager.getAllTools() // Exploration + execution tools
manager.getExplorationTools() // ls, cat, grep, find (for MCP tools, defaults to mcp dir)
manager.getCompactionTools() // ls, cat, grep, find (for compacted files, defaults to workspace root)
manager.getExecutionTool() // Only exec
// Get paths
manager.getMcpDir() // /workspace/mcp
manager.getLocalToolsDir() // /workspace/local-tools
manager.getUserCodeDir() // /workspace/user-code
manager.getCompactDir() // /workspace/compact
manager.getWorkspacePath() // /workspace
// Cleanup
await manager.cleanup()Technique 2: Output Compaction with Smart Retrieval
Automatically persist large tool outputs to sandbox storage and retrieve them on-demand:
import { generateText, tool } from "ai";
import { z } from "zod";
import { compact, SandboxManager } from "ctx-zip";
// Create sandbox manager
const manager = await SandboxManager.create();
const fileAdapter = manager.getFileAdapter({ sessionId: "my-session" });
const result = await generateText({
model: "openai/gpt-4.1-mini",
tools: {
// Compaction tools for reading compacted files using exact paths
...manager.getCompactionTools(),
// Your data-generating tools
fetchEmails: tool({
description: "Fetch emails from inbox",
inputSchema: z.object({ limit: z.number() }),
async execute({ limit }) {
const emails = await getEmails(limit);
return { emails }; // This will be compacted
},
}),
},
prompt: "Check my latest emails and find any about 'budget'",
prepareStep: async ({ messages }) => {
// Compact outputs after each turn
const compacted = await compact(messages, {
storage: fileAdapter,
boundary: "all",
sessionId: "my-session",
});
return { messages: compacted };
},
});
await manager.cleanup();How Compaction Works:
- Agent calls a tool (e.g.,
fetchEmails(50)) - Large output returned (50 emails = 10,000 tokens)
compact()runs inprepareStep:- Detects large tool output
- Writes to storage:
/compact/my-session/tool-results/fetchEmails.json - Replaces output with reference:
Written to file: file:///path/compact/my-session/tool-results/fetchEmails.json Key: compact/my-session/tool-results/fetchEmails.json Use the read/search tools to inspect its contents.
- Agent can retrieve data:
sandbox_ls(path)- List directory contentssandbox_cat(file)- Read entire filesandbox_grep(pattern, path)- Search within filessandbox_find(pattern, path)- Find files by name pattern
Storage Location:
When using SandboxManager with compaction:
/workspace/
└── compact/
└── {sessionId}/
└── tool-results/
├── fetchEmails.json
├── searchGitHub.json
└── getWeather.jsonEach tool overwrites its own file on subsequent calls (one file per tool type).
Boundary Strategies:
Control which messages get compacted:
// 2. All messages - re-compact entire conversation
boundary: "all"
// 3. Keep first N - preserve system prompt, compact rest
boundary: { type: "keep-first", count: 5 }
// 4. Keep last N - preserve recent context, compact older
boundary: { type: "keep-last", count: 20 }Sandbox Tools for Retrieval:
Use compaction-specific tools that default to the workspace root:
const manager = await SandboxManager.create();
const tools = manager.getCompactionTools();
// Available: sandbox_ls, sandbox_cat, sandbox_grep, sandbox_find
// These default to workspace root for easy use with compaction paths
// The compaction message tells you exactly how to read the file:
// "Written to file: sandbox://... To read it, use: sandbox_cat({ file: "compact/..." })"
// Just copy the path from the message!API Reference:
// Compact messages
const compacted = await compact(messages, {
storage: FileAdapter | string, // Where to write files
boundary?: Boundary, // Which messages to compact
sessionId?: string, // Organize by session
fileReaderTools?: string[], // Tools that read (not persisted)
});Combining Both Techniques
Use tool discovery and compaction together for maximum efficiency:
import { generateText } from "ai";
import {
SandboxManager,
compact,
E2BSandboxProvider,
} from "ctx-zip";
// Step 1: Setup sandbox with tools
const sandboxProvider = await E2BSandboxProvider.create();
const manager = await SandboxManager.create({ sandboxProvider });
await manager.register({
servers: [
{ name: "grep-app", url: "https://mcp.grep.app" },
],
});
// Step 2: Get file adapter for compaction
const fileAdapter = manager.getFileAdapter({
sessionId: "combined-session",
});
// Step 3: Get all sandbox tools (exploration + execution)
// These same tools are used for both tool discovery AND accessing compacted outputs
const tools = manager.getAllTools();
// Step 4: Use in agent loop with compaction
const result = await generateText({
model: "openai/gpt-4.1-mini",
tools,
prompt: "Search for authentication bugs in the codebase and summarize",
prepareStep: async ({ messages }) => {
const compacted = await compact(messages, {
storage: fileAdapter,
boundary: "all",
sessionId: "combined-session",
});
return { messages: compacted };
},
});
console.log(result.text);
await manager.cleanup();Benefits:
- MCP tools explored on-demand (no upfront schema loading)
- Large search results compacted to sandbox storage
- Same exploration tools work for both tool discovery and compacted output retrieval
- Maximum token efficiency and simplified API
Sandbox Providers
ctx-zip supports three sandbox environments:
Local Sandbox (Default)
import { SandboxManager, LocalSandboxProvider } from "ctx-zip";
// Option 1: Let SandboxManager create default local sandbox
const manager = await SandboxManager.create();
// Option 2: Explicit local provider
const provider = await LocalSandboxProvider.create({
sandboxDir: "./.sandbox",
cleanOnCreate: false,
});
const manager = await SandboxManager.create({ sandboxProvider: provider });E2B Sandbox
import { SandboxManager, E2BSandboxProvider } from "ctx-zip";
const provider = await E2BSandboxProvider.create({
apiKey: process.env.E2B_API_KEY,
timeout: 1800000, // 30 minutes
});
const manager = await SandboxManager.create({ sandboxProvider: provider });Vercel Sandbox
import { SandboxManager, VercelSandboxProvider } from "ctx-zip";
const provider = await VercelSandboxProvider.create({
timeout: 1800000,
runtime: "node22",
vcpus: 4,
});
const manager = await SandboxManager.create({ sandboxProvider: provider });Examples
See the examples/ directory:
examples/mcp/- MCP server integration with grep.applocal_mcp_search.ts- Local sandboxe2b_mcp_search.ts- E2B sandboxvercel_mcp_search.ts- Vercel sandbox
examples/tools/- AI SDK tool transformationweather_tool_sandbox.ts- Transform and explore standard tools
examples/ctx-management/- Full-featured compaction demoemail_management.ts- Interactive email assistant with multi-environment support
API Overview
SandboxManager
class SandboxManager {
// Create
static async create(config?: {
sandboxProvider?: SandboxProvider,
sandboxOptions?: LocalSandboxOptions,
}): Promise<SandboxManager>
// Register tools
async register(options: {
servers?: MCPServerConfig[],
standardTools?: Record<string, Tool>,
standardToolOptions?: ToolCodeGenerationOptions,
}): Promise<void>
// Get tools
getAllTools(): Record<string, Tool>
getExplorationTools(): Record<string, Tool>
getExecutionTool(): Record<string, Tool>
// Get paths
getMcpDir(): string
getLocalToolsDir(): string
getUserCodeDir(): string
getCompactDir(): string
getWorkspacePath(): string
// File adapter for compaction
getFileAdapter(options?: {
prefix?: string,
sessionId?: string,
}): FileAdapter
// Static helper
static createLocalFileAdapter(options: LocalFileAdapterOptions): FileAdapter
// Cleanup
async cleanup(): Promise<void>
}Compaction
function compact(
messages: ModelMessage[],
options: CompactOptions
): Promise<ModelMessage[]>
interface CompactOptions {
storage: FileAdapter | string,
boundary?: Boundary,
sessionId?: string,
fileReaderTools?: string[],
}
type Boundary =
| "all"
| { type: "keep-first"; count: number }
| { type: "keep-last"; count: number }TypeScript Support
Full TypeScript support with exported types:
import type {
SandboxProvider,
FileAdapter,
CompactOptions,
Boundary,
E2BSandboxOptions,
LocalSandboxOptions,
VercelSandboxOptions,
} from "ctx-zip";License
MIT
Contributing
Contributions welcome! Please open an issue or PR.