Skip to main content

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
};