AgentFS Documentation

repository·main·Indexed 25 days ago

https://github.com/tursodatabase/agentfs

AgentFS is a SQLite-based filesystem designed for AI agents, providing storage abstractions for files, key-value state, and tool-call audit trails to ensure reproducibility and portability. It includes a CLI for managing files and timelines, as well as TypeScript and Go SDKs. The system supports mounting via FUSE (Linux) and NFS (macOS), and provides integration with Go's io/fs standard library.

Tokens
44.3K
Snippets
96
Records
253
Agent score
85%

What's inside AgentFS

  1. Understand the Agent Filesystem Specification components

    main

    The Agent Filesystem Specification (v0.4) defines a SQLite schema for managing agent state. It is composed of three primary functional areas:

    1. Tool Call Audit Trail: An insert-only log that captures tool invocations, parameters, and results for debugging and performance analysis.
    2. Virtual Filesystem: A Unix-like inode-based storage system for agent artifacts (files, documents, outputs) supporting hard links and metadata.
    3. Key-Value Store: A simple get/set mechanism for agent context, preferences, and structured state.

    All timestamps use Unix epoch format (seconds since 1970-01-01 00:00:00 UTC), with optional nanosecond precision provided via _nsec columns.

  2. Use the AI SDK + just-bash Code Explorer Agent

    main

    Once the agent is running, you can interact with it via a readline shell. The agent uses Claude to orchestrate tasks and can execute shell commands via just-bash.

    Example queries you can use:

    • "What commands are available?"
    • "How is the grep command implemented?"
    • "Show me the Bash class"
    • "Find all test files"

    Type exit to quit the session.

  3. Create a File in AgentFS

    main

    To create a file, follow these steps within a transaction:

    1. Resolve the parent directory path to its inode.
    2. Retrieve the chunk_size from fs_config.
    3. Insert a new record into fs_inode and use RETURNING ino to get the new inode number.
    4. Insert a directory entry into fs_dentry mapping the filename to the new inode.
    5. Increment the inode's link count (nlink) in fs_inode.
    6. Split the file content into chunks of chunk_size and insert them into fs_data.
    7. Update the fs_inode with the final file size and mtime.
  4. Quick Start with AgentFS Python SDK

    main

    To get started, import AgentFS and AgentFSOptions, open an agent filesystem with a unique ID, and use the kv, fs, and tools interfaces. Remember to close the database using await agent.close() or use an async context manager.

    import asyncio
    from agentfs_sdk import AgentFS, AgentFSOptions
    
    async def main():
        # Open an agent filesystem
        agent = await AgentFS.open(AgentFSOptions(id='my-agent'))
    
        # Use key-value store
        await agent.kv.set('config', {'debug': True, 'version': '1.0'})
        config = await agent.kv.get('config')
        print(f"Config: {config}")
    
        # Use filesystem
        await agent.fs.write_file('/data/notes.txt', 'Hello, AgentFS!')
        content = await agent.fs.read_file('/data/notes.txt')
        print(f"Content: {content}")
    
        # Track tool calls
        call_id = await agent.tools.start('search', {'query': 'Python'})
        await agent.tools.success(call_id, {'results': ['result1', 'result2']})
    
        # Get statistics
        stats = await agent.tools.get_stats()
        for stat in stats:
            print(f"{stat.name}: {stat.total_calls} calls, {stat.avg_duration_ms:.2f}ms avg")
    
        # Close the database
        await agent.close()
    
    if __name__ == '__main__':
        asyncio.run(main())
  5. Quick Start with AgentFS Go SDK

    main

    This example demonstrates how to initialize an AgentFS database, perform filesystem operations (write/read), use the Key-Value store, and track tool calls.

    package main
    
    import (
    	"context"
    	"fmt"
    	"log"
    	"time"
    
    	agentfs "github.com/tursodatabase/agentfs/sdk/go"
    )
    
    func main() {
    	ctx := context.Background()
    
    	// Open or create an AgentFS database
    	afs, err := agentfs.Open(ctx, agentfs.AgentFSOptions{
    		ID: "my-agent", // Creates ~/.agentfs/my-agent.db
    	})
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer afs.Close()
    
    	// === Filesystem Operations ===
    
    	// Write a file
    	err = afs.FS.WriteFile(ctx, "/hello.txt", []byte("Hello, World!"), 0o644)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// Read a file
    	data, err := afs.FS.ReadFile(ctx, "/hello.txt")
    	if err != nil {
    		log.Fatal(err)
    	}
    	fmt.Println(string(data)) // "Hello, World!"
    
    	// Create directories
    	err = afs.FS.MkdirAll(ctx, "/path/to/dir", 0o755)
    
    	// List directory
    	names, err := afs.FS.Readdir(ctx, "/")
    	for _, name := range names {
    		fmt.Printf("File name: %s\n", name)
    	}
    
    	// Get file stats
    	stats, err := afs.FS.Stat(ctx, "/hello.txt")
    	fmt.Printf("Size: %d, IsDir: %v\n", stats.Size, stats.IsDir())
    
    	// === Key-Value Store ===
    
    	// Store values (JSON-serialized)
    	err = afs.KV.Set(ctx, "config:version", "1.0.0")
    
    	type Settings struct {
    		Theme    string `json:"theme"`
    		FontSize int    `json:"font_size"`
    	}
    	err = afs.KV.Set(ctx, "user:settings", Settings{Theme: "dark", FontSize: 14})
    
    	// Retrieve values
    	var version string
    	err = afs.KV.Get(ctx, "config:version", &version)
    
    	var settings Settings
    	err = afs.KV.Get(ctx, "user:settings", &settings)
    
    	// List keys by prefix
    	keys, err := afs.KV.Keys(ctx, "config:")
    	for _, key := range keys {
    		fmt.Printf("Key: %s\n", key)
    	}
    
    	// === Tool Call Tracking ===
    
    	// Start/Success pattern
    	pending, err := afs.Tools.Start(ctx, "web_search", map[string]string{
    		"query": "golang sqlite",
    	})
    
    	// ... perform operation ...
    
    	call, err := pending.Success(ctx, map[string]any{
    		"results": []string{"result1", "result2"},
    	})
    	fmt.Printf("Tool call %d completed in %dms\n", call.ID, call.DurationMs)
    
    	// Or record directly
    	now := time.Now().Unix()
    	call, err = afs.Tools.Record(ctx, "read_file",
    		map[string]string{"path": "/test.txt"},
    		"file contents",
    		nil, // no error
    		now-1, now,
    	)
    
    	// Query tool calls
    	calls, err := afs.Tools.GetByName(ctx, "web_search", 10)
    	stats, err := afs.Tools.GetStats(ctx)
    }
  6. Run the Research Assistant (VLDB + SIGMOD) example

    main

    The Research Assistant is a minimal tool designed to answer database research questions by retrieving relevant papers from VLDB and SIGMOD conference proceedings.

    To use this example, follow these steps:

    1. Install dependencies: Run npm install in the project directory.
    2. Ask a question: Use the npm run ask command followed by your research question in quotes.

    Example usage:

    npm run ask -- "How do learned indexes compare to B+ trees?"