Skip to main content

agent-vfs

The best AI agents already use filesystems as memory. Now your agent can too.

agent-vfs gives your agent a persistent virtual filesystem backed by your own database. Agents use familiar file operations (read, write, ls, grep) while data lives in SQLite or Postgres.

pip install agent-vfs
from agent_vfs import FileSystem, open_database

db = open_database("memory.db")  # SQLite, auto-creates table
fs = FileSystem(db, "agent-1")

fs.write("/notes.md", "# Meeting Notes\n- Ship agent-vfs")
content = fs.read("/notes.md")

Persistent memory that survives restarts, multi-tenant by default, no external services. One table in your database. Zero dependencies for SQLite (uses Python's built-in sqlite3).

Also available for TypeScript: npm install agent-vfs (docs)

Use with any AI SDK

OpenAI SDK

from openai import OpenAI
from agent_vfs import FileSystem, open_database, openai

db = open_database("memory.db")
fs = FileSystem(db, user_id)
tools, handle_tool_call = openai(fs)

response = OpenAI().chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
)

for call in response.choices[0].message.tool_calls or []:
    result = handle_tool_call(call.function.name, call.function.arguments)
    messages.append({
        "role": "tool",
        "tool_call_id": call.id,
        "content": result["text"],
    })

Anthropic SDK

from anthropic import Anthropic
from agent_vfs import FileSystem, open_database, anthropic

db = open_database("memory.db")
fs = FileSystem(db, user_id)
tools, handle_tool_call = anthropic(fs)

response = Anthropic().messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=messages,
    tools=tools,
)

for block in response.content:
    if block.type == "tool_use":
        result = handle_tool_call(block.name, block.input)
        messages.append({
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": result["text"],
            }],
        })

Example: chat agent with persistent memory

The most common pattern is an agent that loads its memory at the start of each session, then reads and writes files as it chats.

from anthropic import Anthropic
from agent_vfs import FileSystem, open_database, anthropic

db = open_database("memory.db")
fs = FileSystem(db, user_id)
tools, handle_tool_call = anthropic(fs)

# Boot: load the agent's memory into the system prompt
try:
    memory = fs.read("/memory.md")
except FileNotFoundError:
    memory = "(no memory yet)"

system = f"""You are a helpful assistant with persistent memory.
Your current memory:
{memory}

You have filesystem tools. Use them to remember things across sessions.
Save important facts to /memory.md. Organize notes in folders as needed."""

messages = []

while True:
    user_input = input("> ")
    messages.append({"role": "user", "content": user_input})

    response = Anthropic().messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        system=system,
        messages=messages,
        tools=tools,
    )

    while response.stop_reason == "tool_use":
        tool_results = []
        for block in response.content:
            if block.type == "tool_use":
                result = handle_tool_call(block.name, block.input)
                tool_results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result["text"],
                })
        messages.append({"role": "assistant", "content": response.content})
        messages.append({"role": "user", "content": tool_results})
        response = Anthropic().messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=4096,
            system=system,
            messages=messages,
            tools=tools,
        )

    text = "".join(b.text for b in response.content if b.type == "text")
    print(text)
    messages.append({"role": "assistant", "content": response.content})

Tools (16)

Tool Description Key Options
read Read a file offset, limit (line range)
write Write a file (auto-creates parent dirs) summary (optional description for search/ls)
edit Find-and-replace (unique match required)
multi_edit Multiple find-and-replace edits in one call
append Append to a file (creates if missing)
ls List directory recursive, summaries
mkdir Create directory (idempotent, creates parents)
rm Remove file or directory (recursive)
grep Search file contents (regex) case_insensitive
glob Find files by name (glob pattern) type (file/dir)
mv Move or rename (overwrites target)
search Semantic search across all files (FTS5 + optional vectors) path, limit
tag Add a tag to a file or directory
untag Remove a tag from a file or directory
find_by_tag Find all files with a specific tag path (scope)
recent List recently modified files limit, path (scope)

Search

Built-in full-text search (FTS5) with optional vector embeddings for hybrid semantic search.

from agent_vfs import FileSystem, open_database
from agent_vfs.search import open_search

db = open_database("memory.db")

# FTS5 only (zero dependencies):
search = open_search(db, user_id)

# Hybrid FTS5 + vector (just add an API key):
search = open_search(db, user_id, "openai", os.environ["OPENAI_API_KEY"])

fs = FileSystem(db, user_id, search_index=search)

fs.write("/notes.md", "Architecture decisions", summary="Key design choices")
results = fs.search("architecture")

Supported embedding providers: openai, openai-large, voyage, voyage-large, mistral. Or pass a custom url, model, api_key, and dimensions to open_embeddings().

Multi-tenancy

One database, many users. Each FileSystem is scoped by user ID with full isolation at the DB layer:

db = open_database("memory.db")
alice_fs = FileSystem(db, "alice")
bob_fs = FileSystem(db, "bob")

alice_fs.write("/secret.txt", "alice only")
bob_fs.read("/secret.txt")  # raises NotFoundError

Production database

pip install agent-vfs[postgres]
from agent_vfs import open_database, FileSystem

db = open_database("postgresql://user:pass@localhost/mydb")
fs = FileSystem(db, user_id)

Or bring your own connection:

from agent_vfs.db.postgres import PostgresDatabase
import psycopg2

conn = psycopg2.connect("postgresql://...")
db = PostgresDatabase(conn)
db.initialize()
fs = FileSystem(db, user_id)

Custom table name:

db = open_database("app.db", table_name="agent_files")

License

MIT

Release files for agent-vfs 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agent-vfs 0.2.0
File Size Uploaded
agent_vfs-0.2.0.tar.gz 23.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for agent-vfs 0.2.0
File Interpreter ABI Platform
agent_vfs-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 47.8 kB

Release files / agent_vfs-0.2.0.tar.gz

Download URL agent_vfs-0.2.0.tar.gz
Size 23.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a1ba9951b5572296fb7da3d8f9273e3c2d7b9c6850b05672867d750e4f1039e8
BLAKE2b-256 checksum
How to use checksums
00114f445bd9be828ff5ec61d398b6e5556377fb8f2c9bb9e485e9c154061297
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 10, 2026.

Transparency log

Release files / agent_vfs-0.2.0-py3-none-any.whl

Download URL agent_vfs-0.2.0-py3-none-any.whl
Size 24.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9a9ddb6ee0f3271c7c1b741771bd4e1f81d78b0d0f71206d082d7ddcccaecd4f
BLAKE2b-256 checksum
How to use checksums
b086186b65f64379a03c81449281e6e9bd43f82f5a2d512ce87e4e87671d3279
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page