LEGR

Rocket Money on steroids for startups: a fleet of autonomous finance agents, long-running on Dedalus, conversational through Photon. They negotiate. They close. They save.

Inspiration

As founders, we live the problem. To ship fast, we use a lot of tools — Claude APIs, Cursor seats, Notion, Linear, Vercel, seven analytics tools we A/B'd and never cleaned up. Money leaks out in a hundred small ways:

  • Wrong-model API calls running Opus when Haiku would do
  • Ghost seats for employees who left four months ago
  • Subs nobody remembers signing up for
  • Renewals that auto-bump 18% because no one pushed back

Startups move fast, but their financial decisions are slow, manual, and reactive. Consumers got Rocket Money. Startups got nothing.

Existing tools either show you waste without fixing it (dashboards get ignored) or cost $2K/mo for enterprise features early startups don't need. We didn't want another dashboard. We wanted agents that do the work — draft the cancellation email, negotiate the renewal for three days straight, survive restarts, text the founder "saved $4,140/yr" when it's done.

What it does

LEGR is a fleet of autonomous finance agents that handles the boring, expensive work of running a startup's finances — and lives in your iMessage through Photon.

Three pillars:

🤖 AI Spend Optimization — catches wrong-model routing ("31K Opus calls that should've been Haiku — $2,840/mo"), idle credits, forgotten batch jobs.

📦 SaaS Sprawl Killer — finds ghost seats and zombie subs by cross-referencing invoices with real usage signals (GitHub, Calendar, Gmail), then negotiates renewals autonomously instead of just flagging them.

💳 Expense Compliance — scores every card swipe against policy with confidence scores. Silent when clean, loud when something's off.

Founder dashboard — a single pane showing active Machines, live negotiation threads, savings-to-date, agent activity feed, and per-pillar drill-downs. Every Machine on the dashboard is clickable — see the full state file, thread history, and Claude reasoning trace.

The autonomy loop:

Founder: "yes, negotiate Cursor"
  → LEGR spawns a Machine
  → Machine drafts round 1, sends, monitors inbox
  → Vendor replies 18h later → Machine reasons, counters at 22%
  → Vendor accepts 2 days later
  → Founder gets one message: "Closed. $4,140/yr saved."

Founder typed 3 words. LEGR handled 40+ hours of back-and-forth.

How we built it

Built around one architectural thesis: short-lived reasoning calls for stateless work, long-running Dedalus Machines for processes that outlive any single request.

Architecture:

┌─────────────────────────────────────────────────────────────────┐
│                       DATA INGESTION LAYER                       │
├──────────────┬──────────────┬──────────────┬────────────────────┤
│   Knot       │   Gmail      │   Calendar   │   Direct APIs      │
│TransactionLink│  MCP        │   MCP        │ (Anthropic/OpenAI) │
└──────┬───────┴──────┬───────┴──────┬───────┴──────┬─────────────┘
       ▼              ▼              ▼              ▼
┌─────────────────────────────────────────────────────────────────┐
│                   SUPABASE (Postgres + Realtime)                 │
│   transactions, ai_usage, agent_alerts, negotiation_history      │
└──────────────────────────┬──────────────────────────────────────┘
                           │  Realtime INSERT
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│              DEDALUS ORCHESTRATOR (stateless router)             │
│   classifies event → dispatches to short-lived OR spawns Machine │
└──┬────────────┬─────────────┬─────────────┬─────────────────────┘
   │            │             │             │
   │ short-lived agent calls  │             │ spawns long-running
   ▼            ▼             ▼             ▼
┌──────┐   ┌─────────┐   ┌──────────┐  ┌──────────────────────────┐
│ AI-  │   │ SaaS    │   │Compliance│  │   DEDALUS MACHINE         │
│Spend │   │Discovery│   │ Agent    │  │   Negotiation Agent       │
│Agent │   │ Agent   │   │          │  │   (long-running process)  │
│      │   │         │   │ returns  │  │                           │
│returns│  │returns  │   │ in <1s   │  │   uptime: days/weeks      │
│ <5s  │   │ <5s     │   │          │  │   one Machine per deal    │
└──┬───┘   └────┬────┘   └────┬─────┘  └────────────┬──────────────┘
   │            │             │                     │
   │            │             │        ┌────────────┴──────────────┐
   │            │             │        │  PERSISTENT VOLUME         │
   │            │             │        │  /data/negotiations/       │
   │            │             │        │    cursor-2026-04.json     │
   │            │             │        │    notion-2026-04.json     │
   │            │             │        │  /data/logs/               │
   │            │             │        │  /data/receipts/           │
   │            │             │        └────────────┬──────────────┘
   │            │             │                     │
   │            │             │        ┌────────────┴──────────────┐
   │            │             │        │  MACHINE INTERNAL LOOP     │
   │            │             │        │  ├─ inbox.py (IMAP poll)   │
   │            │             │        │  ├─ reasoner.py (Claude)   │
   │            │             │        │  ├─ outbox.py (SMTP send)  │
   │            │             │        │  ├─ state.py (JSON r/w)    │
   │            │             │        │  └─ loop.py (while True)   │
   │            │             │        └────────────┬──────────────┘
   │            │             │                     │
   └────────────┴─────────────┴─────────────────────┘
                              │  writes back to Supabase
                              ▼                ▲
                  ┌─────────────────┐          │
                  │  agent_alerts   │──────────┘
                  │  negotiation_   │  Machine updates status,
                  │    history      │  logs rounds, posts wins
                  └────────┬────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                      PHOTON iMESSAGE LAYER                       │
