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.
An Assignment is something you grade. A Submission is a single
student’s response to it. Submissions hold both the response and the
grade, because in our experience the two need to live next to each
other: AI grading, human grading, regrades, comments, files.
Assignment "Essay: explain Lorentz invariance"
├─ Submission (student A) → grade 8.5 (AI), 9.0 (human override)
├─ Submission (student B) → grade 6.5 (AI)
└─ Submission (student C) → grade 0 (not submitted yet)
Creating an assignment
await hk.assignments.create({
lesson_id: "lsn_123",
type: "essay",
title: "Explain Lorentz invariance in your own words",
due_at: "2026-06-01T23:59:00Z",
rubric: {
criteria: [
{ name: "clarity", weight: 0.4 },
{ name: "physics accuracy", weight: 0.4 },
{ name: "use of sources", weight: 0.2 },
],
scale: { min: 0, max: 10 },
},
});
You can also configure the AI grader explicitly:
await hk.assignments.configure(assignmentId, {
ai_evaluator: { enabled: true, model: "claude-sonnet-4-6" },
human_review: "required" | "optional" | "off",
});
Submitting
A student submits with submissions.create():
await hk.submissions.create({
assignment_id: "asg_123",
student_id: "usr_123",
content: { text: "Lorentz invariance means that the laws of physics ..." },
});
You can attach files via multipart upload.
Grading
Three flavours, in this order of trust:
AI grading
await hk.submissions.gradeWithAi(submissionId);
const sub = await hk.submissions.retrieve(submissionId);
// sub.grade_ai → 8.5
// sub.grading_rationale → markdown explanation, criterion-by-criterion
Human override
await hk.submissions.update(submissionId, {
grade_manual: 9.0,
grader_comments: "Strong on conceptual clarity; missed the bit on simultaneity.",
});
The human grade always wins where present; AI grades stay attached for
audit.
Bulk grading
When you want to grade an entire assignment at once (e.g. reading the
whole class’ submissions overnight):
await hk.submissions.bulk({
assignment_id: "asg_123",
rows: classSubmissions.map(s => ({
submission_id: s.id,
grade_manual: s.draftScore,
grader_comments: s.feedback,
})),
});
Human-in-the-loop pattern
A common pattern: AI proposes, human decides.
// 1. AI grades all of them
for (const sub of submissions) {
await hk.submissions.gradeWithAi(sub.id);
}
// 2. Show teacher the AI grade + rationale; teacher confirms or edits
// in your UI
// 3. Save with a manual grade (optional) and mark reviewed
await hk.submissions.update(submissionId, {
grade_manual: teacherDecision.score,
grader_comments: teacherDecision.notes,
human_review_status: "reviewed",
});
This is the workflow we recommend for everything other than purely
formative quizzes. It’s fast, it’s auditable, and it keeps a teacher
on the hook for the final mark.
What Submission includes
type Submission = {
id: string;
assignment_id: string;
student_id: string;
content: SubmissionContent;
files: File[];
grade_ai: number | null;
grade_manual: number | null;
grading_rationale: string | null; // markdown, AI-generated
grader_comments: string | null; // markdown, human-written
human_review_status: "pending" | "reviewed" | "off";
ai_status: "pending" | "ready" | "error";
evaluated_at: string | null; // ISO 8601
uploaded_at: string; // ISO 8601
};