# Project export: Executor AI

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2026
- Tagline: Executor AI: the AI agent that helps executors avoid costly legal and financial mistakes, saves time, and surfaces what you don't know
- Devpost: https://devpost.com/software/executor-ai
- GitHub: https://github.com/s85rr25/executor-ai
- Team: 5 GitHub contributor(s) — Sherry Shen (30 commits), sameer (30 commits), Davyn Paringkoan (25 commits), alex (21 commits), Claude Opus 4.8 (1M context) (1 commits)

## Devpost submission (written by the team)

### Inspiration

We built Executor AI to help grieving families and busy executors navigate probate deadlines and reduce liability. Inspiration came from seeing how paperwork, missed notices, and tight time windows cause stress and legal risk for non-professional executors.

### What it does

Executor AI ingests estate documents (wills, deeds, bank statements), extracts structured estate state, runs a DeadlineAgent that surfaces urgent probate deadlines and liability risks, supports RAG-powered Q&A for executor questions, and drafts required letters and notices (creditor notices, appraisal requests, court filings).

### How we built it

Backend agent: Python FastAPI (agent/) that runs our agents, document parsers, and embedding flows. Frontend: Next.js + TypeScript (web/) for uploader, dashboard, and SSE streaming chat. Vector store & state: Redis (KV + vector sets) for estate state, document vectors, and retrieval. LLMs: Claude for reasoning and parsing; OpenAI embeddings for vectors. Observability: Phoenix/OpenInference spans around LLM/embedding calls. CI/dev scripts: Makefile to install, run, seed, and test the demo.

### Challenges we ran into

Reliable extraction from varied document formats (scanned PDFs, different templates). Encoding legal deadlines and rules (CA probate) precisely and defensibly. Balancing helpful automation with "never give legal advice" constraints — we surface actions but encourage attorney review where required. Streaming UX for long-form LLM outputs while validating structured responses (Pydantic/Zod).

### Accomplishments we're proud of

DeadlineAgent that codifies CA probate timing and proactively alerts before critical windows. End-to-end demo: upload documents → parsed state → RAG chat → drafted letters. Strong tracing around every LLM/embedding call for auditability and debugging. Voice-enabled chat via Deepgram — executors can speak questions and hear responses Research Agent that monitors for probate law changes weekly using Google News RSS, zero API keys required

### What we learned

Good prompts + structured validation (Pydantic + Zod) dramatically reduce hallucinations for extraction tasks. A small, well-modeled state graph (estate object + assets + tasks + alerts) makes reasoning and RAG far more reliable than ad-hoc documents. Observability (traces + spans) is essential when multiple LLMs and embedding calls interact; it speeds root-cause analysis. UX matters: clear action items and downloadable letters increase user confidence more than raw answers.

### What's next

Expand jurisdictional rules beyond California and add a policy layer for jurisdiction selection. Add richer document OCR/vision fallback for low-quality scans. Add role-based workflows (attorneys, co-executors) and audit logs for compliance. Tighten evaluation: automated Phoenix/Arize evals to track extraction precision and deadline recall. About the project Executor AI turns estate documents into an actionable estate state and gives executors a reliable assist: deadlines, risk alerts, Q&A, and letter drafts. We aimed to reduce missed deadlines and liability by combining robust extraction, a rules-driven DeadlineAgent, a ResearchAgent for latest news updates, and RAG. Ethical Considerations in Development Privacy & Data Protection Estate documents contain deeply sensitive financial, health, and family information. We architected the system to minimize data retention: documents are parsed once, embedded, and stored only as vectors in Redis. User estate state never leaves their Redis instance. We recommend client-side encryption for production deployments and access logs for audit compliance. Avoiding Legal Advice & Liability Risks The system deliberately stops short of recommending specific actions. Instead, it surfaces deadlines and flags rule violations, then directs executors to their attorney for decisions. The UI enforces this boundary by using phrases like "This requires your attorney's input" when an action involves legal judgment. We ensured Claude to refuse to give specific legal advice even when asked directly. Social Impact & Equity Probate is time-sensitive and expensive. By automating deadline tracking and letter generation, we lower the barrier for non-wealthy families to comply without hiring a probate attorney. However, the system requires internet access and assumes literacy in English and digital interfaces—future work should localize and explore accessibility for elderly executors.

## README (from the GitHub repository)

# Executor AI

> The AI that prevents executors from making expensive mistakes — by building a live
> intelligence graph of the estate and running a true agent that alerts *before* probate
> deadlines and liability triggers are missed.

