Documentation Index
Fetch the complete documentation index at: https://docs.hawkings.education/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers the most common high-stakes flow: a student submits
an essay, the AI grades it, a teacher reviews, the gradebook updates.
const assignment = await hk.assignments.create({
lesson_id: "lsn_123",
type: "essay",
title: "Explain mass-energy equivalence",
rubric: {
criteria: [
{ name: "clarity", weight: 0.4 },
{ name: "accuracy", weight: 0.4 },
{ name: "sources", weight: 0.2 },
],
scale: { min: 0, max: 10 },
},
});
await hk.assignments.configure(assignment.id, {
ai_evaluator: { enabled: true, model: "claude-sonnet-4-6" },
human_review: "required", // student doesn't see grade until reviewed
feedback: { tone: "encouraging", verbosity: "normal" },
});
2. Receive a submission
The student app sends the response:
const submission = await hk.submissions.create({
assignment_id: assignment.id,
student_id: "usr_student_42",
content: { text: studentEssay },
});
If the assignment accepts files:
await hk.submissions.create({
assignment_id: assignment.id,
student_id: "usr_student_42",
content: { text: "" },
files: [{ name: "essay.pdf", body: fileBlob, content_type: "application/pdf" }],
});
3. Trigger AI grading
await hk.submissions.gradeWithAi(submission.id);
This is async. Subscribe to the submission.graded webhook for
production, or poll for prototypes:
const graded = await hk.poll(
() => hk.submissions.retrieve(submission.id),
{ until: s => s.ai_status === "ready" || s.ai_status === "error" },
);
4. Show the teacher
console.log(graded.grade_ai); // 8.5
console.log(graded.grading_rationale); // markdown breakdown
console.log(graded.grading_breakdown); // [{criterion, score, max}, ...]
Render grading_rationale as markdown next to the student’s text. The
teacher gets context, not a black box.
5. Teacher confirms or overrides
await hk.submissions.update(submission.id, {
grade_manual: 9.0, // override
grader_comments: "Great link to E=mc² in the closing.", // markdown
human_review_status: "reviewed",
});
If the teacher accepts the AI’s grade verbatim:
await hk.submissions.update(submission.id, {
grade_manual: graded.grade_ai,
human_review_status: "reviewed",
});
Or, if you want to skip the override and trust the AI:
await hk.submissions.update(submission.id, { human_review_status: "reviewed" });
// `grade_manual` stays null; the gradebook reads from `grade_ai`.
6. Read the final grade
The SDK abstracts the precedence rule:
const sub = await hk.submissions.retrieve(submission.id);
console.log(sub.final_grade); // grade_manual ?? grade_ai
final_grade is null while human_review_status === "pending" if the
assignment requires human review. That’s what your student-facing UI
should read.
At scale: grade a whole class
const subs = (await hk.submissions.list({ assignment_id: assignment.id })).data;
await Promise.all(
subs.map(s => hk.submissions.gradeWithAi(s.id)),
);
await hk.poll(
() => hk.submissions.list({ assignment_id: assignment.id }),
{ until: page => page.data.every(s => s.ai_status === "ready") },
);
// Now show the teacher a queue of submissions ranked by edge cases:
const needsReview = subs.filter(s => s.grading_breakdown.some(c => c.score / c.max < 0.5));
Tips
Pin the model. AI grades drift between model versions. If you need
audit-grade reproducibility, pass model: "claude-sonnet-4-6" (or
similar) in the assignment config.
Show the rubric to the student before they submit. A 30% increase
in rubric-aligned answers is typical.
Never auto-publish AI grades on consequential assessments. The
human_review: "required" flag exists for a reason. Use it.