Skip to content

Built for the agents your district will run

An open tool in a world of closed systems.

The next bottleneck in EdTech isn't whether software has AI. It's whether a district's own agent can safely use the software it already pays for. Papalotl EDU is built to be used by an agent the way a teacher uses it in the browser: same actions, same permissions, fully audited, nothing destructive.

Where we sit on the agent-readiness ladder

The rubric is from Kris Hagel's Build Products Our Agents Can Use. We hold ourselves to Level 3 today and name the Level 4 gaps plainly.

  1. L0Closed. Humans click buttons. No programmatic surface
  2. L1Has an API, but it lags the UI and uses shared service accounts
  3. L2API parity + real auth, but no agent affordances
  4. L3Agent-ready. OpenAPI + MCP, scoped delegated permissions, audit, dry-run & rollback, sandboxYou are here
  5. L4Agent-native. Events/webhooks, autonomous workflows, negotiated DPAs

The Level-3 checklist, met honestly

Green means it ships today. Sand means it's deliberately scoped. The architecture is ready. The rest is a district's policy call.

API coverage matches UI actions

Every teacher action is a versioned /api/v1 endpoint backed by the same pure engine the UI uses. That covers generating a comment, scoring against standards, evaluating fluency, and exporting a class.

Machine-readable tool descriptions

A live OpenAPI 3.1 document sits at /api/v1/openapi. A one-call discovery root at /api/v1 lists endpoints, scopes, and how to authenticate.

MCP server

A zero-dependency stdio MCP server (mcp/server.mjs) exposes five tools over the same API. Register it with Claude Code, Claude Desktop, or any district agent.

Fine-grained, delegated permissions

Scoped Bearer keys (standards:read, comments:generate, fluency:read, export:create). Never a god-mode service account. The acting teacher rides in X-On-Behalf-Of for attribution.

Structured, exportable audit log

Every call emits a structured audit record (requestId, at, action, principal, on-behalf-of, sandbox, dry-run) for a district to ship to its SIEM. A queryable store is the district's sink, not ours. The API keeps no student records of its own, and records saved to a school account are a separate store the API does not query.

Dry-run / preview + rollback

The engine is generative, not destructive. Comments are drafts a teacher reviews. Exports take dryRun:true to preview rows before producing a file. The MCP tool defaults to dry-run.

Sandbox to test against

In development (or with CNA_ALLOW_SANDBOX=true) the API runs keyless in open sandbox mode. In production a missing key list fails closed with 503. The engine stores no student records either way.

OAuth scopes / SCIM provisioning

Today it is a signed scoped-key list driven by environment config. The auth boundary is isolated in one module so a district can swap in OAuth 2.0 scopes or SCIM without touching handlers.

Webhooks / event streams (Level 4)

Not yet. The engine is request/response and stateless, so there are no server-side events to stream. This is the honest gap between Level 3 and Level 4.

Clear DPA terms for agent use

We collect as little as possible: in No-Save mode nothing student-bearing is written to the browser or a server, comments are generated on-device with no AI provider in the path, and nothing is ever sold. A district DPA remains a required paperwork step before saved-history deployment.

The surface

MethodPathScope
GET/api/v1public
GET/api/v1/openapipublic
GET/api/v1/standardsstandards:read
GET/api/v1/skillsstandards:read
POST/api/v1/commentscomments:generate
POST/api/v1/fluencyfluency:read
POST/api/v1/exportexport:create

Call it over HTTP

curl -X POST https://your-deployment/api/v1/comments \
  -H "Authorization: Bearer $CNA_KEY" \
  -H "X-On-Behalf-Of: teacher@district.org" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "standards",
    "student": { "alias": "S-K7MPQ2XW", "pronoun": "she" },
    "scores": { "rl_kid": "proficient", "w_text_types": "developing" },
    "languages": ["en", "es"]
  }'

Or hand it to an agent

# Register the MCP server with any district-owned agent
claude mcp add papalotl-edu -- \
  node /path/to/papalotl-edu/mcp/server.mjs

# Tools it exposes:
#   list_standards · list_skills · generate_comment
#   evaluate_fluency · export_class  (dry-run by default)

The point isn't the API. It's the teacher's weekend.

The browser, the API, and the agent all lead to the same place. That place is standards-aligned, bilingual communication that tells a family their child is seen, written in a fraction of the time. Open by design, so it can meet a district wherever it already works.