Inspiration
Students receive important academic information across Canvas pages, lecture PDFs, assignments, announcements, email, and calendars. Understanding what changed and deciding what to do next requires repeatedly checking several systems.
I built StudyOps to reduce this friction. Instead of creating another general-purpose chatbot, I wanted an academic operations agent that could retrieve real course information, answer with verifiable evidence, remember the current conversation, and safely turn assignment data into actions.
What it does
StudyOps supports a complete academic workflow:
- Synchronizes course pages, files, assignments, and deadlines from Canvas.
- Normalizes and deduplicates content before storing it.
- Extracts and chunks PDF course materials.
- Retrieves relevant passages using semantic search.
- Answers course questions with source and page citations.
- Lists deadlines and retrieves authoritative assignment details.
- Maintains persistent conversation memory across requests.
- Prepares Google Calendar events using verified assignment dates.
- Requires confirmation before performing an external calendar action.
The agent uses four controlled tools:
answer_course_questionlist_course_deadlinesget_assignment_detailsprepare_calendar_event
This keeps the agent focused and prevents unrestricted tool use.
How I built it
The backend is built with FastAPI and deployed on Google Cloud Run.
Cloud Scheduler initiates recurring synchronization, while Cloud Tasks handles background ingestion work. The Canvas connector is intentionally read-only and retrieves course information without modifying the source platform.
New or changed PDFs are stored in Google Cloud Storage. StudyOps extracts their text, divides it into searchable chunks, and generates embeddings with Vertex AI. Course records, embeddings, synchronization state, conversations, and pending actions are stored in Firestore.
The agent uses Gemini 3.7 Flash through the Google GenAI SDK. When a student asks a question, Gemini selects an appropriate controlled tool. For course questions, StudyOps retrieves the most relevant chunks and provides them to Gemini as grounded context. The final answer includes numbered citations and source metadata.
Conversation messages are stored using a user ID, course ID, and session ID. When the student asks a follow-up question, StudyOps reloads the previous messages so the agent can understand the existing context. This project implements persistent conversation memory; episodic and semantic preference memory are future work.
Calendar actions follow a prepare → inspect → confirm or cancel workflow. A proposed event is stored as a short-lived pending action. Expiration checks prevent stale approvals, while idempotency protection prevents duplicate events.
Challenges I faced
One major challenge was building a reliable ingestion pipeline around real course data. Canvas content appears in different forms, including pages, assignments, modules, and file references. I created a normalization and deduplication layer so repeated synchronization would not create duplicate records.
Cloud deployment also exposed several practical issues. Early Cloud Run executions encountered missing dependencies and incorrect environment configuration. Firestore initially returned permission errors until the runtime service account received the correct IAM roles.
Scheduler requests returned authentication errors until the request headers and service configuration were aligned. Cloud Tasks also required the correct queue location, worker URL, and service-account settings before asynchronous execution worked successfully.
Another challenge was grounding Gemini’s responses. Early retrieval attempts sometimes returned insufficient context. I improved the pipeline by persisting page-level chunks, generating embeddings, adjusting retrieval limits, and requiring the final response to remain within the supplied course evidence.
Finally, calendar writes required careful safety design. Allowing the model to write immediately would be risky, so I introduced pending actions, explicit confirmation, expiration, and idempotency controls.
What I learned
I learned that building a useful agent requires much more than connecting a language model to a chat interface. The difficult parts are data ingestion, state management, tool boundaries, reliability, and safe action execution.
I also learned the importance of separating agent reasoning from deterministic application logic. Gemini decides which capability is needed, but the application validates identifiers, retrieves trusted data, enforces expiration rules, and controls external writes.
Most importantly, I learned that agent memory should be described precisely. StudyOps implements verified conversation memory, while course sources and synchronization records are operational application state rather than additional human-like memory layers.
Accomplishments
The completed project achieved:
- A deployed Google Cloud backend.
- End-to-end Canvas ingestion and deduplication.
- PDF extraction, chunking, embedding, and semantic retrieval.
- Grounded answers with citations.
- Four controlled agent tools.
- Persistent multi-turn conversation memory.
- Human-confirmed calendar actions with duplicate protection.
- 31 passing automated tests and successful Python compilation.
What’s next
Future improvements include preference memory, better retrieval evaluation, additional academic integrations, richer monitoring, and personalized deadline prioritization.
The long-term goal is for StudyOps to become a trusted academic operations layer that monitors fragmented information, explains what matters, and safely helps students act on it.
Report Link: https://docs.google.com/document/d/1Y_NCPBJQK2Jy0zXbXxj8s4AH1Ge1a9-JVwMPCN2pGBA/edit?usp=sharing
Built With
- agent
- cloudrun
- firestore
Log in or sign up for Devpost to join the conversation.