An agent is a folder.

When you create a new agent in Houston, what really happens is that we make a folder. No databases. No proprietary formats. Just files.

What's inside

Open ~/.houston/workspaces/MyCompany/Sales/ and you see this:

CLAUDE.md ← the agent's instructions .houston/ agent.json ← metadata (id, created_at) activity/ ← things the agent should do routines/ ← scheduled prompts (cron) routine_runs/ ← audit of past cron fires config/ ← per-agent config learnings/ ← memories the agent has built up prompts/modes/ ← editable prompt overlays sessions/ ← per-provider resume ids (anthropic/, openai/) .agents/skills/ ← installed skills .claude/skills/ ← symlinks (Claude Code reads here) AGENTS.md ← symlink → CLAUDE.md (Codex reads here)

Why files

Files are inspectable, portable, and ordinary. You back up an agent by copying its folder. You move it to another machine by copying its folder. You restore it the same way.

The engine reads from this folder. The CLI subprocess writes to it directly when it edits files. The user can hand-edit anything in it. All three actors work on the same files.

Where that folder physically lives

Today on Mac, Windows, and Linux: in your real home directory, ~/.houston/workspaces/.... You can open it in Finder.

If Chapter 3 ships: inside a Linux runtime that runs alongside the desktop app. On Linux, that's the host filesystem (same as today). On Windows, it's the WSL2 filesystem, which Windows Explorer exposes at \\wsl$\Houston\.... On Mac, it lives inside the VM's disk image and is reached through the app's Files panel, with explicit Import, Download, and Export flows.

The reason the folder might move is in Chapter 3. The short version: most real users keep their data in Drive, Slack, Notion, and Gmail. They don't browse ~/Documents. Putting agents inside a Linux runtime could give us per-agent isolation and reduce Windows tooling differences. The cost is that host file access stops working uniformly. The Files panel, Import, Download, and Export flows replace direct host access where needed.

Schemas as source of truth

Each typed file (activity, routines, config, etc) has a JSON Schema. Those schemas live in ui/agent-schemas/ and get embedded into the Rust binary at compile time via include_str!. On first launch, the engine seeds each agent's folder with a copy of the relevant schema so the LLM can validate before writing.

One source of truth, two consumers (Rust engine and TS client). One PR changes both.

The reactivity stack

Files change in three ways: the user writes via the UI, the LLM writes via its CLI tools, or a human edits with a text editor. All three need to update the UI in real time.

  1. Engine writes emit a HoustonEvent on the broadcast bus.
  2. Direct CLI writes are caught by a notify file watcher in houston-file-watcher, which emits the same event.
  3. The frontend uses TanStack Query keyed on the file path. Events invalidate the query, which refetches.

The rule: no feature where the agent changes data but the UI doesn't update until refresh.

What stays the same after the redesign

The folder layout. The schemas. The reactivity stack. The atomic write rules. The migration story. All of that survives Chapter 3 untouched. What changes is the location of the folder and how the desktop app gets bytes in and out of it.

Where to look in the code

File I/O and migrations: engine/houston-agent-files. JSON schemas: ui/agent-schemas/src/*.schema.json. File watcher: engine/houston-file-watcher. Event invalidation: app/src/hooks/use-agent-invalidation.ts. Migrations: houston_agent_files::migrate_agent_data.