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.
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:
# 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.
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