Loading...
Loading...
Bulk grading workflows for Canvas LMS assignments using rubrics. Covers single grading, batch grading, and code execution strategies with safety-first dry runs.
npx skill4agent add vishalsachdev/canvas-mcp canvas-bulk-gradingget_assignment_details(course_identifier, assignment_id)get_assignment_rubric_detailslist_all_rubricsget_assignment_rubric_details(course_identifier, assignment_id)
list_all_rubrics(course_identifier)
get_rubric_details(course_identifier, rubric_id)_8027list_submissions(course_identifier, assignment_id)user_idworkflow_stateHow many submissions need grading?
|
+-- 1-9 submissions
| Use grade_with_rubric (one call per submission)
|
+-- 10-29 submissions
| Use bulk_grade_submissions (concurrent batch processing)
| Set max_concurrent: 5, rate_limit_delay: 1.0
| ALWAYS run with dry_run: true first
|
+-- 30+ submissions OR custom grading logic needed
Use execute_typescript with bulkGrade function
99.7% token savings -- grading logic runs locally
ALWAYS run with dry_run: true firstgrade_with_rubricgrade_with_rubric(
course_identifier,
assignment_id,
user_id,
rubric_assessment: {
"criterion_id": {
"points": <number>,
"rating_id": "<string>", // optional
"comments": "<string>" // optional per-criterion feedback
}
},
comment: "Overall feedback" // optional
)bulk_grade_submissions(
course_identifier,
assignment_id,
grades: {
"user_id_1": {
"rubric_assessment": {
"criterion_id": {"points": 85, "comments": "Good analysis"}
},
"comment": "Overall feedback"
},
"user_id_2": {
"grade": 92,
"comment": "Excellent work"
}
},
dry_run: true, // VALIDATE FIRST
max_concurrent: 5,
rate_limit_delay: 1.0
)dry_run: falseexecute_typescriptexecute_typescript(code: `
import { bulkGrade } from './canvas/grading/bulkGrade.js';
await bulkGrade({
courseIdentifier: "COURSE_ID",
assignmentId: "ASSIGNMENT_ID",
gradingFunction: (submission) => {
// Custom grading logic runs locally -- no token cost
const notebook = submission.attachments?.find(
f => f.filename.endsWith('.ipynb')
);
if (!notebook) return null; // skip ungraded
return {
points: 100,
rubricAssessment: { "_8027": { points: 100 } },
comment: "Graded via automated review"
};
}
});
`)search_canvas_tools("grading", "signatures")| Strategy | When | Token Cost | Why |
|---|---|---|---|
| 1-9 submissions | Low | Few round-trips, small payloads |
| 10-29 submissions | Medium | One call with batch data |
| 30+ submissions | Minimal | Grading logic runs locally; only the code string is sent. 99.7% savings vs loading all submissions into context |
bulk_grade_submissionsdry_run: truegrade_with_rubricmax_concurrent: 5rate_limit_delay: 1.0| Error | Cause | Action |
|---|---|---|
| 401 Unauthorized | Token expired or invalid | Regenerate Canvas API token |
| 403 Forbidden | Not an instructor/TA for this course | Verify Canvas role |
| 404 Not Found | Wrong course, assignment, or rubric ID | Re-check IDs with |
| 422 Unprocessable | Invalid rubric assessment format | Verify criterion IDs and point ranges match the rubric |
| Partial failures in bulk | Some grades submitted, others failed | Check the response for per-student status; retry only failed ones |