The problem
The client's learning management system had been in production for five years, serving a mix of K-12 and higher-ed institutions. Its course-content architecture, permissions model, and gradebook logic had accumulated real complexity and, more importantly, real institutional trust. Nobody on the client's engineering team, or on ours, wanted to touch the core system to add an AI feature. The risk of breaking something load-bearing was high, and a ground-up rewrite was a multi-quarter project the business had no appetite for. The actual ask was narrower: give students an AI tutor that could help with course material in context, without changing the LMS underneath any existing integration or workflow.
The additional constraint was time. The client wanted this live before the start of the next academic term, which gave us roughly five weeks. That wasn't enough time for anything requiring deep changes to how course content was modeled or stored, even if we'd wanted to make them.
What we actually did
We built the tutor as a separate service that reads the LMS's content and enrollment data through its existing APIs. It isn't merged into the core application, and it's deployed and scaled independently of the main LMS.
Week 1: mapping what the existing APIs could and couldn't give us
The LMS had an internal API originally built for a mobile companion app, not for an AI feature, but it exposed enough: course structure, assigned readings, and a student's current progress through a course. We spent the first week confirming this API surface was sufficient to ground the tutor's answers in the course material a student was looking at, rather than assuming so and finding gaps mid-build. It was sufficient with one exception: quiz question content was deliberately not exposed through the API, for academic-integrity reasons. That shaped a scoping decision described below.
Weeks 2-3: building the tutor as an isolated service with read-only access
The tutor calls the LMS's existing API with a scoped, read-only service account. Broader database access would have been faster to build, but it would have put a new AI service with broad or write access next to five years of trust in the core system's data integrity. Every tutor response is grounded in the course content the student currently has open, retrieved fresh for each question rather than from a cached copy, because instructors do update course content mid-term.
Weeks 4-5: the academic-integrity boundary and rollout
Quiz content wasn't exposed via the API, and the client's academic customers were explicitly worried about an AI tutor being used to answer graded assessments. So we scoped the tutor to explain concepts and work through practice problems, with an explicit check that declines to engage when a student pastes in what looks like graded quiz or exam content, and tells the student why instead of silently answering. This required a lightweight classifier for "does this look like it's from a graded assessment?", which was its own small research problem within the five-week window.
Challenges and tradeoffs
- The existing API's rate limits weren't built for an AI feature calling it on every student question. The mobile-app API had rate limits sized for occasional app refreshes, not a tutor calling it dozens of times per session across thousands of concurrent students. We added request batching and a short-lived cache scoped narrowly to course-structure data (not the freshness-sensitive content itself) to stay within the existing limits without asking the client's team to raise them under time pressure.
- The academic-integrity classifier needed real validation before launch, not a best-effort heuristic. A tutor that's too aggressive about declining looks broken to students with legitimate questions; one that's too permissive undermines the client's core promise to academic customers. We validated the classifier against real graded-assessment excerpts and legitimate practice questions from the client's curriculum team, tuning until both false-decline and false-permit rates were acceptable to their academic advisory board.
- Five weeks meant deferring some genuinely useful features rather than compressing the timeline. A version of the tutor that could reference a student's past quiz performance to personalize explanations was requested but deferred to a second phase. Building it properly needed deeper API access than the timeline allowed, and we didn't want to rush the academic-integrity boundary to fit it in.
Results
The tutor launched on schedule before the start of term, with zero modifications to the LMS's core codebase, exactly the constraint the client's engineering leadership had set. In the first full term, 31% of actively enrolled students used it at least weekly, which the client's product team considered strong for an opt-in feature with no in-app prompting beyond a single onboarding notice.
Median time to first streamed token held at 212 milliseconds despite fetching fresh content for every question, largely because the request-batching layer absorbed the added API load without the core LMS's rate limits being raised. No participating institution logged an academic-integrity incident involving the tutor in the first term, which was the metric the client's academic advisory board most wanted validated before considering broader rollout.
What we'd do differently
We'd scope the academic-integrity classifier's validation dataset earlier, ideally in week one alongside the API mapping, rather than building it in week four under time pressure. It worked out, but validating a system meant to catch a sensitive failure mode deserves more runway than the four or five days it got.