The terminal is the best agent architecture
Most agent tooling is built on a false premise: that we can predict what context the model needs better than the model can. That means brittle retrieval pipelines and custom APIs for every data type. A simpler pattern works better: replace most custom tools with a filesystem and bash. The sales call summarization agent we built this way dropped from roughly $1.00 to $0.25 per call on Claude Opus 4.5, while output quality improved. The same approach powers d0, our text-to-SQL agent.
The reasoning is straightforward. LLMs are trained on massive amounts of code, so they are already experts at navigating directories, grepping through files, and managing state across a codebase. Give an agent the same tools for any domain, and it brings the same capabilities. Customer support tickets, sales transcripts, CRM records: structure them as files, expose bash, and the model uses familiar patterns to find what it needs.
Agent receives task
↓
Explores filesystem (ls, find)
↓
Searches for relevant content (grep, cat)
↓
Sends context + request to LLM
↓
Returns structured output
The agent and its tool execution run on separate compute. The model's reasoning is trusted; the sandbox limits what its actions can reach.
Filesystems vs. prompt stuffing and vector search
Most agent context strategies fall into two camps. Prompt stuffing fills the context window until it hits token limits. Vector search handles semantic similarity but is imprecise when you need a specific value from structured data. Filesystems have a different tradeoff.
Structure maps to your domain. Customer records and ticket histories have natural hierarchies that map to directories without flattening relationships into embeddings.
Retrieval is exact. grep -r "pricing objection" transcripts/ returns precise matches, not approximations.
Context loads on demand. A long transcript does not enter the prompt upfront. The agent reads metadata, greps relevant sections, and pulls only what it needs.
Structuring domains as files
The pattern applies across domains. In a customer support system, don't throw raw JSON at the agent:
/customers/
/cust_12345/
profile.json # High-level info
tickets/
ticket_001.md # Each ticket
ticket_002.md
conversations/
2024-01-15.txt # Daily conversation logs
preferences.json
When asked "What was the resolution to my issue?", the agent can ls the tickets directory, grep for "resolved", and read the relevant file.
For a document analysis pipeline:
/documents/
/uploaded/
contract_abc123.pdf
invoice_def456.pdf
/extracted/
contract_abc123.txt
invoice_def456.txt
/analysis/
contract_abc123/
summary.md
key_terms.json
risk_assessment.md
/templates/
contract_analysis_prompt.md
invoice_validation_rules.md
Raw inputs sit in one place, processed outputs in structured directories. The agent can reference prior analysis without reprocessing anything.
Case study: a sales call summary agent
The Sales Call Summary template demonstrates the architecture. The agent reads call transcripts and produces structured summaries covering objections, action items, and insights. It starts with this structure:
gong-calls/
demo-call-001-companyname-product-demo.md # Current call transcript
metadata.json # Call metadata
previous-calls/
demo-call-000-discovery-call.md # Prior discovery call
demo-call-intro-initial-call.md # Initial intro call
salesforce/
account.md # CRM account record
opportunity.md # Deal/opportunity details
contacts.md # Contact profiles
slack/
slack-channel.md # Slack history
research/
company-research.md # Company background
competitive-intel.md # Competitor analysis
playbooks/
sales-playbook.md # Internal sales playbook
The agent explores it the way it would a codebase:
# Explore what's available
$ ls sales-calls/
customer-call-123456-q4.md
metadata.json
# Read the metadata
$ cat sales-calls/metadata.json
# Look for objections
$ grep -i "concern\|worried\|issue\|problem" sales-calls/*.md
The transcript is treated like source code. The agent searches for patterns, reads sections, and assembles context the same way it would debug a program. No custom retrieval logic is involved. Because the agent works against the raw information with tools it already knows well, it can handle edge cases that were never anticipated by hand-written parameters.
Why bash and filesystems win
Native model capabilities. grep, cat, find, awk are not novel skills. Models encountered these tools billions of times in training; they are native behavior, not bolted-on tools.
Scaling with future models. As models improve at coding, this architecture improves with them. Each gain in code comprehension transfers directly to the agent's other domains.
Complete debuggability. Failure shows exactly which files were read and which commands were run. The execution path is visible, no black box.
Isolation-based security. The sandbox confines the agent's exploration, separating what it can reason about from what it can affect.
Minimal code. Writing files into a directory structure replaces building retrieval pipelines per data type.
Getting started
When building an agent, resist creating custom tools. Instead ask whether the domain can be represented as files. If so, filesystem plus bash may be all that's needed. The recently open-sourced bash-tool is a dedicated implementation of this pattern.
- AI SDK for tool execution and model calls
- bash-tool for sandboxed filesystem access
- Sales Call Summary template for a one-click working version
More about building agents with Vercel Sandbox.



