Assets

Seven years of production infrastructure. No prototypes. No demos. Each system handles real volume every day. This page peels back the layers — from the surface-level architecture down to the code that runs at 3 AM.

The Onion: System Architecture

Four business units. Three AI agents. Dozens of background services. The architecture looks simple from the outside — leads come in, conversations happen, deals close. But each layer you peel back reveals another system: background research agents, tonality calibration, customer profiling, inventory polling, compliance gates, ILS integrations, and the governance layer that keeps it all from exploding.

Layer 1: Lead Sources (ILS + Direct) Zillow Apartments.com YouGotListings paid syndication Craigslist direct ads Building partners API feeds Google Ads organic search S2 Capital partner feed Direct referrals walk-ins Layer 2: Lead Intake + Qualification Sniff Test 8 qualification checks ZIP demographics • credit estimate Customer Profiler Google the lead (2-3 signals) income estimate • household size Background Agent web search on renter LinkedIn • public records • news TCPA Gate DNC registry check opt-out suppression list Layer 3: Conversation Engine (The Agent Brain) Agent Brain (Tool-Use LLM) Claude Opus primary • Gemini fallback No decision trees. Full context window per turn. Post-generation guardrails. Tonality calibration. Socratic question framework in all sales conversations. Tools the brain calls: inventory_search(city, budget, beds) building_lookup(name | address) schedule_tour(building_id, date) web_search(renter query) commission_check(building_id) escalate_to_human(reason) Layer 4: Background Services (Run 24/7) Inventory Poller 10K+ buildings/day voice calls + API Follow-up Engine every 15 minutes drip cadences Stale Data Detector 72-hour threshold priority re-call Lead Scoring recalc vs fresh inventory nightly Compliance Audit every outbound msg TCPA + DNC Red Team Agent adversarial tests continuous Layer 5: Infrastructure + External APIs PostgreSQL Redis RabbitMQ GKE Cluster Cloud Build Mutagen Sync Mac Studio M4 Pro Twilio SMS Bland AI Voice Claude API Gemini API Assurant Stripe Gmail/Drive Asana

The Conversation Engine: How the Agent Brain Works

The agent is not a chatbot. It's a tool-use LLM orchestrator with a sales doctrine encoded in its system prompt. It doesn't follow decision trees — it reasons about each message, calls tools to look things up, and generates responses calibrated to the conversation state. Here's the actual code that handles an inbound message:

# From ken.py — the actual production insurance agent

class KenAgent:
    """
    Ken - The Jamboree Insurance SMS Agent

    Handles:
    - Initial outreach (WE message THEM)
    - Response classification (20+ intents)
    - Info gathering (address, move-in, email)
    - Quote delivery (ONLY after Assurant API)
    - Follow-up sequencing
    - Objection handling
    """

    def handle_inbound(self, lead, message):
        """
        Handle an inbound message from a lead.

        Returns: (response, event, action_needed)

        action_needed can be:
        - {"action": "generate_quote",
           "address": "...", "city": "..."}
        - {"action": "escalate_to_human",
           "reason": "..."}
        - None
        """
        # Classify the message
        classification = classify_message(message)

        # ALWAYS extract statements for later
        # urgency building
        self._extract_statements(lead, message)

        # Handle by intent
        response, event, action = \
            self._handle_intent(
                lead, classification, message
            )

        # Process state transition
        if event:
            self.state_machine.process_event(
                lead, event
            )

        return response, event, action

The key design decision: action_needed. The agent brain decides what to do, but external services execute the action. When the agent needs a quote, it doesn't call Assurant directly — it returns {"action": "generate_quote"} and the orchestrator handles the API call. This separation means the agent can be tested without live API calls, and the Assurant integration can change without touching the agent logic.

The Tonality System

The agent doesn't just generate text — it calibrates tone based on the conversation state and the lead's profile. The CLAUDE.md encodes the doctrine:

# From Workflows/ken-insurance/CLAUDE.md

## Tone: DIRECT, NOT INQUISITIVE

WRONG: "Hey Sarah, are you moving in Austin soon?
        Do you need help?"

RIGHT: "Hey Sarah - we got flagged that you're
        moving into a rental in Austin. I'm reaching
        out to get you set up with renters insurance
        — it's required before you can get keys
        in Texas."

Key principles:
- TELL (with an out if wrong)
- DRIVE to next action
- Emphasize REQUIREMENT not optional

The tonality isn't random. "Tell, don't ask" converts at 2x the rate of inquisitive opening messages. This was measured across thousands of conversations — the macro loop identified the pattern, and it became a rule in the CLAUDE.md.

The Socratic Sales Framework

