Inspiration
My two teammates and I spent years in university lecture halls, filling our schedules with courses we thought were the right ones — only to graduate and realize half of them never came up again. Not once. Career services handed us pamphlets. Advisors had 400 students each and fifteen minutes for us. The course catalog was a PDF. We guessed. Most students guess. And they pay tens of thousands of dollars for the privilege.
Sitting in this hackathon, the three of us kept coming back to the same question: what if someone had just told us? What if a system existed that knew your goals, knew your history, and could actually connect the two? That frustration became CourSelect
What It Does
CourSelect is a conversational AI academic advisor. A student tells it their goal — "I want to be a machine learning engineer" or "I need to protect my GPA this semester" — and it responds with a ranked, explained course plan, complete with confidence scores and career outcome projections.
It doesn't guess. It reasons. It reads the student's completed courses, cross-references thousands of real university courses against actual career data, checks prerequisite eligibility, and returns personalized recommendations with a short explanation for each one — why this course, for this student, toward this goal.
Built on Penn State's public course catalog — 8,983 courses across 242 departments — it enforces major-discipline permissions, protects completed academic records, and remembers every conversation so returning students never start from scratch.
How We Built It
The backbone is CockroachDB Cloud, used not as a simple database but as a five-layer persistent memory system:
Conversational memory — every chat turn stored in the conversations table, retrieved via MCP so the agent has full context across sessions Identity memory — students and student_goals tables read at session start to personalize every query Task state — recommendation_sessions written mid-run so no request is ever lost to a timeout or restart Semantic embeddings — all-MiniLM-L6-v2 vectors stored natively via pgvector for cosine-similarity course and career matching Transactional data — enrollment records, prerequisite graphs, and graduation requirements, all queried read-only through an MCP server
The agent is Gemini with tool use, running a single-shot architecture — tools prefetched in parallel, one LLM call, results in under two seconds. A 4-tier fallback chain (Gemini → Ollama local → Mistral → direct vector results) means the system never goes down. An L2 cognitive cache on top of the vector index brings repeat query latency from ~1100ms to under 3ms.
The Flask backend runs on Amazon EC2, deploys automatically from GitHub, and writes every recommendation report to Amazon S3. The ccloud CLI gives the agent live visibility into cluster health.
Challenges We Ran Into
Getting five memory types to work coherently inside a single agent request was the hardest architectural problem we faced. Conversation history, identity context, task state, semantic matches, and transactional eligibility checks all needed to resolve before the LLM call — without adding latency that would make the system feel broken.
We rewrote the agent three times. The first version made sequential tool calls — fifteen seconds per request. The second parallelized the fetches but lost coherence in the prompt. The third — the one that shipped — pre-fetches all tool results concurrently, builds a single structured prompt, and makes one LLM call. Two seconds, end to end.
We also hit memory limits at 2am on a t3.micro EC2 instance trying to load sentence-transformers and three gunicorn workers simultaneously into 908MB of RAM. We rebuilt the deployment from scratch — single preloaded worker, 2GB swap, CPU-only PyTorch — and shipped it in time.
Accomplishments That We're Proud Of
We're proud that it actually works — not just in a demo environment but live, at a public URL, handling real queries against 8,983 real courses.
We're proud of the memory architecture. Most agents treat memory as an afterthought — a chat history array appended to a prompt. We designed five distinct memory types from the schema up, and each one does something the others can't.
And we're proud that the three of us — each carrying the specific frustration of having chosen the wrong courses at the wrong time — built something we genuinely wish had existed when we were students.
What We Learned
We learned that the quality of an AI agent is determined by the quality of its memory, not its model. Gemini 1.5 Flash with five layers of structured CockroachDB memory outperformed every heavier model we tested with flat context.
We learned that CockroachDB is genuinely different at scale. Horizontal distribution isn't a feature you bolt on — it's a design decision you make at the schema level, and making it early changed how we thought about every table we created.
We learned that pgvector inside CockroachDB eliminates an entire category of infrastructure complexity. No separate vector store. No sync job. Semantic search and transactional queries in the same cluster, the same connection, the same consistency guarantees.
What's Next for CourSelect
GPA simulation. Swap one course in your plan and instantly see how your projected GPA shifts. We have the grade distribution data. The query is already written. This is the feature students will actually open the app for every semester.
Multi-campus rollout. A single university system can have dozens of campuses, each with its own catalog. CockroachDB's horizontal scalability means CourSelect can expand to every campus without a schema change — just data. UC Berkeley is first on our list.
Employer outcome feeds. We want to connect real hiring data — which courses appear most frequently on the resumes of people who landed specific roles — and feed that signal directly into the agent's ranking logic.
Built With
- amazon-ec2
- amazon-web-services
- cockroachdb
- css3
- flask
- gemini
- git
- github
- gunicorn
- html5
- javascript
- mcp
- mistral
- ollama
- pgvector
- postgresql
- python
- sentence-transformers
- sql
- sqlalchemy
Log in or sign up for Devpost to join the conversation.