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.

A design decision worth calling out
We recommended against caching course content inside the tutor service for performance, even though calling the LMS's API fresh on every question added latency we then had to optimize elsewhere. A cached copy risked serving stale material after an instructor corrected an error or updated a reading. That's a low-probability but high-consequence failure in education: an AI tutor confidently explaining outdated material is worse than a few hundred extra milliseconds of latency.

Challenges and tradeoffs

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.