Grade Sync via AGS
The Assignment and Grade Services (AGS) specification is the LTI 1.3 standard for sending scores from a tool back to the LMS gradebook. TutorFlow implements AGS to automatically sync evaluation scores when a student completes an LTI-launched assessment.
How AGS Works
AGS defines a REST API that the LMS exposes for managing line items (grade columns) and posting scores. During an LTI launch, the LMS includes an AGS claim in the JWT that provides the endpoint URLs and scopes available to TutorFlow.
AGS Claim in the Launch Token
{
"https://purl.imsglobal.org/spec/lti-ags/claim/endpoint": {
"scope": [
"https://purl.imsglobal.org/spec/lti-ags/scope/lineitem",
"https://purl.imsglobal.org/spec/lti-ags/scope/score",
"https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly"
],
"lineitems": "https://canvas.instructure.com/api/lti/courses/1/line_items",
"lineitem": "https://canvas.instructure.com/api/lti/courses/1/line_items/42"
}
}| Field | Description |
|---|---|
scope | The AGS operations TutorFlow is authorized to perform |
lineitems | URL to manage all line items for the course (optional) |
lineitem | URL for the specific line item linked to this assignment |
Score Sync Flow
When a student launches TutorFlow from an LMS assignment and completes an evaluation, the following happens automatically:
1. Student launches TutorFlow via LTI
-> TutorFlow stores AGS endpoint and credentials in the launch session
2. Student submits answer, evaluation runs
-> Evaluation completes with a score
3. TutorFlow requests an OAuth2 access token from the LMS
POST {platformTokenEndpoint}
grant_type=client_credentials
scope=https://purl.imsglobal.org/spec/lti-ags/scope/score
4. TutorFlow posts the score to the LMS line item
POST {lineitem}/scores
Authorization: Bearer {access_token}
5. LMS updates the gradebookTutorFlow handles steps 3 through 5 automatically after the evaluation completes. No additional API calls are needed from your side.
Triggering Grade Sync from the REST API
If you are building a custom integration where evaluations are created via the REST API (rather than through the LTI UI), you can link an evaluation to an LTI launch session. This allows the automatic grade sync to work even when the evaluation is created programmatically.
Include the ltiLaunchSessionId in the clientMetadata field of your evaluation request:
curl -X POST https://api.tutorflow.io/v1/platform/evaluations \
-H "Authorization: Bearer tf_platform_..." \
-H "Content-Type: application/json" \
-d '{
"evaluationType": "open_ended",
"questionText": "Explain the concept of supply and demand",
"learnerAnswer": "Supply and demand is the relationship between...",
"language": "en",
"maxScore": 10,
"clientMetadata": {
"ltiLaunchSessionId": "session_abc123"
}
}'When the evaluation completes, TutorFlow looks up the launch session, retrieves the AGS credentials, and posts the score to the LMS.
Where to Get the Launch Session ID
The ltiLaunchSessionId is returned in the launch session context when TutorFlow
processes an LTI launch. If you are building a custom frontend that embeds inside the LMS
iframe, the session ID is available in the launch response and can be passed to your
backend for use in evaluation requests.
Score Format
TutorFlow posts scores using the AGS Score service format:
{
"scoreGiven": 8.0,
"scoreMaximum": 10.0,
"activityProgress": "Completed",
"gradingProgress": "FullyGraded",
"userId": "lti-user-sub-claim",
"timestamp": "2026-03-25T12:05:00Z"
}Score Fields
| Field | Type | Description |
|---|---|---|
scoreGiven | number | The score the student received (from the evaluation result) |
scoreMaximum | number | The maximum possible score (from the evaluation maxScore) |
activityProgress | string | The student's progress on the activity |
gradingProgress | string | The grading status |
userId | string | The sub claim from the LTI launch token (identifies the student in the LMS) |
timestamp | string | ISO 8601 timestamp of when the score was recorded |
Activity Progress Values
| Value | When Used |
|---|---|
Initialized | Launch started but no submission yet |
Started | Student has begun the activity |
InProgress | Student is working on the activity |
Submitted | Student submitted but grading is pending |
Completed | Activity and grading are both finished |
Grading Progress Values
| Value | When Used |
|---|---|
FullyGraded | Evaluation completed successfully |
Pending | Evaluation is still processing |
PendingManual | Requires manual review (not currently used) |
Failed | Evaluation failed (score not posted to LMS) |
NotReady | Not yet ready for grading |
Score Mapping
TutorFlow maps evaluation results to AGS scores as follows:
| Evaluation Field | AGS Field |
|---|---|
score | scoreGiven |
maxScore | scoreMaximum |
Status COMPLETED | activityProgress: Completed, gradingProgress: FullyGraded |
Status FAILED | Grade sync is skipped (no score posted) |
Status PENDING / PROCESSING | Grade sync waits until the evaluation reaches a terminal state |
Error Handling
If the grade sync fails (e.g., the LMS token endpoint is unreachable or the line item URL has expired), TutorFlow retries with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 5 seconds |
| 2nd retry | 30 seconds |
| 3rd retry | 120 seconds |
After 3 retries, the sync is marked as failed. The evaluation itself remains in the
COMPLETED state. You can check whether the grade sync succeeded by looking at the
evaluation's ltiGradeSyncStatus field:
curl https://api.tutorflow.io/v1/platform/evaluations/2f4ad455-1e8e-4b6c-9f3a-7ebf4cf6f483 \
-H "Authorization: Bearer tf_platform_..."{
"id": "2f4ad455-1e8e-4b6c-9f3a-7ebf4cf6f483",
"status": "COMPLETED",
"score": 8,
"maxScore": 10,
"ltiGradeSyncStatus": "synced",
"ltiGradeSyncedAt": "2026-03-25T12:05:01Z"
}Grade Sync Status Values
| Status | Description |
|---|---|
pending | Grade sync has not yet been attempted |
syncing | Currently posting the score to the LMS |
synced | Score successfully posted to the LMS gradebook |
failed | All retry attempts exhausted |
not_applicable | Evaluation was not linked to an LTI launch session |
Webhook Events
When grade sync completes or fails, TutorFlow emits webhook events if you have Webhooks configured:
| Event | Description |
|---|---|
lti.grade_synced | Score successfully posted to LMS |
lti.grade_sync_failed | Grade sync failed after all retries |
Example Webhook Payload
{
"event": "lti.grade_synced",
"evaluationId": "2f4ad455-1e8e-4b6c-9f3a-7ebf4cf6f483",
"ltiRegistrationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"scoreGiven": 8.0,
"scoreMaximum": 10.0,
"userId": "lti-user-sub-claim",
"syncedAt": "2026-03-25T12:05:01Z"
}