Skip to content

Architecture

TinyFat is built on open-source components with a simple, transparent architecture.

ComponentTechnologyPurpose
Agent runtimepi-monoClaude-powered agent framework
ContainerCloudflare Sandbox SDKSecure container execution
StorageCloudflare R2Per-agent persistent storage
PlatformAstro on Cloudflare PagesDashboard, API, webhooks
QueueCloudflare QueuesJob orchestration
EmailResendInbound/outbound email
DatabaseSupabaseUser accounts, agent config

Agent identity lives entirely in R2 storage, not the container.

All agents share the same stateless container image. Each agent gets temporary R2 credentials scoped to their storage prefix (agents/{id}/). The container mounts that prefix at /data. Your agent sees only its files.

┌─────────────────────────────────────────────┐
│ Shared Sandbox Container │
│ (stateless - same code for all agents) │
├─────────────────────────────────────────────┤
│ Agent A: r2:bucket/agents/a/ → /data │
│ Agent B: r2:bucket/agents/b/ → /data │
└─────────────────────────────────────────────┘
1. You send email to [email protected]
2. Resend receives it, sends webhook to platform
3. Platform validates sender, looks up agent
4. Platform enqueues job to sandbox-queue
5. Queue worker generates scoped R2 credentials
6. Worker calls sandbox-spike with agent config
7. Sandbox mounts agent's R2 prefix at /data
8. step-mom runs one agent turn via pi-mono
9. Agent writes response to /data/outbox/email/
10. Worker reads outbox, sends email via Resend
11. You receive reply

Each email triggers exactly one agent turn:

  1. Read input
  2. Think + use tools
  3. Write output
  4. Exit

This avoids complexity of long-running processes, connection management, and state drift.

The core execution engine:

  • Receives job from queue
  • Mounts R2 storage with scoped credentials
  • Runs step-mom (the agent harness)
  • Reads outbox files and returns emails

TypeScript harness running inside the container:

  • Reads input from /inbox/input.json
  • Creates AgentSession using pi-mono
  • Runs one turn via session.prompt()
  • Writes emails to /data/outbox/email/*.json
  • Streams events to /data/events/ for dashboard

Queue consumer that orchestrates execution:

  • Parses commands (/clear, /resume, /model)
  • Calls sandbox-spike to run agent
  • Sends response emails via Resend
  • Tracks job status in Supabase

Per-agent prefix in R2: agents/{agent_id}/

agents/{agent_id}/
├── MEMORY.md # Agent's persistent memory
├── config.json # Agent preferences (model, etc.)
├── sessions/
│ └── {id}.jsonl # Conversation history files
├── outbox/
│ ├── email/ # Pending emails (written by agent)
│ ├── sent/ # Successfully sent
│ └── failed/ # Failed to send
└── events/
└── {timestamp}.jsonl # Run events for dashboard

Your Anthropic API key is encrypted at rest using AES-256-GCM. It’s only decrypted when:

  • Starting your container
  • Injected as environment variable
  • Never logged or exposed in UI

Only whitelisted emails can trigger your agent. This prevents:

  • Spam triggering expensive API calls
  • Unauthorized access to your agent

Configure in the dashboard under Settings.

Each agent run is isolated:

  • Scoped R2 credentials (can’t access other agents’ data)
  • No network access to internal services
  • Container exits after each turn

Agents don’t send emails directly. They write JSON files to /data/outbox/email/:

{
"to": ["[email protected]"],
"subject": "Re: Help request",
"body": "Here's what I found...",
"in_reply_to": "<message-id>",
"status": "pending"
}

The queue worker reads these and sends via Resend. This provides:

  • Reliability — If sending fails, the file stays for retry
  • Auditability — Every outgoing email is a file you can inspect
  • Simplicity — Agent doesn’t need email credentials

Sessions persist in /data/sessions/ as JSONL files. Each file contains:

  • Your messages
  • Agent responses
  • Tool calls and results

Use email commands to manage sessions:

  • /clear — Start fresh (old sessions preserved)
  • /resume — List available sessions
  • /resume abc1 — Resume specific session by hash

Responses maintain proper email threading:

  • In-Reply-To header set to original Message-ID
  • References header includes thread chain
  • Gmail/Outlook group replies correctly

Each response includes a footer:

---
[agent:a1b2 | ↑38 ↓5.0k R663k W37k $0.687 18.7%/200k | claude-haiku-4-5]

Shows: agent name, session hash, tokens in/out, cache stats, cost, context usage, model.

The entire agent runtime is inspectable:

Want to self-host? You need:

  • Cloudflare account (Workers, R2, Queues)
  • Anthropic API key
  • Email provider (Resend, Postmark, etc.)
  • Supabase or equivalent for user data

The platform code isn’t currently open source, but the agent runtime is fully open.