The story in one breath
Every month, someone at a property company opens a thousand bills and asks the same four questions: Is this ours? Did we already pay it? Is this number normal? Do we trust who sent it? Lintel asks those questions on every bill, in code, in seconds. The model reads the bill. Code decides whether it gets paid. Agents do the legwork. A person owns the exceptions.
Fills 2 full-time property AP and utility-audit seats on a 250-property portfolio.
- Live App: https://lintel-brown.vercel.app/
- GitHub Repository: https://github.com/Pranillama/lintel
- Convex Hackathon Log (
hackathon.md): https://github.com/Pranillama/lintel/blob/main/hackathon.md - CREAO Investigator Agent (
cfc435a7-6765-4fb3-8c00-8d55d3c7af52): https://app.creao.ai/agent/install/G5fE3N3q - Figma Wireframe : https://www.figma.com/design/HWk2SSTzH0XoD925fcukB3/Lintel-%C2%B7-AP-workflow-wireframes?node-id=2-27&t=aw5kaIUKMOvz7mPY-0
Inspiration — Why "AI that pays bills" is dangerous
Paying utility and contractor bills across hundreds of properties takes an operations team two full days every month (sourced from DSD Cohort's Property Bill Automation brief, where a property CTO faced a $10M software overhaul over this exact bottleneck).
The hard part is not "reading PDFs." The hard part is that every bill carries a quiet way to lose money:
| What goes wrong | What it looks like on paper | What a tired human does |
|---|---|---|
| The double bill | Same trash pickup, new invoice number (RW-10021 vs RW-99201), $6 different ($686 vs $680) |
Pays it. The number looks familiar. |
| The leak | A water bill 3.8x normal (160 CCF vs 42 CCF average) at the exact same rate per CCF |
Pays it. Water bills vary, right? |
| The mystery address | "1880 Lombard #B" when the building (1880 Lombard St, Units 101–408) has no unit B |
Guesses, or lets it sit until late fees hit. |
| The stranger | A contractor you have never paid, over the auto-pay limit, with active liens | Pays it because the work order looks real. |
Software that "uses an LLM to pay bills" makes this worse: now a probabilistic model is guessing on money.
Lintel's core architecture is the split:
- AI does the reading, investigating, and voice explanation.
- Pure deterministic TypeScript does every check that touches money, with zero model calls.
- A person owns every exception.
- Every step is written to a SHA-256 hash-chained audit log, while a counter on screen never moves:
AI DECISIONS ON MONEY: 0.
What it does
Lintel is an autonomous property bill and accounts-payable system of work modeled across a 5-property San Francisco & Berkeley portfolio (Bayview Commons, Telegraph Hill Lofts, Shattuck Student Living, Marina Gate Retail Plaza, and Soma Tech Atrium standing in for a 250-property book):
- Receipt-Story Landing (
/) & Routed Inbox (/inbox):- On
/, a live thermal receipt prints a bill's journey line by line as rules check off andAI DECISIONS ON MONEYstays at0. - On
/inbox, the operator (Dana, our AP lead persona) doesn't face a stack of PDFs—she sees only the rows that need a human (Needs you$6,100.00 · 2· Blocked$680.00 · 1· Cleared$2,290.40 · 1·✓ Audit trail intact).
- On
- Claude Multimodal Reader (
claude-haiku-5-5):- Upload any utility PDF, photo, or invoice (or enter fields directly). Claude reads 7 structured fields, returning a per-field confidence score and the exact source snippet from the document, while storing the original file in Convex so operators can compare side by side. If any required field is below
0.85confidence, the bill waits for a person.
- Upload any utility PDF, photo, or invoice (or enter fields directly). Claude reads 7 structured fields, returning a per-field confidence score and the exact source snippet from the document, while storing the original file in Convex so operators can compare side by side. If any required field is below
- Pure Deterministic Rules Engine (
src/engine/decide.ts,src/match/matchBill.ts):- Pure TypeScript with zero network calls and zero model calls. Matches property and vendor by exact account (
1.00), learned human alias (1.00), or street/unit address scoring, then checks exact duplicates, fuzzy duplicates (±2%amount within 7 days), line-item sums, usage and amount spikes (+25%hold line against the saved 90-day baseline), vendor trust, and property policy limits. - Outputs Approved (approved for payment with its rail: utility portal or ACH), Needs review (routed to
OPERATORorVP_FINANCE), or Blocked (no pay button exists in the DOM).
- Pure TypeScript with zero network calls and zero model calls. Matches property and vendor by exact account (
- One-Click Human Teaching (
1880 Lombard #B->1.00 HUMAN_ALIAS):- When Bayline Plumbing bills
"1880 Lombard #B"($420.00), Lintel caps confidence at0.80because Telegraph Hill Lofts has no unit#B. Dana clicks Assign to Telegraph Hill Lofts once. Lintel records that alias in Convex and re-evaluates the rules. When the next#Bbill ($390.00) is uploaded, it matches at1.00(Matched by what a person taught it) and clears on its own.
- When Bayline Plumbing bills
- CREAO Exception Investigator (
cfc435a7-6765-4fb3-8c00-8d55d3c7af52) with Claude Sonnet 5.5 Fallback:- Whenever a bill is held or blocked—such as EBMUD's
$5,680.00water bill (160 CCFvs42 CCFaverage,+281.0%usage at a flat rate)—Lintel schedules a background run on our hosted CREAO agent. The agent pulls the property's 90-day history and drafts the plumber work order or vendor dispute email. Remove the CREAO agent, and the autonomous exception-investigation workflow stops working.
- Whenever a bill is held or blocked—such as EBMUD's
- Live CRS Credit Bureau Vendor Check (
verifyVendor):- Unknown contractors over policy limits trigger a live background check against the Stitch Credit / CRS Sandbox API (official test persona
P08, Priya Venkatesan). When Apex Rapid HVAC LLC submits a$3,450.00invoice, CRS returns a $12,300 civil judgment and a $7,450 state tax lien, and Lintel immediately stamps it BLOCKED. If CRS is disabled or unreachable, Lintel holds the bill as unverified—never treating "couldn't check" as a pass.
- Unknown contractors over policy limits trigger a live background check against the Stitch Credit / CRS Sandbox API (official test persona
- "Talk to Lintel" — Cartesia Owl Voice Reviewer (
src/voice/owl.ts,src/voice/reviewerAgent.ts):- A custom lime owl mascot sits in the corner of the desk with paper eyes, blinking lids, sleepy idle state (
IDLE_SLEEP_MS = 8000), and a beak driven in real time by Web Audio RMS playback levels (timeDomainRms->beakOpenFromLevel). - Powered by a Cartesia Managed Voice Agent (
agent_uVkeKQtpoKmCKtCxGEDZpr,Skylarvoice +claude-sonnet-5) connected over bidirectional WebSockets (@cartesia/line). - Operators can ask "What needs me today?", "Why is the EBMUD bill held?", or "Open the Bayline bill." The owl calls 3 read-only Convex HTTP webhook tools (
list_open_bills,find_bills,get_bill_explanation) and 2 client browser tools (get_selected_bill,show_bill) to navigate the UI and explain the engine's exact numbers—while architecturally possessing zero write tools to approve, reject, or pay a bill.
- A custom lime owl mascot sits in the corner of the desk with paper eyes, blinking lids, sleepy idle state (
- Tamper-Evident SHA-256 Audit Log (
/audit) & Code-Generated Policy (/policy):- Every action by Lintel's rules, Claude, CREAO, CRS, or a human appends a SHA-256 hash-chained row (
prevHash -> hash) in Convex. Clicking Verify fingerprints recomputes the entire chain in the browser. The/policypage is generated directly from the same TypeScript constants (src/seed/policy.ts) that the engine executes.
- Every action by Lintel's rules, Claude, CREAO, CRS, or a human appends a SHA-256 hash-chained row (
How we built it
- Frontend: Next.js 16 (App Router, React 19, TypeScript) featuring the receipt-story landing (
/), routed AP inbox (/inbox), side-by-side PDF comparison drawer, SHA-256 audit verifier (/audit), live policy view (/policy), and the Web Audio RMS-animated Cartesia owl mascot (src/components/app/VoiceReviewerCard.tsx,src/voice/owl.ts). - Backend & Real-Time Ledger (
Convex): 9 relational tables (properties,vendors,vendorAccounts,history,bills,auditEvents,payments,aliases,investigations) inconvex/schema.ts, Convex file storage for uploaded PDFs, scheduled CREAO investigations (ctx.scheduler.runAfterwith 4-second slot spacing), atomic state + audit mutations, and authenticated HTTP action endpoints (convex/http.ts) for Cartesia voice tool calls. - AI & Sponsor Stack:
- Anthropic:
claude-haiku-5-5(messages.parse+zodOutputFormat) for document extraction with snippets and confidences;claude-sonnet-5-5for investigator fallback. - CREAO AI: Hosted Exception Investigator agent (
cfc435a7-6765-4fb3-8c00-8d55d3c7af52) invoked from Convex background actions (src/integrations/creao/client.ts). - CRS Credit API: Live Stitch Credit sandbox (
POST /users/login+POST /pp/fcrablj/dataand criminal/eviction checks) mapped to official sandbox personaP08(src/integrations/crs/verifyVendor.ts). - Cartesia: Managed Voice Agent (
agent_uVkeKQtpoKmCKtCxGEDZpr) streaming low-latency WebSocket audio in the browser with custom domain keyterms (EBMUD,PG&E,SFPUC,Recology,Bayline Plumbing,Shattuck Student Living). - SpaceXSI (Cursor & Grok Bot): Built across 3 parallel engineering lanes using frozen
/contextcontracts, Cursor cloud agents, and a 6-agent Grok Bot fleet coordinating in Slack (#collaborative-context). - Figma: Used Figma Wireframes to design the frontend of the application
- Anthropic:
Sponsor Track Alignment
- Hyphenate — Autonomous Systems for Finance: Lintel is an autonomous AP desk, not a chatbot. It clears, holds, and blocks bills on its own, routes
$5,000+exceptions toVP_FINANCE, learns property aliases from one human click, and keepsAI DECISIONS ON MONEYat0. - Convex — Best use of Convex: Convex is the entire backend (
https://incredible-cobra-296.convex.cloud). LiveuseQuerysubscriptions stream receipt steps as they land, mutations atomically commit bill verdicts + learnedHUMAN_ALIASrules + SHA-256auditEvents,ctx.storageserves original bill PDFs,ctx.scheduler.runAfterspaces CREAO runs, andhttpRouter(convex/http.ts) serves Bearer-authenticated JSON to our Cartesia voice agent. Full details in/hackathon.md. - CREAO AI — Best Build on CREAO: Every held or blocked bill schedules a live run on our CREAO Exception Investigator (
cfc435a7-6765-4fb3-8c00-8d55d3c7af52, install link), which analyzes the 90-day baseline and drafts the maintenance work order or vendor dispute email with its run ID displayed on the card. - CRS Credit API — Best Use of CRS API: Unverified contractors trigger a live Stitch Credit sandbox check (
P08), catching a$12,300civil judgment and$7,450state tax lien on Apex Rapid HVAC LLC and blocking payment before a dollar moves. - Cartesia — Voice AI: Our corner owl mascot (
Talk to Lintel) streams real-time voice explanations via Cartesia's Managed Agent WebSocket API, driving the owl's beak from live Web Audio RMS samples, navigating bills on screen via client tools (show_bill,get_selected_bill), and answering questions from live Convex webhook tools without ever touching write permissions. - Anthropic — Claude for Public Benefit: Protects student and residential housing operating budgets (modeled on Berkeley's Shattuck Student Living) by catching
+281%water main leaks immediately and enforcing strict< 0.85confidence holds so an LLM never guesses with housing funds. - Microsoft — Built for the Real World: Grounded in a real multi-property AP pain point with measurable per-batch outputs (dollars cleared, held, and blocked) and clean payment instructions (
UTILITY_PORTAL/ACH) ready to plug into production rails. - SpaceXSI — Make it Legendary with SpaceXSI: Built by a 3-person team pairing Cursor (frozen TypeScript contracts in
/context+ parallel cloud agents) and Grok Bot (Jam,Sprout,Mochi,Eng Head,Bolt,Hoot) in Slack.
Challenges we ran into
- Keeping AI out of the money path while making it maximally useful: It is tempting to let an LLM output
status: "APPROVED". Instead, we forced Claude into a strict perception schema (ExtractedBillwith per-field confidences and verbatim snippets), keptdecide()100% deterministic TypeScript verified by offline golden tests, and gave our Cartesia owl reviewer read-only webhook/navigation tools so even voice commands cannot bypass policy. - Spacing burst CREAO runs from Convex: Uploading four bills in a batch initially triggered upstream HTTP 429 rate limits on CREAO. We built a slot-reservation scheduler (
src/agents/investigator/spacing.ts+ctx.scheduler.runAfter) that spaces runs 4 seconds apart in the same transaction that writes thePENDINGbrief. - Syncing the owl mascot's beak to live Cartesia WebSocket audio: Raw PCM frames arrive over the Cartesia WebSocket in bursts. We wired a Web Audio
AnalyserNodeinto the playback queue and mapped time-domain RMS (timeDomainRms->beakOpenFromLevel->smoothLevelinsrc/voice/owl.ts) so the owl's beak and blink rate react naturally to Skylar's voice while respectingprefers-reduced-motion.
Accomplishments that we're proud of
- Zero fake data in the desk: Everything in
/inbox, the bill pages, the side-by-side PDF viewer, the Cartesia owl voice reviewer, and/auditis live Convex data produced by the real pipeline. - One-click alias learning that compounds: Assigning
"1880 Lombard #B"once turns a0.80hold into a1.00auto-match on the very next upload (BILL-104B-bayline.pdf). - Cryptographic receipts for every step: Every rule check, model read, CRS background check, CREAO brief, and human click is SHA-256 hash-chained and verifiable in one click.
What we learned
- Trustworthy financial autonomy comes from strict boundary discipline: probabilistic models at the edges (reading messy PDFs, drafting follow-ups, speaking explanations out loud) and deterministic, auditable code at the core.
- Designing a multi-agent repo around frozen TypeScript contracts (
src/types/bill.ts,src/seed/policy.ts) let three teammates, Cursor agents, and Grok Bot ship a full-stack system with 115+ passing tests in 36 hours.
What's next for Lintel
- Direct ACH & Utility Portal Execution: Connecting the approved payment instruction (
ACH/UTILITY_PORTAL) to live bank and utility portal rails behind the existing approval contract. - Inbound AP Email Forwarding: Piping
ap@<portfolio>.comattachments straight into the Convex intake action so bills land on the desk the moment a vendor emails them. - Portfolio-Wide Benchmarking: Comparing per-unit water, electric, and trash costs across all 250 properties to catch slow leaks before they cross the
+25%single-bill spike threshold.
Built With
- anthropic
- cartesia
- claude
- convex
- creao-ai
- crs-credit-api
- cursor
- figma
- grok-bot
- nextjs
- react
- tailwindcss
- typescript
- vercel
- vitest
- web-audio-api