Multi-agent course planning assistant for Columbia University students. Built at the Claude Builder Hackathon (April 12, 2026).
Read docs/plan.md for the full implementation plan, directory structure, shared contracts, agent architecture, and work split across team members. Read docs/prd.md for product requirements and feature priorities.
- Backend: Python 3.14, FastAPI, anthropic SDK (raw tool use, not Agent SDK)
- Frontend: Next.js 16, TypeScript, Tailwind CSS, react-markdown
- External Search: Linkup API (
linkup-sdkPython package) - LLM: Claude Sonnet (
claude-sonnet-4-6) for agents, Claude Haiku (claude-haiku-4-5-20251001) for fast tasks - Data: JSON course catalog (
data/2026-Spring.json,data/2026-Fall.json), loaded into memory at startup
The backend has 3 agents orchestrated by a coordinator. Each agent is an async function that calls anthropic.AsyncAnthropic().messages.create() with a specific system prompt and tools, then runs a tool-use loop (agents/base.py:run_agent_loop).
- Coordinator (
agents/coordinator.py): classifies user intent (simple_query, research_query, recommendation), routes to agent pipeline - Catalog Agent (
agents/catalog.py): searches the local course catalog viasearch_coursestool - Web Research Agent (
agents/web_research.py): enriches courses with external data via Linkup API (linkup_searchtool with structured schemas for course reviews, professor reviews, industry demand, custom insights) - Advisor Agent (
agents/advisor.py): ranks courses against student preferences, returns fit scores (0.0-1.0)
Pipeline flow for recommendations: Coordinator -> Catalog Agent -> Web Research Agent -> Advisor Agent. Simple queries skip directly to the Catalog Agent.
Frontend communicates with backend via SSE (Server-Sent Events) on POST /api/chat. The useChat hook handles streaming of agent status updates and text deltas.
GET /api/health: Health checkGET /api/courses: Returns full course catalog as JSONPOST /api/chat: SSE stream (acceptsChatRequestwith messages and student profile)
- All shared data models live in
backend/models.py(Pydantic). If you need a new model, add it there. - Tool definitions (JSON schemas + executor functions) live in
backend/tools/. - Use
async/awaiteverywhere in the backend. No sync blocking calls. - Use
config.pyfor all env vars and constants. Do not hardcode API keys or model names. - Frontend types in
frontend/src/lib/types.tsmust mirror the Pydantic models inbackend/models.py. Keep them in sync.
# Backend
cd backend
cp .env.example .env # fill in API keys
source ../.venv/bin/activate
uvicorn main:app --reload
# Frontend
cd frontend
npm install
npm run dev- Andrew Suh
- Kaspar Soukup
- Steven Mei
- Leo Lin