How this site works

A plain-English look at how the assistant finds the right context, chooses an answer, checks its work, and handles failures.

Responds in real time

Answers appear as they are written, and the status reflects what the assistant is actually doing — not a fake typing animation.

Finds the right context

Searches for both exact words and related ideas, then combines the strongest matches before answering.

Human judgment first

I review test answers first, then compare the AI judges against those human decisions.

Built to fail safely

If context search is unavailable, the assistant uses the full resume instead, so visitors can still get an answer.

Architecture

One FastAPI service serves the static frontend and the API. Guardrails (rate limits, quotas, validation) run before any model call; retrieval and model routing run concurrently; the answer streams back over SSE.

Architecture diagram The browser connects to the application, which searches for exact words and related ideas while choosing the right Claude model, then streams the answer back. Browser vanilla JS · no framework FastAPI gateway guardrails · quotas · model router Haiku classifier picks the model Context search exact words + meaning combines best matches resume + project notes Claude Opus — complex Sonnet — simple fallback on failure Answer assembly grounded reply · sources · follow-ups SSE stream back tokens render live

Streaming & model routing

Every chat is a real server-sent-event stream: the browser shows retrieval status, then tokens as Claude produces them. What you see in the status steps is what actually happened — a cached answer says "answered from cache," it doesn't fake a search.

A small Haiku classifier (4 output tokens, 2-second timeout) routes each question: simple factual lookups go to Sonnet, synthesis and comparisons go to Opus, and any router failure fails safe to the most capable model. Routing runs concurrently with retrieval, so it adds no time to first token.

event: status   {"stage": "rag_search", "state": "done", "sources": [...]}
event: status   {"stage": "routing", "state": "done", "model": "sonnet"}
event: delta    {"text": "Dakota is PCAP-certified and uses Python in"}
event: done     {"reply": "...", "sources": [...], "followups": [...]}

How it finds the right context

When someone asks a question, the assistant searches my resume and project notes in two ways: one looks for the exact words they used, and the other looks for ideas with a similar meaning. It combines the best matches and gives Claude the most relevant context before it answers.

If search is temporarily unavailable, the site uses the full resume instead, so visitors can still get an answer.

Human-judged LLM

I reviewed a 100-question test set by hand, using pass/fail labels and written critiques to identify recurring problems. I then built three focused LLM graders and compare their verdicts with the human labels. The graders are still being tuned, so human judgment remains the standard. This workflow is inspired by Hamel Husain's human-first evaluation approach.

Connect your own AI

The resume is machine-readable: /llms.txt is rendered live from the same source of truth, and an MCP endpoint exposes one data-only tool, get_resume. Connect it and your own AI can read the full resume and answer questions with its own reasoning — no account, no API key, nothing to authorize.

Claude (claude.ai or desktop): Settings → Connectors → Add custom connector, then paste this URL:

https://www.dakotaradigan.io/mcp

Claude Code (terminal):

claude mcp add --transport http resume https://www.dakotaradigan.io/mcp

Then ask your assistant something like "Using the resume tool, is Dakota a fit for this role?" Any other MCP-capable client (ChatGPT, Cursor, etc.) works the same way — add a remote MCP server with the URL above, streamable-HTTP transport, no authentication.

Ask the assistant about any of this