save_evaluation_request_item

Save an evaluation on a request item

All MCP toolsWrite

Save (or re-save) the evaluator's evaluation of ONE candidate on ONE evaluation request — the same save as the evaluation page: the overall grade, the typed answers to the request lane's aspects, and a comment. The EVALUATOR alone may write; the requester, admins, and other members are refused (not_evaluator), a canceled request refuses (already_canceled), a candidate who is not one of the request's items refuses (person_not_found), and unknown, cross-organization, and garbage request ids get ONE indistinguishable not-found refusal. Answers are held to the form's definitions and each refusal writes nothing: an answer whose type differs from its aspect's refuses (aspect_type_mismatch), a choice/multi value outside the definition's options refuses (option_unknown), and a required aspect left unanswered refuses (required_unanswered — details.missingIndices names the blank form indices). The save is the WHOLE state: a re-save replaces the previous grade, aspect answers, and comment (omitted aspectAnswers = every aspect unanswered, omitted note = empty), while evaluatedAt keeps its first-save value. Aspects are answered by INDEX into the aspects array of get_evaluation_request (read it right before saving — the form can change): each entry is {type, answer} matching the aspect's own type (choice = one option's text, multi = the picked options' texts, text = free text ≤ 300 chars) or null for unanswered; the server snapshots each aspect's text from the CURRENT form, an answer past the form's length is dropped, and unanswered aspects save no entry. On the agreed terms the form declares no aspects, so every aspectAnswers entry is dropped and the grade and note alone save. No notification is published and candidates never see the evaluation. This is the request's own evaluation — a different fact from the organization-level save_candidate_evaluation quick grade, which it never touches. Person-id inputs name the human principal you act for (persons.id), never a credential identity: pass the staff member on whose behalf the call is made.

Input schema

{
  "type": "object",
  "properties": {
    "requestId": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "The request being evaluated (evaluation_requests.id)."
    },
    "personId": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "The candidate being evaluated (persons.id) — one of the request's items."
    },
    "actorPersonId": {
      "type": "string",
      "format": "uuid",
      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      "description": "The acting staff member (persons.id) — must be the request's evaluator."
    },
    "grade": {
      "anyOf": [
        {
          "type": "string",
          "enum": [
            "S",
            "A",
            "B"
          ],
          "description": "Candidate evaluation grade: S | A | B (S = most want to meet). No C grade — declined owns rejection."
        },
        {
          "type": "null"
        }
      ],
      "description": "The overall grade: S | A | B, or null for no overall grade."
    },
    "aspectAnswers": {
      "description": "The typed answers in form order — {type, answer} | null per aspect, indexed like get_evaluation_request's aspects. Omitted = every aspect unanswered.",
      "maxItems": 10,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "const": "choice"
                  },
                  "answer": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 30,
                    "description": "The selected option's text, exactly as the form spells it."
                  }
                },
                "required": [
                  "type",
                  "answer"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "const": "multi"
                  },
                  "answer": {
                    "minItems": 1,
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 30
                    },
                    "description": "The selected options' texts, distinct, exactly as the form spells them."
                  }
                },
                "required": [
                  "type",
                  "answer"
                ],
                "additionalProperties": false
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "const": "text"
                  },
                  "answer": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300,
                    "description": "The free-text answer, trimmed, non-empty, ≤ 300 chars."
                  }
                },
                "required": [
                  "type",
                  "answer"
                ],
                "additionalProperties": false
              }
            ]
          },
          {
            "type": "null"
          }
        ],
        "description": "One answer input in form order — the type tag and the answer, or null for unanswered. The aspect text never rides the wire: the server snapshots it by index."
      }
    },
    "note": {
      "description": "The comment — the reason behind the judgement, ≤ 300 chars. Omitted = empty.",
      "type": "string",
      "maxLength": 300
    }
  },
  "required": [
    "requestId",
    "personId",
    "actorPersonId",
    "grade"
  ],
  "$schema": "http://json-schema.org/draft-07/schema#"
}

Output schema

