Architecture

Three-Plane Separation

The system is divided into three planes with strict boundaries:

PlaneResponsibilityExamples
DeterministicBinary correctnessNormalization, dedup, commute calc, hard filters, scoring, state machine, idempotency
AgenticJudgment & interpretationNeighbourhood assessment, qualitative ranking, shortlist synthesis, message drafting
HumanExternal side-effect authorityApprove/reject realtor messages

Component Ownership

DirectoryOwnsRules
contracts/Pydantic models for all domain typesNo business logic; pure data models with validators
workflow/State machine, step implementations, controllerOnly this layer changes workflow state
deterministic/Normalization, dedup, commute, filtering, scoringPure functions, no I/O, no LLM calls
agents/Agent interfaces, mock/ADK runtimesAgents produce typed outputs; never mutate state
tools/Mock external services (listings, maps, email)Only tool registry exposes tools; agents get read-only subset
persistence/SQLAlchemy models, database, repositories, UoWNo business logic; pure data access
security/Untrusted input wrapper, prompt injection scanner, redactionApplied at system boundaries
observability/Structured logging, audit events, tracing, metricsAll components emit events through this layer

Data Flow

  1. User creates search with preferences → persisted to SQLite
  2. Workflow engine executes steps sequentially with validated transitions
  3. Deterministic pipeline fetches, normalizes, deduplicates, scores listings
  4. Agent runtime (mock or ADK/Gemini) provides qualitative assessments
  5. Approval gateway gates all external actions behind human review
  6. Audit logger records every event across all planes

Trust Boundaries

#BoundaryProtects
1Untrusted Input → AgentAgent prompt integrity
2Agent → Workflow StateState consistency
3Agent → External ToolsSide-effect safety
4Human → Approval GatewayAuthorization
5Approval → ExecutionPayload integrity
6Execution → External ServiceIdempotency
7All Components → Audit LogNon-repudiation

Agent Runtime Isolation

The AgentInterface protocol ensures the workflow engine never depends on a specific LLM:

class AgentInterface(Protocol):
    async def research_neighbourhood(...) -> NeighbourhoodAssessment: ...
    async def evaluate_qualitative_fit(...) -> dict: ...
    async def synthesize_shortlist(...) -> dict: ...
    async def draft_realtor_message(...) -> dict: ...

Mock runtime: Deterministic canned responses. No API keys. CI, demos, development.
ADK runtime: Live Gemini 2.5 Flash via Google ADK. Same contracts, same validation, same security boundaries.


Threat Model

10 documented threats across 4 categories:

CategoryThreatsControls
Prompt Injection3Input wrapping, system prompt defenses, scanner
Agent Misbehavior3Schema validation, no tool access, output repair
Authorization Bypass2Approval gateway, payload hash binding
Operational2Idempotency, crash recovery, audit trail

Full threat model →