All projects
Knowledge Graph · Agents · RAGArchitecture, ML, and full stack/2025

uSport.ai

An AI recruiting platform built on a knowledge graph — ten agent surfaces, seven vector indexes, one substrate.

The system as it stands: ten product surfaces over four service layers, every agent grounded in the graph.

uSport.ai matches student-athletes to college coaches. The hard part was never the chat interface — it was building a substrate factual enough that an agent could answer recruiting questions without inventing schools, times, or eligibility rules. That substrate is a Neo4j knowledge graph with 8M+ athletes, 51K coaches, 176K schools, and 15M+ swim results, with seven native vector indexes layered on top for retrieval. I architected and built it from an empty repository.

8M+
Athletes in the graph
51K coaches · 176K schools
15M+
Swim results
plus 350K D1 basketball games over 50 years
7
Vector indexes
native to Neo4j — no separate vector store
15+
Agent tools
across 6 RAG chains and 10 product surfaces

Why a graph and not a vector store

Recruiting questions are relational. “Which D2 programs in my conference recruit 51-second 100 freestylers, and am I still eligible after transferring?” is four joins and a rules lookup, not a similarity search. Embeddings retrieve things that read alike; they cannot tell you that a school's slowest benchmark is faster than your best time, or that a contact period has closed.

So the ground truth is a Neo4j graph — 8M+ athletes, 51K coaches, 176K schools, 15M+ swim results, 350K D1 basketball games across fifty years, 120 years of Olympic history, and 1,400+ NCAA rules — traversed with Cypher. Agents call it as a tool and get facts back.

Retrieval sits on the same database rather than beside it. Seven vector indexes live natively in Neo4j — episodes, news, RSS, conversation memory, swim research, and generated swim and lacrosse plans — all embedded with text-embedding-3-small at 1536 dimensions. One store, so a retrieved passage and the entity it describes are one hop apart instead of one network call and a join key.

Ten surfaces, one substrate

The platform is not a single chatbot. Scout is the athlete's portal for discovering programs; Draft is the coach's for scouting and outreach; the Assistant is the general agent with 15+ tools and full RAG. Around those sit NIL valuation, career projection, drill planning, a teams hub, an NCAA compliance checker, and transfer-portal tracking.

Each has its own API route and its own tool set, but they all resolve to the same graph and the same indexes. Adding a surface means composing existing retrieval rather than standing up new infrastructure — which is the entire argument for putting the effort into the substrate first.

A representative flow: a coach asks Draft for prospects, Claude calls search_athletes against indexed Neo4j queries over 8M+ records, pulls a roster with get_school_roster, drafts outreach that goes out through Resend and gets logged to Firestore, and emits a report block that renders to PDF. The conversation turn is then embedded into the memory index so the next session starts informed.

Agent Gym — training data from simulation

Recruiting conversations are scarce, private, and slow to accumulate. Agent Gym generates them instead: Claude simulates both sides of a recruiting exchange and then judges the result, and every episode is embedded into a dedicated index.

Those episodes come back as in-context examples for Scout and Draft, so the production agents retrieve prior situations that resemble the one in front of them. It is a closed loop — simulation produces episodes, episodes ground the live agents, live behavior suggests what to simulate next — and it meant the agents were not starting cold on day one.

What the substrate makes cheap

Compliance is a good example of the payoff. NCAA rules are in the graph as data, so an eligibility check is a traversal that cross-references the athlete's own record against division-specific rules and contact periods, with the model interpreting rather than recalling. The failure mode of an LLM confidently misremembering an eligibility rule is designed out rather than prompt-engineered around.

Drill planning composes three retrievals at once — the swim technique graph for drills, faults, and biomechanics; a research index of PDF chunks; and a plan index of prior generations — which is why the same generator could later be lifted wholesale into the Onpace mobile app and produce identical plans.

Transfer-portal tracking ingests RSS, embeds it, writes entries as graph nodes, and surfaces relevant moves by similarity — the same four moves as everything else, which is the point.

Scope

Solo, from data to production: the scrapers and ETL that fill the graph, the Cypher and schema, the embedding pipelines behind all seven indexes, the agent tool definitions and RAG orchestration, the Next.js application, Firebase Auth and Firestore, Cloud Functions for credits and sync, Stripe billing, Gmail sequences, and PDF and Excel generation.

Two pieces are documented separately here: Agent Gym, the simulation environment that trains the recruiting agents, and the two-tower retrieval model that ranks coach–athlete matches.

Platform at a glance

Graph
Neo4j Aura — COACHES_AT, ATTENDS, COMMITTED_TO, PLAYS_SPORT
Embeddings
text-embedding-3-small, 1536-d, indexed natively in Neo4j
Models
Claude for every agent; GPT-4o for re-ranking, email, scoring
App
Next.js on Firebase — Auth, Firestore, Storage, Cloud Functions
Domain graphs
Swim technique, lacrosse, deaf sports, 1,400+ NCAA rules
Ingestion
Swimcloud, Hudl, ON3, SportsRecruits, golf scrapers

Stack

Next.jsTypeScriptNeo4j AuraCypherClaudeGPT-4otext-embedding-3-smallFirebaseFirestoreCloud RunCloud FunctionsStripePlaywright / ScrapyCrewAI