{
  "type": "object",
  "properties": {
    "request": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "description": "The request id (evaluation_requests.id)."
        },
        "jobId": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ],
          "description": "The job the evaluation is against (jobs.id, same organization) when the request's seat is a job's; null when the interview was on the agreed terms."
        },
        "agreementId": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ],
          "description": "The agreed terms the interview referred to (agreements.id) when the request's seat is the agreement's; null on a job seat — exactly one of jobId / agreementId is set, and the agreed terms declare no aspects."
        },
        "requesterPersonId": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ],
          "description": "The requesting staff member (persons.id), or null for a workflow-filed request."
        },
        "evaluatorPersonId": {
          "type": "string",
          "format": "uuid",
          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
          "description": "The staff member asked to evaluate (persons.id)."
        },
        "origin": {
          "type": "string",
          "enum": [
            "manual",
            "interview"
          ],
          "description": "How the request was filed: manual (a staff member) | interview (the post-interview workflow)."
        },
        "interviewSlotId": {
          "anyOf": [
            {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            {
              "type": "null"
            }
          ],
          "description": "The interview the workflow filed this request for (interview_slots.id), else null."
        },
        "status": {
          "type": "string",
          "enum": [
            "open",
            "completed",
            "canceled"
          ],
          "description": "Derived evaluation-request status: open | completed | canceled (never stored)."
        },
        "createdAt": {
          "type": "string",
          "format": "date-time",
          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
          "description": "When the request was filed (ISO 8601, UTC)."
        },
        "canceledAt": {
          "anyOf": [
            {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
            },
            {
              "type": "null"
            }
          ],
          "description": "When the request was canceled, or null while it stands."
        },
        "items": {
          "maxItems": 100,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "personId": {
                "type": "string",
                "format": "uuid",
                "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
                "description": "The candidate to evaluate (persons.id, same organization)."
              },
              "evaluated": {
                "type": "boolean",
                "description": "Whether the evaluator has saved an evaluation for this candidate on this request."
              },
              "evaluation": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "grade": {
                        "anyOf": [
                          {
                            "type": "string",
                            "enum": [
                              "S",
                              "A",
                              "B"
                            ],
                            "description": "Candidate evaluation grade: S | A | B (S = most want to meet). No C grade — declined owns rejection."
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "The overall grade (S | A | B), or null."
                      },
                      "aspectAnswers": {
                        "type": "array",
                        "items": {
                          "oneOf": [
                            {
                              "type": "object",
                              "properties": {
                                "aspect": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 60,
                                  "description": "The aspect text as it read when the evaluation was saved (a snapshot)."
                                },
                                "type": {
                                  "type": "string",
                                  "const": "choice"
                                },
                                "answer": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 30,
                                  "description": "The selected option's text, exactly as the form spells it."
                                }
                              },
                              "required": [
                                "aspect",
                                "type",
                                "answer"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "aspect": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 60,
                                  "description": "The aspect text as it read when the evaluation was saved (a snapshot)."
                                },
                                "type": {
                                  "type": "string",
                                  "const": "multi"
                                },
                                "answer": {
                                  "minItems": 1,
                                  "maxItems": 5,
                                  "type": "array",
                                  "items": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 30
                                  },
                                  "description": "The selected options' texts, distinct, exactly as the form spells them."
                                }
                              },
                              "required": [
                                "aspect",
                                "type",
                                "answer"
                              ],
                              "additionalProperties": false
                            },
                            {
                              "type": "object",
                              "properties": {
                                "aspect": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 60,
                                  "description": "The aspect text as it read when the evaluation was saved (a snapshot)."
                                },
                                "type": {
                                  "type": "string",
                                  "const": "text"
                                },
                                "answer": {
                                  "type": "string",
                                  "minLength": 1,
                                  "maxLength": 300,
                                  "description": "The free-text answer, trimmed, non-empty, ≤ 300 chars."
                                }
                              },
                              "required": [
                                "aspect",
                                "type",
                                "answer"
                              ],
                              "additionalProperties": false
                            }
                          ],
                          "description": "One saved aspect answer — the aspect text snapshot, its type, and the typed answer. Unanswered aspects have no entry."
                        },
                        "description": "The aspects as ANSWERED at save time, in the form's order then — unanswered aspects have no entry."
                      },
                      "note": {
                        "type": "string",
                        "maxLength": 300,
                        "description": "The comment — the reason behind the judgement, read by whoever asked. ≤ 300 chars."
                      },
                      "evaluatedAt": {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
                        "description": "When the evaluation was first saved (ISO 8601, UTC)."
                      }
                    },
                    "required": [
                      "grade",
                      "aspectAnswers",
                      "note",
                      "evaluatedAt"
                    ],
                    "additionalProperties": false,
                    "description": "One evaluator's saved evaluation of one candidate on one request."
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The saved evaluation, or null while the evaluator has not saved one."
              }
            },
            "required": [
              "personId",
              "evaluated",
              "evaluation"
            ],
            "additionalProperties": false,
            "description": "One evaluation-request item: the candidate, the evaluated flag, and the saved evaluation."
          },
          "description": "The requested candidates with their derived evaluated flags."
        }
      },
      "required": [
        "id",
        "jobId",
        "agreementId",
        "requesterPersonId",
        "evaluatorPersonId",
        "origin",
        "interviewSlotId",
        "status",
        "createdAt",
        "canceledAt",
        "items"
      ],
      "additionalProperties": false,
      "description": "The request as the evaluator now sees it — the saved item carries evaluated: true and its evaluation."
    }
  },
  "required": [
    "request"
  ],
  "$schema": "http://json-schema.org/draft-07/schema#",
  "additionalProperties": false
}

On this page