Skip to main content
Every Book in Pathway has its own AI agent. The agent runs inside an ephemeral Linux sandbox with Python, pip, network access, and a writable filesystem. It can run code, read files, produce artifacts, and reason over everything in the Book.

What you can do

Ask questions about your Book. The agent has access to the full parsed data and computed analytics. Ask about total deposits, true revenue, debt-to-income, specific transactions, counterparty breakdowns, or anything else in the data. It computes answers from the source, not from summaries. Generate charts and reports. The agent writes Python, runs it, and produces output. Ask for a revenue trend chart, a cash flow heatmap, a custom Excel export, an HTML report. Generated files appear inline in the chat as images, interactive previews, or download links. Work with email. Connect a Gmail account and the agent can search your inbox, read threads, download attachments, and process them alongside Book data. Ask it to find invoices from a specific sender, pull the amounts from the PDFs, and compare them against bank statement deposits. Attach files. Drop a CSV, PDF, image, or spreadsheet into the chat. The agent can read it, parse it, cross-reference it against Book data, or just answer questions about it. Standalone chats. Chats that are not attached to a Book get the same sandbox and tools, just without the pre-loaded financial data. Use them for general computation, data analysis, or anything else.

How it works

The sandbox

Each chat gets a fresh sandbox created from a cached snapshot. pandas, numpy, matplotlib, seaborn, openpyxl, scipy, and tabulate are pre-installed. Anything else installs with pip. The filesystem is rooted at /tmp/. Network is open. The first sandbox on the platform bootstraps: installs the package set, takes a snapshot. Every sandbox after that creates from the snapshot in seconds. The snapshot is cached in Redis with a 29-day TTL and refreshed before it expires. For Book chats, two things happen before the first message. The raw financial documents are downloaded from S3 to /tmp/documents/. The full parsed and analytics data is written to /tmp/context/book_data.json. User-attached files go to /tmp/uploads/. Sandboxes are ephemeral. They live for the conversation and are destroyed after. If one times out mid-conversation, a new sandbox spins up from the snapshot, the files are restored, and the conversation continues.

The filesystem

Every object in the system is a file at a known path.
PathContents
/tmp/context/book_data.jsonParsed data and computed analytics for the Book
/tmp/documents/Raw financial documents (bank statements, tax returns, credit reports)
/tmp/uploads/Files the user attaches to a message
/tmp/emails/{message_id}/Fetched email bodies and downloaded attachments
/tmp/emails/threads/{thread_id}/Full email threads as markdown
/tmp/Everything the agent generates: scripts, charts, spreadsheets, exports
The agent reads book_data.json with cat or loads it into pandas. It opens a PDF with view_file. It processes a CSV with Python. Every tool writes its output to disk, and every other tool reads from disk. There is no serialization layer between them, no protocol for handing data from one step to the next. Tools compose because they share a filesystem, the same way shell commands compose because they share stdio. This is what makes cross-domain queries work without purpose-built integrations. When asked to compare bank statement revenue against invoices from email, the agent searches Gmail, downloads attachments to /tmp/emails/, loads the book analytics from /tmp/context/book_data.json, and writes a Python script that reads both. That works because both data sources landed as files in the same namespace.

Tools

Four core tools, built on two primitives: the shell and the filesystem. run_command executes a shell command. The agent reads files with cat, installs packages with pip, runs scripts, pipes output, curls endpoints. stdout and stderr come back as text. Long output is truncated at the midpoint to keep the context window manageable. write_file writes content to a path. Used for config and data files. For Python scripts, the agent writes via a shell heredoc through run_command instead, which avoids JSON escaping issues. save_artifact reads a file from the sandbox, uploads it to S3, and returns a permanent URL through the asset proxy. The agent embeds this URL in its markdown response. Images render inline. HTML renders in a sandboxed iframe. Excel files get a live Office Online preview. Everything else becomes a download link. view_file reads an image or PDF from the sandbox and injects the raw bytes into the LLM’s visual context. After generating a chart, the agent calls view_file to see the pixels and can then describe or correct what it produced. Text files are read with cat. save_artifact is for the user: a permanent URL rendered in the response. view_file is for the agent: bytes in the context window for visual reasoning.