Every sales conversation follows the Socratic pattern: ask questions where the only honest answer moves the deal forward.

# From Workflows/apartment-locator/CLAUDE.md

## INVERT THE BURDEN OF PROOF

Constantly lower the bar so saying NO
becomes the insane option.

With renters:
  "At a minimum, if nothing else worked out,
   could you make this work?"

With buildings:
  "I've got a renter ready to sign.
   Want the commission or should I send
   them across the street?"

Each question has only one honest answer.
The logical conclusion is inescapable.

Inventory Intelligence: How We Know What's Available

The apartment database isn't scraped from listing sites. It's built from three independent data streams that cross-reference each other. Here's how the polling works:

Three Independent Data Streams Stream 1: Automated Voice Calls Bland AI calls 10K+ buildings/day Extracts: vacancy, commission %, specials, app requirements, contacts $0.09/min per call Stream 2: ILS Platform APIs Zillow API • Apartments.com feed YouGotListings • RentPath Listing prices, photos, unit types Often stale ($280 avg delta) Stream 3: Transaction History Actual closed deals + payments Commission received vs promised Revenue per building over time Ground truth signal Building Intelligence Database PostgreSQL + embeddings Cross-referenced, freshness-scored, revenue-ranked Commission Freshness How recently verified? Vacancy Confidence Voice-verified vs ILS-scraped Revenue Ranking Actual $ earned per building The stale data detector triggers priority re-calls when any building hasn't been reached in 72 hours. ILS data is noise. Voice calls are signal. Transaction history is truth.
# From the production FastAPI lifecycle — automated jobs

# Follow-up job every 15 minutes, all night
scheduler.add_job(
    process_followups,
    IntervalTrigger(minutes=15),
    args=[db, sms, ken],
    id='followup_job',
)

# Expiration job daily at 6 AM
scheduler.add_job(
    expire_past_move_ins,
    CronTrigger(hour=6, minute=0),
    args=[db],
    id='expiration_job',
)

# TCPA gate: reject leads on suppression list
if await compliance.is_suppressed(lead.phone):
    raise HTTPException(
        status_code=409,
        detail="Phone is on suppression list"
    )
if await compliance.is_on_dnc(lead.phone):
    raise HTTPException(
        status_code=409,
        detail="Phone is on DNC registry"
    )

Ken: The Insurance Sales Agent

SMS-based renters insurance sales. HO4 renters insurance via Assurant (Fortune 500 carrier). The key constraint: we outbound to them — they don't come to us. We get leads from partner buildings. We have: first_name, phone, city, state. We don't have: exact address, exact building, move-in date. The agent has to extract all of that through conversation before it can quote.

# Ken's lead lifecycle state machine

NEW → CONTACTED → ENGAGED → INFO_GATHERED
      → QUOTED → PAYMENT_SENT → CONVERTED
                    │
              NO_RESPONSE → FOLLOWUP_1 → FOLLOWUP_2
              → FOLLOWUP_3 → EXPIRED
                    │
              OPTED_OUT (terminal)
              HUMAN_ESCALATION

# Drip cadence: 4h → 24h → 48h → 5d → 7d → 14d

# Intent classification: 20+ intents
# Each one forged by the red team

STOP           → opt out immediately
YES_INTERESTED → ask for address
PRICE_QUESTION → ask address first (NEVER quote before API)
ALREADY_HAS    → verify $100k liability
WHO_IS_THIS    → explain we got flagged
IS_THIS_SCAM   → licensed, Assurant-backed, Fortune 500
FOXEN_MENTION  → explain waiver vs real insurance
GAVE_ADDRESS   → trigger Assurant API quote

The critical rule: NEVER hardcode prices. Prices come from the Assurant API based on address, coverage level, and dwelling type. The flow is: Outreach (NO PRICE) → Collect address → Call Assurant API → THEN show price. If the agent quotes before calling the API, the price is a hallucination. If too low, the renter signs, discovers the real price, cancels, and files a complaint. If too high, the renter walks. Either way: legal liability.

# Lead intake endpoint — actual FastAPI code

class LeadCreate(BaseModel):
    """New lead intake"""
    first_name: Optional[str] = None
    phone: str = Field(..., pattern=r'^\+1\d{10}$')
    city: Optional[str] = None
    state: str = Field(..., pattern=r'^(TX|IL|MI)$')
    move_in_date: Optional[date] = None
    source: Optional[str] = None
    partner_code: Optional[str] = None

