Back to portfolio
SERVICE · port 8000 · live
Career Bot
A public chat that answers real questions about my work. Behind the friendly bubble: RAG over a Memory-Archive knowledge graph, dual-LLM routing through the agentic-framework registry, and the production-live Talent Manager agent that mirrors a phase-gated outreach protocol.
Try the chat →Request flow
From a chat-bubble keystroke to a cited answer — every hop, named.
Architecture, in seven moving parts
Each piece does one job; nothing leaks across boundaries.
1 · Chat widget
vanilla JS · no framework
A small widget mounted on the home page (
?chat=open auto-opens it). Posts to /career-bot/api/chat-widget; degrades gracefully if the upstream is down.2 · Flask app
port 8000 · gunicorn · launchd
Stateless API surface. Per-IP rate limit, request tracing, cost-tracking middleware that records token spend to PostgreSQL on every call.
3 · Memory Archive — RAG
MCP · /memory-archive/mcp
Every query first hits the Memory Archive's
hybrid_search + kg_query tools to pull cited context. The bot never answers from training alone — every response is grounded in indexed memories.4 · Agentic framework
ProviderRegistry · cost tracker
Shared package abstracts the LLM call. Routes a fast question to Sonnet, a depth-of-thought question to Opus 4.7. One registry, one place to swap providers.
5 · Talent Manager
phase-gated · production-live
In-bot agent that mirrors an outreach protocol: scout → resolve → outreach. Phase gates with explicit transitions, rate-limited HTTP executor, and a Slack approve/deny pre-filter for any side-effecting step.
6 · Redis
rate limit · transient state
Sliding-window rate limit per IP, plus session state for in-flight Talent Manager phases. Independent of Postgres so a slow LLM call never blocks transactional reads.
7 · Cost ledger
PostgreSQL · per-call rows
Every LLM call writes one row: model, input tokens, output tokens, latency, dollar cost, success bool. Drives the FinOps Agent's monthly review and feeds the Morning Brief digest. Cost surprises die quietly here, not on a credit-card statement.
Talent Manager — phase gates
Why an agent that can do real outreach can't accidentally fire off a real email.
1
Scout
Crawls a seed list of company URLs (
api.* subdomains, OpenAPI / Swagger paths, common career endpoints). Last live run: 4 hits from 52 seeds.2
Resolve
For every hit: pointer-follow MCP resolver, classify
mcp_auth_required vs open. Stores both states. Never assumes.3
Slack pre-filter
Before any outbound action: agent posts the proposed action to Slack with approve/deny. No approval = no execution. Period.
4
Outreach
Live HTTP dispatch with rate-limit race already fixed (Phase 5b). Idempotency keys; observable from
/memory-archive/sessions.Why this is more than a chatbot
Every answer is sourced
RAG isn't decoration. The bot can't answer about my work without grounding in a real memory. If the KG has nothing, it says so.
Dual-LLM routing
"What did Corey ship last week?" → Sonnet 4.6, low latency. "Walk me through the deploy pipeline" → Opus 4.7, depth.
A real agent lives inside
Talent Manager is reference for the rest of the system. Other service agents copy its phase-gate pattern.
Cost is a first-class metric
Per-call cost rows in Postgres. Monthly FinOps review reads them. Nothing surprises me on the Anthropic invoice.
Want the rest of the system?
Career Bot is one node in a larger graph. Memory Archive holds the brain; the agentic framework wires every service together; the deployment pipeline lands changes safely.