Inspiration
We receive dozens of offering memorandums every month for light industrial properties: small commercial buildings rented to electricians, HVAC contractors and cabinet shops. Almost every off-market email pitches an aggressive pro forma. The broker assumes zero vacancy and applies the seller's old tax bill. We spend hours tearing down those numbers to find the actual cap rate (the annual return on the purchase price). Our process requires adding a management fee alongside a realistic capex reserve. We then model the Prop 13 tax reset just to see if the property clears our debt coverage floor. Most deals get passed on within the hour, and a pass is only "not at this price"; nobody has the hours to re-run fifty old passes when a seller cuts a price.
When a building finally clears our underwriting, the diligence phase begins. Chasing down the property condition report to check for ponding on the flat built-up roof takes days. Then we need the Phase I assessment to identify environmental risk from automotive tenants. Drafting emails to verify CAM reconciliations and review lease rollover schedules consumes the rest of the week. We built DealSieve to do the triage, hold a price on every pass, and manage the follow-up questions. Our team now spends its time pricing the basis.
What it does
DealSieve ingests broker emails (with offering-memorandum attachments), Telegram messages, and pasted URLs. A Strands Acquisition Agent extracts claims with per-fact provenance. It hands off to deterministic tools that resolve the property to one canonical opportunity, reconcile the claims into working values, and run a Decimal-precision underwriting engine under an immutable investment policy (property-tax reset, vacancy floor, management fee, capex reserve, then six hard gates: tenant count, tenant concentration, absolute price cap, LTV, normalized cap rate, DSCR). The engine classifies the result DEAD, WATCH, NEAR, or REVIEW. For anything short of REVIEW, it solves a bisection to find the viability frontier: the maximum price at which every economic gate would pass, noting which gate is binding.
An independent Skeptic Agent (a second Strands agent with no tools and structured output only) is invoked if the deal looks clean on paper. It flags unsupported items in the record such as roof age, a Phase I environmental report, and CAM reconciliation. It drafts an information request and prompts a human on Telegram for approval.
If approved, the request is delivered to the broker. The broker replies with a Property Condition Report containing photographs. A third Strands agent, the Inspector Agent, reads the text and visually inspects embedded photos. DealSieve automatically re-underwrites on the all-in basis. Unanswered requests are followed up on a policy cadence. If the broker goes dark, the loop stalls and alerts the human.
DealSieve also remembers the buyer's own decisions. Every pass, price and approval is written to a decision memory (Amazon Bedrock AgentCore Memory, with a local store as the fallback), and the next alert on the same building quotes it back: e.g. "You previously: passed at $1.29M."
The frozen policy also takes the emotion out of the decision. A building the buyer has fallen for has to clear the same numbers as every other package, under a policy version the engine records with every run, so the system never talks anyone into a bad buy.
How we built it
Workstreams against a shared contracts document (docs/CONTRACTS.md), so the finance engine, persistence layer, Strands agent layer, diligence loop, API/notifications, and dashboard could be built concurrently against fixed Pydantic schemas (dealsieve/schemas/core.py) without stepping on each other:
Finance (dealsieve/underwriting/): pure, tested functions on Decimal — all-in basis underwriting (total_acquisition_cost = price + closing_costs + immediate_capex), normalization, financing, stress testing, gates, and bisection viability solver. Persistence (dealsieve/persistence/): SQLite in WAL mode; events, underwriting runs, and document analyses are immutable; concurrency-safe deal/event sequence allocation with BEGIN IMMEDIATE (R10); message claiming (R4); deduplication constraints. Agents (dealsieve/agents/, dealsieve/models/): three specialized Strands agents — (1) Acquisition Agent with deterministic code-gated tools, (2) Skeptic Agent for second-opinion risk audit, and (3) Inspector Agent with multimodal vision analyzing inspection PDFs and photos. A custom CLIModel Strands provider supports local CLIs (claude, codex, agy), and ScriptedModel replays recorded turns for deterministic offline demos and tests. Diligence & Delivery (dealsieve/diligence/, dealsieve/outbound/): deterministic screen blocking unauthorized offers or money language, follow-up cadence advancement, keyword-family answer matching, stall detection, and RFC 822 .eml delivery backends. Memory (dealsieve/memory/): decision memory behind one interface, Amazon Bedrock AgentCore Memory in AWS and a local store offline, read by the Skeptic and quoted in every alert. API/notifications (dealsieve/api/, dealsieve/notifications/): FastAPI surface, console and Telegram notifiers with inline-keyboard approval (the alert carries the actual draft email), and the dealsieve/agentcore_app.py AWS Bedrock AgentCore entrypoint. Dashboard (frontend/): Vite + React + TypeScript + Tailwind — overview watchlist sorted by distance to viability, and a deal-detail view with the broker-vs-DealSieve comparison table, viability frontier, diligence tracker, unified correspondence thread, document analysis with photo lightbox, and pending drafts.
Challenges we ran into
Keeping the model out of the arithmetic while letting it drive the workflow was a primary design challenge. LLMs often return plausible but incorrect calculations for metrics like cap rates. We addressed this by making every deterministic step a tool call with preconditions enforced in code. For example, notify_human returns {"skipped": "no threshold crossing"} unless the preceding underwriting run changed the status, and request_price_adjustment calculates the credit needed from the viability frontier. A pipeline-level safety net performs any step the model skips. A second challenge was ensuring reliability against network flakiness during recording. The ScriptedModel replays recorded turns with zero network calls, allowing the story to reproduce offline. The same code path runs against a live CLI or Bedrock by changing an environment variable.
Accomplishments that we're proud of
A viability solver that computes a specific, monitorable target price for rejected deals. A tool-gated multi-agent system where the properties that make a hackathon demo scary — the model hallucinating a pass, doing unchecked arithmetic, or double-notifying a human — are structurally impossible. An end-to-end 3-act story (WATCH -> REVIEW -> Diligence & Condition Report -> Capex adjustment & price-credit negotiation) fully tested (tests/e2e/test_watch_to_review.py and tests/e2e/test_diligence_loop.py) and reproducible offline in 3 seconds. Hard policy and guardrails in code, not in prompts: 493 tests cover gate boundaries, the amortization schedule, the property-tax reset, bisection convergence on the viability frontier, stress scenarios, identity resolution, evidence-conflict preservation, multimodal document inspection, and the diligence follow-up loop.
What we learned
Deterministic-first agent design improves testability. Because the arithmetic and workflow gates are plain Python functions, the underwriting engine and tool-gating logic are unit-testable without mocking a model. The model layer is swappable to a scripted replay for CI and offline demos. We found that a custom Strands Model provider is a small surface area, handling request rendering and JSON response parsing. Building one against local CLI tools increased iteration speed by removing the need for API keys early in development.
What's next for DealSieve
Next steps include monitoring broker emails at mailbox scale, pulling listings from crawl and API sources, and building an off-market owner universe from assessor data. We plan to add loan-rate and seller-financing monitoring as additional axes on the viability-frontier machinery. Market-rent and transaction comps will help check normalized NOI against external data. The core primitive of persistent opportunity state, deterministic policy, and monitored thresholds could also be applied outside commercial real estate to small-business, franchise, private-credit, and equipment acquisitions.
Log in or sign up for Devpost to join the conversation.