Built for the Hackathon @ Berkeley 2026 (24-hour build).

## The problem
When someone dies, the **executor** — usually a grieving family member, not a lawyer — is
personally responsible for administering the estate: probate filings, asset inventory,
creditor notices, debts paid in the right legal order, taxes, and distributions. Miss a
deadline or pay out of order and the executor can be held *personally* liable. Families who
can't afford a probate attorney do this alone, spending ~180 hours and making expensive
mistakes nobody warned them about.

Executor AI is the expert in their corner: it reconstructs the estate from its documents
and tells the executor the next action *before* it costs them. California probate only, and
never a substitute for legal advice — for attorney-judgment questions it says so plainly.

## What it does
Sign in, create an estate, and upload a will, deed, bank statement, or creditor notice.
Claude parses each into a live estate-state graph. An estate-aware chat (text + voice)
answers questions grounded in *your* documents. A real agent — the **DeadlineAgent** —
proactively reasons over California probate law and tells you the next action before a
missed deadline costs you, and a second **ResearchAgent** watches weekly for probate-law
changes. Generated letters and emailed alert digests close the loop.

## Architecture
Polyglot, two services + shared Redis. Python is the brain, TypeScript is the experience,
Redis is the memory.

```
web/  (Next.js + TypeScript)  ── HTTP / SSE ──▶  agent/  (FastAPI + Python)
  auth · dashboard · chat · voice                 auth · documents · RAG chat
  Deepgram · Sentry                               DeadlineAgent · ResearchAgent
                                                  letters · email · Phoenix + evals
            └──────────────── Redis (KV state + vector search) ────────────────┘
```