├────────────────────────────────┬────────────────────────────────┤
│      FOUNDER THREAD            │      EMPLOYEE THREADS          │
│                                │                                │
│ - daily brief                  │ - expense memo asks            │
│ - "Negotiate Cursor? Y/N"      │ - seat usage check-ins         │
│ - Machine updates: "Round 3,   │                                │
│    vendor offered 18%,         │                                │
│    countering at 22%"          │                                │
│ - "Cursor closed at 22% ✓"     │                                │
└────────────────────────────────┴────────────────────────────────┘

Stack:

Layer Tech
Agent runtime Dedalus Machines (long-running negotiation)
Reasoning Dedalus + Claude Sonnet 4
Interface Photon (iMessage) + Next.js dashboard
Data Supabase (Postgres + Realtime)
Ingestion Knot TransactionLink, Gmail MCP, Calendar MCP
Email IMAP inbound + Resend outbound
Webhooks FastAPI

The Orchestrator — stateless router. Classifies each event with a quick Claude call, then either awaits a short-lived agent or spawns a Machine. That split is the whole thesis: await for stateless, spawn for long-running.

The Negotiation Machine — vendors reply on their own schedule over days. No function can wait that long. Each active deal gets its own state file:

{
  "negotiation_id": "cursor-2026-04",
  "vendor": "Cursor",
  "round": 3,
  "thread": [...],
  "leverage_used": ["competitor_mention", "annual_commit"],
  "status": "awaiting_reply"
}

Machine loops every 5 min: load state → IMAP poll → Claude classifies replies (accept | counter | stall | reject) → draft counter using past won deals as leverage → SMTP send → atomic state write → Photon update if milestone → sleep. Survives kill -9 mid-round and resumes cleanly from the state file.

The Dashboard — Next.js + Supabase Realtime. Live Machine list with uptime counters, active thread previews, savings ticker, and per-Machine drill-down showing the full state file and Claude reasoning trace. Founders can approve, pause, or kill Machines directly from the UI.

Photon — wired into both layers. Three message tiers (silent / FYI / decision-needed) so the founder is only pinged when human input is actually required. The agent initiates on its own schedule — it's not a chatbot, it's a process narrating its own work.

Challenges we ran into

Stateless vs long-running boundary. First instinct was to make everything a Machine. Wrong — compliance scoring an $89 dinner is a pure function. Forcing it onto a VM would be theater. Only negotiation genuinely needs days of memory.

State corruption from mid-write kills. Naive json.dump() left half-written files on crashes. Fixed with atomic writes (temp file → fsync → rename). Now the kill-and-resume demo actually works.

IMAP is a minefield. Gmail rate-limited us within an hour. Switched to fresh connections per poll and moved outbound to Resend to avoid spam folders.

Vendor replies don't come in clean categories. "Let me check with my manager" is neither accept nor reject. Built a Claude classifier outputting {class, confidence, extracted_offer} with a stall-branch that nudges politely.

Photon message fatigue. First version pinged on every Machine event. Within an hour we'd become the annoying agent. Three-tier messaging fixed it — restraint was the hardest UX problem.

Realtime race conditions. Fast bursts triggered duplicate Machine spawns. Added an active_machines table with unique constraints so the orchestrator can't double-spawn.

Accomplishments that we're proud of

kill -9 and resume — killing a Machine mid-negotiation on stage, booting it, watching it read state and keep going. Persistent state is real.

End-to-end autonomy — founder taps "Y" once, LEGR handles 40+ hours of back-and-forth, texts the receipt.

Clean architectural splitawait agent() vs spawn machine(). The right pattern for agent systems, not just our hack.

Photon as active participant — agents initiate, narrate, escalate only when needed. Actual conversational agency, not a notification firehose.

Real-time dashboard with live Machine uptime, state drill-downs, and savings ticker.

Caught real waste during testing — including a wrong-model routing pattern in our own codebase.

What we learned

Machines aren't just "longer functions." Crash recovery, atomic writes, idempotent loops, and human-in-the-loop escalation are first-class concerns from day one.

The orchestrator pattern changes once Machines exist. await and spawn are architecturally different calls — one blocks, the other hands off to a process that may outlive the caller.

Agent UX is a restraint problem. Knowing when not to post is harder than posting. Message tiering was the single biggest UX improvement.

Claude negotiates better with concrete leverage. Feeding past won deals as context made counter-offers dramatically sharper.

Persistent state is a product feature. Showing a founder "round 3, here's exactly what leverage I used" builds trust no dashboard metric can.

What's next for LEGR

Near-term:

  • Seat Reclamation Machine — Playwright on a real VM with persistent cookies, logs into vendor admin panels, executes cancellations with screenshot receipts.
  • Always-on Usage Signals Machine — continuous per-employee × per-tool activity time series.
  • Parallel negotiations with a shared leverage store — wins from Notion become ammo for Linear.

Medium-term:

  • Founder memory — persistent model of each founder's tolerance, vendor preferences, and burn runway.
  • Vendor intelligence graph — aggregate (anonymized) negotiation data to know what discounts are actually achievable.
  • One-click model routing middleware — LEGR doesn't just recommend Haiku, it deploys the router.

Long-term: The first tool a startup connects, and the last finance tool they need before they hire a real CFO. The architecture (short-lived agents + long-running Machines + Photon) generalizes to legal ops, vendor management, HR compliance. Finance is the flagship; the real bet is on the shape of the system.


Built with Dedalus Machines, Claude, and Photon. Autonomous finance agents for startups.

Built With

Share this project:

Updates