@router.post("/leads")
async def create_lead(lead: LeadCreate, ...):
    """
    Create a new lead and trigger outreach.

    This endpoint:
    1. Creates the lead record
    2. Links to building if found
    3. Queues initial SMS outreach
    """
    # TCPA gate first
    if await compliance.is_suppressed(lead.phone):
        raise HTTPException(409, "Opted out")
    if await compliance.is_on_dnc(lead.phone):
        raise HTTPException(409, "DNC registry")

The Governance Layer: Hooks, Rules, and Scars

Eight hooks across four event types. They run deterministically — can't be skipped, can't be overridden. Each one exists because of a production incident. The CLAUDE.md files (1,334 lines across 7 files) encode every rule, every lesson, every scar.

# Hook architecture — 8 hooks, 4 event types

SessionStart:
  pre-session-read-state.sh
    → Loads deployment state, last session
    → Shows what's broken before you start
    → "READ THE ABOVE. Do NOT start work until
       you understand what is deployed, what broke,
       and what the last session did."

PreToolUse (Bash):
  pre-bash-safeguard.sh
    → Blocks DROP TABLE, TRUNCATE, DELETE FROM
    → Cleans stale git locks
    → "This hook NEVER prints instructions.
       It either BLOCKS or ALLOWS. That's it."

PreToolUse (SQL):
  pre-sql-bottomup.sh
    → Blocks aggregate queries before sampling
    → Warns on client_stage_progression (garbage)
    → "Classifiers lie. Summary fields are stale."

PostToolUse (Edit/Write):
  post-edit-lint.sh
    → Auto-lints Python after every edit
    → Blocks on syntax errors
    → Detects secret leaks

Stop:
  session-end-save.sh (126 lines)
    → Auto-saves session memory + git state
    → Detects deploys automatically
    → "Exit code: ALWAYS 0. Stop hooks should
       never block session exit."

  stop-fresh-eyes-check.sh
    → Logs unreviewed changes to debt file

  ralph-wiggum/hooks/stop-hook.sh (178 lines)
    → Autonomous loop controller
    → Intercepts session exit
    → Reads transcript for completion promise
    → Feeds prompt back in if work isn't done
    → Named after a Simpsons character because
      humor in infrastructure is how you stay
      sane at 2 AM
# The Ralph Wiggum autonomous loop — actual code

# When you try to exit, it checks: did you
# actually finish what you promised?

PROMISE_TEXT=$(echo "$LAST_OUTPUT" | \
  perl -0777 -pe \
  's/.*?(.*?)<\/promise>.*/$1/s')

if [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
  echo "Ralph loop: Detected completion."
  rm "$RALPH_STATE_FILE"
  exit 0
fi

# Not complete — feed the prompt back in
jq -n --arg prompt "$PROMPT_TEXT" \
  '{"decision": "block", "reason": $prompt}'

# The AI can't claim it's done unless it
# actually is. The loop is inescapable.

The Quoting Engine (PE-Backed Portfolio Company)

Before HomeEasy, I deployed this same architecture into a PE-backed portfolio company — commercial electrical distribution. AI trained on 180,000+ SKUs. Roughly 90% accuracy on quote generation. Built a CRM by mining 4,298 email threads — 657 net-new contacts extracted without anyone doing data entry.

The system found a $2.2M SUSOL arbitrage opportunity by identifying imported circuit breakers that could be sourced at 40% below the manufacturer's price. The AI read the emails. The AI found the pattern. The margin was sitting in the inbox for years.

This is the proof that the architecture works across industries. Different SKUs, same pattern. Same decomposition. Same onion layers. The apartment locating machine and the quoting engine are structurally identical — conversational intake, inventory match, qualification, fulfillment. The interface stays the same. The executors swap out.

The Decomposition

Alex Rampell at a16z wrote an investment memo about Fly Homes that broke a real estate transaction into its component services. I went three levels deeper.

Level 0: Monolith One human does everything Level 1: Special Teams Qualify Match Tour Docs Apply Follow-up Compliance Level 2: Atomic Tasks parse intent check budget query DB rank results draft msg check TCPA send log score escalate Level 3: Replaceable Executors LLM (Claude/Gemini) $0.003/task Voice AI (Bland) $0.09/min Human (FancyHands) $3-7/task Deterministic Code $0/task Four principles: Modularization. Replaceability. Sanctity. Operating leverage. The executor is interchangeable. The interface is sacred. Same architecture as Amazon's internal services. Applied to a leasing office.

By the Numbers

531 commits in 15 months (one person)
1,004,287 lines of Python
7 CLAUDE.md governance files (1,334 lines)
8 deterministic hooks (4 event types)
12 reusable skills
7 slash commands
119 session memory files
4 business units
3 AI agents in production
30,000 leads/month
97% contribution margins
$0.003 cost per conversation
0 human engineers