## Stack
- **agent/** — Python · FastAPI · Anthropic (`claude-sonnet-4-6` across parsing, the
  agents, chat, and letters) · OpenAI embeddings · Pydantic · bcrypt auth · Resend email
  · Phoenix tracing + LLM-as-judge evals
- **web/** — Next.js 14 · TypeScript · Tailwind · Deepgram · Sentry · Zod
- **shared** — Redis: KV estate state + vector search for document retrieval, behind a
  store layer that supports Redis Cloud (cloud path in use), Upstash, or in-memory backends

## Repo layout
- [`CLAUDE.md`](CLAUDE.md) — working instructions for Claude / coding agents
- [`project_overview.md`](project_overview.md) — full design, data shapes, flows, demo
- [`hackathon_tracks_and_prizes.md`](hackathon_tracks_and_prizes.md) — tracks & sponsors
- [`docs/project_structure.md`](docs/project_structure.md) — implementation folders,
  ownership boundaries, and placeholder contracts
- [`docs/database.md`](docs/database.md) — Redis KV/vector contract and database setup
  checklist
- [`docs/workstreams.md`](docs/workstreams.md) — per-member start points and stable
  dependency boundaries
- [`team/`](team/) — per-member role briefs (Members 1–4)
- `agent/` — Python service · `web/` — Next.js frontend

## Getting started
```bash
# 1. Copy env files (won't overwrite if they already exist)
make env

# 2. Install all dependencies (uv for Python, npm for web)
make install

# 3. Start both services — agent on :8000, web on :3000
make dev

# 4. In a separate terminal: seed the demo estate
make seed
```

Fill in your API keys in `agent/.env` and `web/.env.local` after running `make env`.
Minimum to start: `ANTHROPIC_API_KEY` in `agent/.env`. The store defaults to
`STORE_BACKEND=memory`, so Redis Cloud is optional for local dev; voice (Deepgram),
email (Resend), and observability (Phoenix/Sentry) degrade gracefully when their keys are
unset — voice and email return previews instead of failing.

Phoenix tracing sends Anthropic, OpenAI embedding, and custom agent spans to
`PHOENIX_COLLECTOR_ENDPOINT` (defaults to `http://localhost:6006/v1/traces`). Set
`PHOENIX_API_KEY` when using Phoenix Cloud; local Phoenix does not require one.

## Team
| Member | Owns | Brief |
|--------|------|-------|
| 1 (Alex) | Document Intelligence (Python) | [member1](team/member1-document-intelligence.md) |
| 2 | Data & Contracts (Python + TS) | [member2](team/member2-data-layer.md) |
| 3 | DeadlineAgent + Reasoning (Python) | [member3](team/member3-deadline-agent.md) |
| 4 | Frontend + Voice (TS) | [member4](team/member4-frontend-chat-voice.md) |


## Detected evidence (automated analysis)

Indexed codebase: 267 recognized source files, 1191 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Redis (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository; commit authorship or trailers
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (120 of 296)

```
.agents/skills/arize-instrumentation/references/ax-profiles.md
.agents/skills/arize-instrumentation/references/integration-routing.md
.agents/skills/arize-instrumentation/references/manual-spans.md
.agents/skills/arize-instrumentation/references/tracing-assistant-mcp.md
.agents/skills/arize-instrumentation/SKILL.md
.agents/skills/arize-trace/references/ax-profiles.md
.agents/skills/arize-trace/references/ax-setup.md
.agents/skills/arize-trace/SKILL.md
.agents/skills/iris-development/.cursor-plugin/plugin.json
.agents/skills/iris-development/references/ltm-bulk-create.md
.agents/skills/iris-development/references/ltm-organize.md
.agents/skills/iris-development/references/ltm-search.md
.agents/skills/iris-development/references/promotion-overview.md
.agents/skills/iris-development/references/session-add-event.md
.agents/skills/iris-development/references/session-retrieval.md
.agents/skills/iris-development/references/session-when-to-use.md
.agents/skills/iris-development/references/setup-auth-token.md
.agents/skills/iris-development/references/setup-cloud-service.md
.agents/skills/iris-development/SKILL.md
.agents/skills/phoenix-cli/references/axial-coding.md
.agents/skills/phoenix-cli/references/open-coding.md
.agents/skills/phoenix-cli/SKILL.md
.agents/skills/phoenix-evals/references/axial-coding.md
.agents/skills/phoenix-evals/references/common-mistakes-python.md
.agents/skills/phoenix-evals/references/error-analysis-multi-turn.md
.agents/skills/phoenix-evals/references/error-analysis.md
.agents/skills/phoenix-evals/references/evaluate-dataframe-python.md
.agents/skills/phoenix-evals/references/evaluators-code-python.md
.agents/skills/phoenix-evals/references/evaluators-code-typescript.md
.agents/skills/phoenix-evals/references/evaluators-custom-templates.md
.agents/skills/phoenix-evals/references/evaluators-llm-python.md
.agents/skills/phoenix-evals/references/evaluators-llm-typescript.md
.agents/skills/phoenix-evals/references/evaluators-overview.md
.agents/skills/phoenix-evals/references/evaluators-pre-built.md
.agents/skills/phoenix-evals/references/evaluators-rag.md
.agents/skills/phoenix-evals/references/experiments-datasets-python.md
.agents/skills/phoenix-evals/references/experiments-datasets-typescript.md
.agents/skills/phoenix-evals/references/experiments-overview.md
.agents/skills/phoenix-evals/references/experiments-running-python.md
.agents/skills/phoenix-evals/references/experiments-running-typescript.md
.agents/skills/phoenix-evals/references/experiments-synthetic-python.md
.agents/skills/phoenix-evals/references/experiments-synthetic-typescript.md
.agents/skills/phoenix-evals/references/fundamentals-anti-patterns.md
.agents/skills/phoenix-evals/references/fundamentals-model-selection.md
.agents/skills/phoenix-evals/references/fundamentals.md
.agents/skills/phoenix-evals/references/observe-sampling-python.md
.agents/skills/phoenix-evals/references/observe-sampling-typescript.md
.agents/skills/phoenix-evals/references/observe-tracing-setup.md
.agents/skills/phoenix-evals/references/production-continuous.md
.agents/skills/phoenix-evals/references/production-guardrails.md
.agents/skills/phoenix-evals/references/production-overview.md
.agents/skills/phoenix-evals/references/setup-python.md
.agents/skills/phoenix-evals/references/setup-typescript.md
.agents/skills/phoenix-evals/references/validation-evaluators-python.md
.agents/skills/phoenix-evals/references/validation-evaluators-typescript.md
.agents/skills/phoenix-evals/references/validation.md
.agents/skills/phoenix-evals/SKILL.md
.agents/skills/phoenix-tracing/README.md
.agents/skills/phoenix-tracing/references/annotations-overview.md
.agents/skills/phoenix-tracing/references/annotations-python.md
.agents/skills/phoenix-tracing/references/annotations-typescript.md
.agents/skills/phoenix-tracing/references/fundamentals-flattening.md
.agents/skills/phoenix-tracing/references/fundamentals-overview.md
.agents/skills/phoenix-tracing/references/fundamentals-required-attributes.md
.agents/skills/phoenix-tracing/references/fundamentals-universal-attributes.md
.agents/skills/phoenix-tracing/references/instrumentation-atif-python.md
.agents/skills/phoenix-tracing/references/instrumentation-auto-python.md
.agents/skills/phoenix-tracing/references/instrumentation-auto-typescript.md
.agents/skills/phoenix-tracing/references/instrumentation-manual-python.md
.agents/skills/phoenix-tracing/references/instrumentation-manual-typescript.md
.agents/skills/phoenix-tracing/references/metadata-python.md
.agents/skills/phoenix-tracing/references/metadata-typescript.md
.agents/skills/phoenix-tracing/references/production-python.md
.agents/skills/phoenix-tracing/references/production-typescript.md
.agents/skills/phoenix-tracing/references/projects-python.md
.agents/skills/phoenix-tracing/references/projects-typescript.md
.agents/skills/phoenix-tracing/references/sessions-python.md
.agents/skills/phoenix-tracing/references/sessions-typescript.md
.agents/skills/phoenix-tracing/references/setup-python.md
.agents/skills/phoenix-tracing/references/setup-typescript.md
.agents/skills/phoenix-tracing/references/span-agent.md
.agents/skills/phoenix-tracing/references/span-chain.md
.agents/skills/phoenix-tracing/references/span-embedding.md
.agents/skills/phoenix-tracing/references/span-evaluator.md
.agents/skills/phoenix-tracing/references/span-guardrail.md
.agents/skills/phoenix-tracing/references/span-llm.md
.agents/skills/phoenix-tracing/references/span-reranker.md
.agents/skills/phoenix-tracing/references/span-retriever.md
.agents/skills/phoenix-tracing/references/span-tool.md
.agents/skills/phoenix-tracing/SKILL.md
.agents/skills/redis-clustering/.cursor-plugin/plugin.json
.agents/skills/redis-clustering/references/hash-tags.md
.agents/skills/redis-clustering/references/read-replicas.md
.agents/skills/redis-clustering/SKILL.md
.agents/skills/redis-connections/.cursor-plugin/plugin.json
.agents/skills/redis-connections/references/blocking.md
.agents/skills/redis-connections/references/client-cache.md
.agents/skills/redis-connections/references/pipelining.md
.agents/skills/redis-connections/references/pooling.md
.agents/skills/redis-connections/references/timeouts.md
.agents/skills/redis-connections/SKILL.md
.agents/skills/redis-core/.cursor-plugin/plugin.json
.agents/skills/redis-core/evals/core/baselines/aggregate-benchmark.json
.agents/skills/redis-core/evals/core/baselines/aggregate-benchmark.md
.agents/skills/redis-core/evals/core/baselines/baseline.json
.agents/skills/redis-core/evals/core/baselines/model-matrix.json
.agents/skills/redis-core/evals/core/baselines/README.md
.agents/skills/redis-core/evals/core/evals.json
.agents/skills/redis-core/evals/core/model-matrix.json
.agents/skills/redis-core/references/choose-data-structure.md
.agents/skills/redis-core/references/key-naming.md
.agents/skills/redis-core/SKILL.md
.agents/skills/redis-observability/.cursor-plugin/plugin.json
.agents/skills/redis-observability/references/commands.md
.agents/skills/redis-observability/references/metrics.md
.agents/skills/redis-observability/SKILL.md
.agents/skills/redis-query-engine/.cursor-plugin/plugin.json
.agents/skills/redis-query-engine/references/dialect.md
.agents/skills/redis-query-engine/references/field-types.md
.agents/skills/redis-query-engine/references/index-creation.md
[176 more files omitted for size]
```

### Dependencies

- agent/pyproject.toml: anthropic@>=0.40.0, arize-phoenix-client, arize-phoenix-evals, arize-phoenix-otel, bcrypt@>=4.0.0, email-validator@>=2.0.0, fastapi@>=0.111.0, openai@>=1.50.0, openinference-instrumentation-anthropic@>=0.1.0, openinference-instrumentation-openai@>=0.1.0, opentelemetry-sdk@>=1.42.1, pdfplumber@>=0.11.0, pillow@>=10.0.0, pillow-heif@>=0.16.0, pydantic@>=2.7.0, pypdf@>=4.0.0, python-dateutil@>=2.9.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.9, redis@>=5.0.0, upstash-redis@>=1.0.0, upstash-vector@>=0.5.0, uvicorn[standard]@>=0.30.0
- agent/requirements.txt: anthropic@>=0.40.0, arize-phoenix-client, arize-phoenix-evals, arize-phoenix-otel, bcrypt@>=4.0.0, email-validator@>=2.0.0, fastapi@>=0.111.0, openai@>=1.50.0, openinference-instrumentation-anthropic@>=0.1.0, openinference-instrumentation-openai@>=0.1.0, opentelemetry-sdk@>=1.42.1, pdfplumber@>=0.11.0, pillow@>=10.0.0, pillow-heif@>=0.16.0, pydantic@>=2.7.0, pypdf@>=4.0.0, python-dateutil@>=2.9.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.9, redis@>=5.0.0, upstash-redis@>=1.0.0, upstash-vector@>=0.5.0, uvicorn[standard]@>=0.30.0
- web/package.json: @deepgram/sdk@^3.8.0, @sentry/nextjs@^8.30.0, @types/node@^20.14.0, @types/react@^18.3.0, @types/react-dom@^18.3.0, autoprefixer@^10.4.0, eslint@^8.57.0, eslint-config-next@^14.2.0, lucide-react@^0.468.0, next@^14.2.0, postcss@^8.4.0, react@^18.3.0, react-dom@^18.3.0, react-markdown@^10.1.0, remark-gfm@^4.0.1, tailwindcss@^3.4.0, typescript@^5.5.0, zod@^3.23.0

### Recent commits (newest first)

- Merge branch 'sameer-dashboard'
- Removed setup in progress
- Merge branch 'sameer-dashboard'
- Fixed deadline agent
- updated example docs
- updated more docs
- Merge branch 'main' of github.com:s85rr25/executor-ai
- update all documents
- Merge branch 'main' of https://github.com/s85rr25/executor-ai into sameer-dashboard
- Made changes to the dashboard so that it updates dynamically
- added research agent
- update email contents
- Fixed the claude output for deadline agent
- Added phoenix evals
- Merge branch 'sameer-dashboard'
- Added phoenix
- Merge branch 'main' of https://github.com/s85rr25/executor-ai
- Added functionality to delete saved letters
- Merge pull request #18 from s85rr25/sameer-dashboard
- Merge branch 'main' of https://github.com/s85rr25/executor-ai into sameer-dashboard

## Key source files (fetched from GitHub, selected and truncated for size)

### hackathon_tracks_and_prizes.md

```markdown
# Hackathon @ Berkeley 2026: Tracks & Prizes

## Main Tracks

Each team will be able to apply to exactly one main track. If your project is motivated by a real-world social challenge, this is where it belongs.

### 🌍 Ddoski’s World Track
This track is for projects at the intersection of technology and social impact. This can include (but is not limited to) EdTech tools that improve access to quality education, civic platforms that support political participation or community organizing, environmental apps that track, reduce, or communicate ecological impact, and software that addresses systemic inequity in any form. 

### 🛠️ Ddoski’s Toolbox Track
This track covers tools built for developers, creators, and knowledge workers. Think developer utilities, APIs, automation scripts, workflow apps, project management systems, writing or design aids, and anything else that meaningfully improves how people work or create. We are interested in how useful, usable, and well-executed your tools are — not just the idea behind them.

### 🔬 Ddoski’s Lab Track
This track is for projects rooted in science and engineering. This can include health tech and medical tools, hardware hacks, embedded systems, biotech applications, data-driven scientific research tools, and solutions to complex engineering problems. Projects can be software, hardware, or a combination — what unites them is a grounding in technical depth and real-world application.

### 🎨 Ddoski’s Playground Track
AI is changing the creative space. Think outside of the box because this is our most open ended track! If you’re looking for an idea, have a think about how you could use AI to produce art or music or help others who do. Alternatively, have a go at building an experience like a game or performance. Some examples can include games, interactive experiences, generative art, experimental interfaces, and any idea that's creative or unconventional in its approach.

---

## Hackathon @ Berkeley Prizes

In addition to the four main tracks, there are a few other prizes that Hackathons @ Berkeley will be offering. All teams will automatically be considered for these prizes. The prizes that we are offering are summarized below:

| Track Name | Track Criteria | Prize(s) |
| :--- | :--- | :--- |
| **Grand Prize: Ddoski’s World** | Best project in the track, selected after finalist presentations. | $5K cash prize |
| **Grand Prize: Ddoski’s Toolbox** | Best project in the track, selected after finalist presentations. | $5K cash prize |
| **Grand Prize: Ddoski’s Lab** | Best project in the track, selected after finalist presentations. | $5K cash prize |
| **Grand Prize: Ddoski’s Playground** | Best project in the track, selected after finalist presentations. | $5K cash prize |
| **Finalists (top 10 teams)** | For all finalists invited to present on-stage at the Closing Ceremony. | Limited edition AI Hackathon 2026 merch |
| **SkyDeck Grand Prize Winner** | One startup-oriented Grand Prize winner will be inv
[truncated — 7877 more characters]
```

### AGENTS.md

```markdown
# Executor AI — Codex Instructions

## What This Is
An AI executor assistant. It parses estate documents into a live state graph, then
proactively alerts the executor *before* probate deadlines and liability triggers are
missed. The differentiator is a real **agent** — the DeadlineAgent — that reasons over
estate state against California probate law and surfaces the next action before the
executor knows to ask. Built with Codex for a 24-hour hackathon.

Full project detail: [project_overview.md](project_overview.md)
Tracks & sponsors: [hackathon_tracks_and_prizes.md](hackathon_tracks_and_prizes.md)

---

## Architecture at a Glance
This is a **polyglot** project — two services sharing one Redis state store. Use each
language for what it is best at; do not collapse everything into one stack.

```
┌────────────────────────┐         ┌─────────────────────────────┐
│  web/  (TypeScript)     │  HTTP   │  agent/  (Python)            │
│  Next.js 14 frontend    │ ──────▶ │  FastAPI "brain"             │
│  • Dashboard / chat UI  │  SSE    │  • Auth (login / register)   │
│  • Deepgram voice       │ ◀────── │  • Document intelligence     │
│  • Sentry observability │         │  • RAG chat (streaming)      │
└───────────┬─────────────┘         │  • DeadlineAgent (tool-use)  │
            │                       │  • ResearchAgent (law watch) │
            │                       │  • Letter gen · Email (Resend)│
            │                       │  • Phoenix tracing + evals   │
            │                       └──────────────┬──────────────┘
            │        Redis (KV estate state + vector search)        │
            └───────────────────────┬──────────────────────────────┘
                                    ▼
              Redis Cloud (KV + Redis 8 Vector Sets)
               (Upstash / in-memory backends also supported)
```

- **Python (`agent/`)** owns all Claude reasoning, document parsing, embeddings, the
  agent loop, and RAG. This is the "hard AI" surface and the Anthropic-prize story.
- **TypeScript (`web/`)** owns everything the judge sees and touches, plus voice.
- **Redis** is the only thing both services talk to. It is the contract.

---

## Stack (Quick Reference)

### `agent/` — Python service (the brain)
- **Framework**: FastAPI + Uvicorn, Python 3.11+
- **AI**: Anthropic Python SDK (`anthropic`)
  - `claude-sonnet-4-6` — used across the whole service today (document parsing,
    DeadlineAgent reasoning, RAG chat, letters). `agent/llm/claude.py` defines
    `DOCUMENT_MODEL` and `REASONING_MODEL` (both `claude-sonnet-4-6`); swap
    `REASONING_MODEL` to `claude-opus-4-8` for the heavier reasoning path.
- **Embeddings**: OpenAI `text-embedding-3-small` (`openai`), 1536-dim
- **Auth**: cookie sessions + `bcrypt` (`agent/auth/`)
- **Email**: Resend weekly recap / alert digest (`agent/notify/email.py`)
- **Validation**: Pydantic v2 for all Claude structured outputs and API schemas
- **Observability**: Phoenix tracing (`phoenix.otel.reg
[truncated — 8225 more characters]
```

### agent/requirements.txt

```
# Generated from pyproject.toml — prefer `uv sync` over installing this directly.
# Kept for environments without uv: `pip install -r requirements.txt`

fastapi>=0.111.0
uvicorn[standard]>=0.30.0
python-multipart>=0.0.9
anthropic>=0.40.0
openai>=1.50.0
arize-phoenix-otel
arize-phoenix-client
arize-phoenix-evals
openinference-instrumentation-anthropic>=0.1.0
openinference-instrumentation-openai>=0.1.0
opentelemetry-sdk>=1.42.1
pydantic>=2.7.0
email-validator>=2.0.0
bcrypt>=4.0.0
python-dateutil>=2.9.0
python-dotenv>=1.0.0
pypdf>=4.0.0
pdfplumber>=0.11.0
pillow>=10.0.0
pillow-heif>=0.16.0
redis>=5.0.0
upstash-redis>=1.0.0
upstash-vector>=0.5.0

```

### web/package.json

```
{
  "name": "clearpath-estate-web",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "typecheck": "tsc --noEmit",
    "test:contracts": "tsc -p ../tests/tsconfig.web.json && NODE_PATH=./node_modules node ../tests/.compiled/tests/member2_web_contracts.test.js && NODE_PATH=./node_modules node ../tests/.compiled/tests/member4_agent_client.test.js"
  },
  "dependencies": {
    "@deepgram/sdk": "^3.8.0",
    "@sentry/nextjs": "^8.30.0",
    "lucide-react": "^0.468.0",
    "next": "^14.2.0",
    "react": "^18.3.0",
    "react-dom": "^18.3.0",
    "react-markdown": "^10.1.0",
    "remark-gfm": "^4.0.1",
    "zod": "^3.23.0"
  },
  "devDependencies": {
    "@types/node": "^20.14.0",
    "@types/react": "^18.3.0",
    "@types/react-dom": "^18.3.0",
    "autoprefixer": "^10.4.0",
    "eslint": "^8.57.0",
    "eslint-config-next": "^14.2.0",
    "postcss": "^8.4.0",
    "tailwindcss": "^3.4.0",
    "typescript": "^5.5.0"
  }
}

```

### agent/pyproject.toml

```
[project]
name = "clearpath-agent"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    # Web framework
    "fastapi>=0.111.0",
    "uvicorn[standard]>=0.30.0",
    "python-multipart>=0.0.9",

    # AI
    "anthropic>=0.40.0",
    "openai>=1.50.0",

    # Observability
    "arize-phoenix-otel",
    "arize-phoenix-client",
    "arize-phoenix-evals",
    "openinference-instrumentation-anthropic>=0.1.0",
    "openinference-instrumentation-openai>=0.1.0",
    "opentelemetry-sdk>=1.42.1",

    # Data & validation
    "pydantic>=2.7.0",
    "email-validator>=2.0.0",
    "python-dateutil>=2.9.0",
    "python-dotenv>=1.0.0",

    # Auth
    "bcrypt>=4.0.0",

    # Document processing
    "pypdf>=4.0.0",
    "pdfplumber>=0.11.0",
    "pillow>=10.0.0",
    "pillow-heif>=0.16.0",

    # Redis
    "redis>=5.0.0",
    "upstash-redis>=1.0.0",
    "upstash-vector>=0.5.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["."]

[dependency-groups]
dev = [
    "pytest>=8.0.0",
    "pytest-asyncio>=0.23.0",
    "httpx>=0.27.0",
]

```

### web/types/index.ts

```typescript
export * from "./api";
export * from "./auth";
export * from "./documents";
export * from "./estate";


```

### web/app/page.tsx

```typescript
import { AppShell } from "@/components/screens/AppShell";

// The full Executor AI app, ported from the design system's ui_kits/web prototype.
// AppShell owns sidebar navigation (dashboard / documents / chat / letters) and modals.
export default function HomePage() {
  return <AppShell />;
}

```

### web/app/layout.tsx

```typescript
import type { Metadata } from "next";
import "./globals.css";

export const metadata: Metadata = {
  title: "Executor AI",
  description: "Executor assistant dashboard",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}


```

### agent/main.py

```python
from __future__ import annotations

import asyncio
from dataclasses import dataclass
import json
import logging
import uuid
from datetime import date
from typing import Any

from dotenv import load_dotenv

load_dotenv(".env")  # must run before any module that reads env vars at import time

from fastapi import Depends, FastAPI, File, Form, Header, HTTPException, UploadFile
from fastapi.responses import Response, StreamingResponse

from agents.deadline_agent import mark_alert_complete, refresh_deadline_state, run_deadline_agent
from auth.security import hash_password, new_session_token, verify_password
from documents.pdf_reader import extract_text
from documents.router import parse_document_text_with_type as parse_document_text
from llm.claude import DocumentParseError, generate_letter_draft, stream_chat, suggest_followups
from llm.embeddings import embed_query, embed_texts
from observability.phoenix import get_tracing_status, init_tracing, set_span_attribute, set_span_error, span
from prompts.letters import (
    CUSTOM_LETTER_TYPE,
    build_custom_letter_fallback,
    build_custom_letter_prompt,
    build_letter_fallback,
    build_letter_prompt,
    normalize_letter_type,
)
from prompts.system import build_chat_prompt
from researcher.research_agent import run_research_agent
from notify.email import build_alert_digest, build_weekly_recap, email_configured, resolve_recipient, send_email
from schemas.api import AnyDocumentExtraction, ChatHistoryResponse, ChatRequest, ChatSessionResponse, ChatSessionsResponse, ChatSuggestionsRequest, ChatSuggestionsResponse, DeadlineAgentRequest, GenerateLetterRequest, NotifyEmailRequest, NotifyEmailResponse, ParseDocumentResponse
from schemas.api import (
    AnyDocumentExtraction,
    ChatHistoryResponse,
    ChatRequest,
    ChatSessionResponse,
    ChatSessionsResponse,
    CompleteAlertRequest,
    DeadlineAgentRequest,
    EstateResponse,
    GenerateLetterRequest,
    ParseDocumentFailure,
    ParseDocumentResponse,
    ParseDocumentsResponse,
    ResearchAgentRequest,
    ResearchAgentResponse,
    SaveLetterRequest,
)
from schemas.auth import AuthResponse, CreateEstateRequest, LoginRequest, MeResponse, PublicUser, RegisterRequest, User
from schemas.documents import BankStatementExtraction, CreditorNoticeExtraction, DeedExtraction, WillExtraction
from schemas.estate import Alert, Asset, EstateState, Executor, SavedLetter, UploadedDocument, utc_now_iso
from store.redis_client import (
    add_document,
    append_chat_session_messages,
    create_chat_session,
    create_session,
    create_user,
    delete_document,
    delete_letter,
    delete_session,
    get_chat_history,
    get_chat_session_history,
    get_estate_state,
    get_document_file,
    get_session_user_id,
    get_user,
    get_user_by_email,
    merge_estate_state,
    seed_demo_estate,
    semantic_search,
    list_chat_sessions,
    set_document_file,
    set_estate_state,
    update_user,
    upsert_vectors,
)


LOGGER = logging.getLogger(__name__)
app = FastAPI(title="Executor AI Agent")


@app.on_event("startup")
async def startup() -> None:
    init_tracing()


@app.get("/health")
async def health() -> dict[str, object]:
    return {"status": "ok", "tracing": get_tracing_status()}


# --------------------------------------------------------------------------- #
# Auth — users + sessions live in the same Redis store as estate state.
# The web layer carries the opaque session token in an httpOnly cookie and
# forwards it here as ``Authorization: Bearer <token>``.
# --------------------------------------------------------------------------- #


def _bearer_token(authorization: str | None) -> str | None:
    if not authorization:
        return None
    scheme, _, token = authorization.partition(" ")
    if scheme.lower() != "bearer" or not token:
        return None
    return token.strip()


async def require_user(authorization: str | None = Header(default=None)) -> User:
    token = _bearer_token(authorization)
    user_id = get_session_user_id(token) if token else None
    user = get_user(user_id) if user_id else None
    if user is None:
        raise HTTPException(status_code=401, detail="Not authenticated")
    return user


def _create_estate_for_user(user: User, request: RegisterRequest) -> EstateState:
    """Create the user's first estate from their sign-up details. Jurisdiction
    is California-only for the hackathon, regardless of the chosen state."""
    estate = EstateState(
        id=f"est-{uuid.uuid4().hex[:8]}",
        deceasedName=request.deceasedName.strip() or "Unknown Decedent",
        dateOfDeath=request.dateOfDeath or date.today().isoformat(),
        appointmentDate=date.today().isoformat(),
        executor=Executor(name=user.name, email=user.email),
        county=user.county,
        phase=1,
    )
    return set_estate_state(estate)


@app.post("/auth/register", response_model=AuthResponse)
async def register(request: RegisterRequest) -> AuthResponse:
    if get_user_by_email(request.email) is not None:
        raise HTTPException(status_code=409, detail="An account with that email already exists.")

    user = User(
        id=f"user-{uuid.uuid4().hex[:12]}",
        name=request.name.strip(),
        email=str(request.email).strip().lower(),
        phone=request.phone,
        passwordHash=hash_password(request.password),
        relationship=request.relationship,
        state=request.state,
        county=request.county,
    )
    create_user(user)

    estate = _create_estate_for_user(user, request)
    user.estateIds = [estate.id]
    update_user(user)

    token = create_session(user.id, new_session_token())
    return AuthResponse(token=token, user=PublicUser.from_user(user), estate=estate)


@app.post("/auth/login", response_model=AuthResponse)
async def login(request: LoginRequest) -> AuthResponse:
    user = get_user_by_email(str(request.email))
    if user is None or not verify_password(request.password, user.passwordHash):
       
[truncated — 26599 more characters]
```

### web/lib/schemas/index.ts

```typescript
export * from "./api";
export * from "./auth";
export * from "./documents";
export * from "./estate";


```

[252 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]