Gmail tools

When a connected Gmail account is enabled, the agent gets five additional tools. These run as server-side API calls, but their results land on the sandbox filesystem as markdown and attachment files. search_inbox takes a Gmail query string (from:, subject:, has:attachment, newer_than:, label:) and returns compact results: message ID, sender, subject, date, snippet, thread ID. fetch_email takes a message ID. Returns the body inline and writes it to /tmp/emails/{message_id}/email.md. Lists attachments with metadata (filename, ID, size) but does not download them. fetch_thread takes a thread ID. Returns all messages inline and writes them to /tmp/emails/threads/{thread_id}/. Lists attachments but does not download them. fetch_attachment takes a message ID and optionally a list of specific attachments. Downloads them to /tmp/emails/{message_id}/ and returns the file paths. get_labels lists all Gmail labels and folders with unread and total message counts. The typical flow: search, scan results, fetch threads that matter, download specific attachments, then process with the core tools. A CSV gets loaded into pandas. A PDF gets inspected with view_file. An invoice image gets read visually by the LLM. Gmail access is read-only and toggled per chat.

The asset proxy

Every file in the platform is stored in S3 and served through one endpoint: /api/assets/{s3_key}. The key contains an unguessable UUID, so the endpoint needs no authentication. It generates a short-lived pre-signed URL and returns a 302 redirect. For Excel files, passing ?embed=office returns a JSON payload with a fresh Office Online embed URL instead of redirecting. The frontend uses this to render interactive spreadsheet previews in the chat, in the Book’s spreadsheet tab, and in the embed API. Chat artifacts, spreadsheet exports, document uploads, and embed API assets all route through this proxy. The frontend receives a URL, checks the mime type, and renders the right preview component. It does not distinguish between a chart the agent just generated and a spreadsheet the parser produced.

Book context

Book chats load /tmp/context/book_data.json with two top-level keys: parsed and analytics. parsed is the raw parser output: business identity, owner details, bank account metadata, raw ledger transactions with dates and descriptions, loan positions with matched disbursements and payment schedules, web research results, and tampering analysis. analytics is the computed metrics: total deposits, true revenue, average daily balance, days negative, NSF and overdraft counts, debt-to-income ratio, per-statement breakdowns by account, counterparty clusters, and loan summaries by type. The Book overview tab, the Salesforce sync, and the spreadsheet generator all read from this same object. The agent reads the same object. It can answer metric questions directly, or go further: cross-reference transactions across accounts, build custom visualizations, run regressions, generate reports in formats the structured UI does not support. When a user re-tags a transaction (marking a deposit as an internal transfer, assigning a payment to a position), the analytics recompute. The next chat session loads the new data. The spreadsheets regenerate. The Salesforce metrics update. Tags are the single input; everything downstream derives from them.

Turns

A turn starts when the user sends a message. The backend builds the full conversation history, appends the system prompt, and sends it to the LLM. The LLM responds with text, tool calls, or both. Tool calls execute against the sandbox. Results feed back to the LLM, which responds with more text, more tool calls, or both. The loop continues until the LLM responds with text only, or the round limit is reached. Tool calls and text stream to the frontend in real time.

Rendering

Tool calls render as collapsible rows with an icon and label ( Run command, Save artifact, Fetch email, etc.). Expanding a row shows the full input syntax-highlighted (bash for run_command, the file’s language for write_file, JSON for everything else) and the full output syntax-highlighted. If the output contains a URL, a preview renders based on mime type: images inline, PDFs in an embedded viewer, HTML in a sandboxed iframe, Excel in Office Online, everything else as a download link. Adding a new tool to the backend requires no frontend changes. The rendering inspects the output shape and mime type, nothing else.

State

The sandbox filesystem and the conversation history. Files on disk, messages in the database. Two additions to a bare shell: save_artifact for uploading to permanent storage, view_file for injecting visual content into the LLM context.