Discover capabilities first
Read rollout and authorization before the scoped LMS schema:agentSurfaces: the family status is disabled, rollout_gated, unauthorized, or available, and each operation has its own authorized value. Treat every status except available as fail-closed.
Then read the canonical LMS contract before composing requests:
capabilities.retraining for operations, modes, exact-one recipient and due-date rules, plan receipt bindings, receipt lifetime, close outcomes, and human checkpoints. The same response describes current course, lesson, assessment, asset, Preview, and mastery capabilities.
Endpoints
Authorization
Reads requirelms:read. Writes and the protected no-write plan require lms:write. Every operation enforces organization and job access. Worker names are masked. Answer keys, correct values, and other workers’ submissions are never included.
Create, update, assign, close, and module-registration requests require an Idempotency-Key header. Replaying the same key with the same request returns the stored result. Reusing it with a different request fails with 409 CONFLICT. Planning intentionally takes no idempotency key because it performs no writes.
Create a case
POST /cases requires an Idempotency-Key header and an exact-one worker reference:
worker.contractId or worker.workerName, never both. Exact-name resolution fails closed on zero or multiple matches.
Use exactly one of dueOffsetMinutes or absoluteDue:
Update a draft
PATCH /cases/{caseId} requires expectedStateRevision and an Idempotency-Key header:
DRAFT case. A stale revision returns 409 CONFLICT; read the current case before deciding whether to retry.
Plan and assign
POST /cases/{caseId}/plan takes no idempotency key and performs no writes. The response includes:
- the masked recipient and stable contract ID;
- the exact published course version, module, and content hash;
- the case revision and capture hash;
- the exact frozen due instant;
- mastery eligibility and warnings;
- zero plan-side writes, notifications, and attempts;
- the exact confirmation effects;
- a request hash and short-lived signed receipt.
POST /cases/{caseId}/assign, an Idempotency-Key header, and:
confirmAssign: true records the approved mutation; it does not authorize an agent to approve its own plan. The receipt becomes stale when the captured case, course content, course version, or revision changes. Re-plan and obtain approval for the new result instead of forcing a stale assignment.
Read and close
GET /cases/{caseId} returns employer-safe case details plus live projections from the canonical assignment and review readers. Run history is bounded; follow the returned cursor through the canonical LMS run-history operation when more rows exist.
GET /cases and GET /modules return hasMore and an opaque nextCursor. Pass nextCursor back unchanged as cursor and continue until hasMore === false before reporting a complete inventory. A cursor outside the authorized, filtered result set returns 400 BAD_REQUEST.
Closing is terminal for that occurrence. PASSED requires a canonically completed assignment. FAILED requires an exhausted failure parked with the employer. CANCELLED and SUPERSEDED do not cancel an active assignment; resolve that assignment through its canonical operation first.
POST /cases/{caseId}/close requires an Idempotency-Key header and:
Errors
Failures use the shared envelope:code and structured details, not error. Common retraining statuses are: create 404/409/422, update 409/422, plan 404/409/422, assign 409, close 409, and list 400. See Errors, Pagination, and Rate Limits for the shared meanings and retry rules.
Register a reusable module
POST /modules takes an Idempotency-Key header: