Skip to main content
Glama

Update interview or position

update_interview
DestructiveIdempotent

[Interviews] Update the configuration of an existing interview/position: name, description, avatar template, recording, scoring, tags and the rest of the create-time settings. Only the fields you send are changed. To change the questions, send questions — the WHOLE list you want the interview to end up with, in order, in the format get_interview_definition returns. OMIT questions and the existing questions are left completely alone; there is no way to change one question on its own, so read the interview first, edit that array, and send it back. Resending an unchanged array does nothing. Not updated by this tool at all: the welcome and thank-you messages and the instructional-video screen (stored as steps, not questions), and the language, which the existing questions are already written in. Use tags to place a coaching session into a catalogue directory. MULTI-STAGE POSITIONS: some per-interview settings do not exist at position level and are rejected with a 422 naming the field — candidate_expectations_json is the one seen in practice. Read the position with get_interview_definition, then update the individual stage you mean instead of sending that field to the position.

Updates the configuration of an existing interview (single-stage) or position (multi-stage). Only the fields present in the request body are written — everything else keeps its current value, and sending null clears a nullable field. The question list is only touched when you send questions; omit that field and the questions are left exactly as they are. When sent, it must be the complete list and is applied as a diff against what is stored (matched on external_id, then id, then identical content), so unchanged questions keep their existing records, edited ones are unlinked and re-created, and dropped ones are unlinked — and re-sending the array job-interview-get returned changes nothing. See the field description, and questions_diff in the response for what was decided. Questions of an interview that is already active can only be changed on interactive avatar templates, where re-publishing is instant; on the offline (pre-rendered video) templates set the interview back to draft first. The welcome / thank-you messages and the instructional-video screen are stored as steps rather than questions and are never changed here. mojito_language_code cannot be changed — the existing questions and rendered videos are in the original language — so create a new interview to change language. A multi-stage position only carries the shared identity fields (name, code, location, description, description_long, cover_image_url, department, salary, available_till, recruiter, status, visibility, hiring_for_company); sending an interview-only field for a position is a 422.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codeNoExternal code/reference. Blank is stored as null.
nameNoInterview / position name.
tagsNoFree-form tags stored on the interview. Tags are also the coaching-catalogue mapping key: a catalogue directory (see the catalogue-tag-create / catalogue-tag-update endpoints) lists a coaching or persona session when the session's tags contain EVERY tag in that directory's `tags_interview_set_filter`. Only `active` sessions with visibility `public` or `merchant_public` are listed.
typeNoProduct type of the interview. Changing it also re-derives `type_credit` (null for interview/assessment, otherwise interview_coach_manager) unless you send `type_credit` explicitly. Single-stage interviews only.
statusNoNew lifecycle status. Applied through the same interview_set_status routine as job-interview-set-state (which is also where you manage the iframe embed key).
locationNoInterview location (column `interview_location`). Blank is stored as null.
questionsNoOPTIONAL. Omit this field entirely and the interview's questions are left exactly as they are — this endpoint only touches questions when you send the array. When you do send it, send the COMPLETE list you want the interview to end up with, in order, in the same format job-interview-create-from-array accepts and job-interview-get returns: there is no way to change a single question on its own, so read the interview, edit that array, and send the whole thing back. An empty array is rejected. It is applied as a DIFF, not a replace, so resending the array job-interview-get gave you changes nothing at all. Each entry is matched against what is stored — first on `external_id`, then on `id`, then on identical content — and: an entry matching an unchanged question keeps that question exactly as it is, including its answer rules and any rendered avatar video; an entry matching a question whose content differs unlinks the old question and creates a new one in its place (fields you omit are carried over from the old one); an entry matching nothing is created; and a stored question no entry matches is unlinked. `questions_diff` in the response reports exactly what was decided. Questions are shared records, so nothing is ever deleted — removing one only unlinks it from this interview, and an edit is always unlink-old + create-new so the change cannot leak into another interview reusing the same question. The welcome, thank-you and instructional-video steps are not part of this array and are left in place. Single-stage interviews only; for a multi-stage position, update its interview stages individually.
recordingNoCheating/proctoring detection mode for candidate answers — this is NOT a full session recording. Video options also record the candidate. Omit/null to disable. Options — `audio_first_5_answers`: Audio-only cheating detection, first 5 answers only. | `audio_all`: Audio-only cheating detection on every answer. | `video_all`: Audio + video cheating detection on every answer (candidate is recorded for all answers). | `video_first_5_answers`: Audio + video cheating detection, first 5 answers only..
coach_planNoCoaching-plan stage this item belongs to, used by the coaching-plan progress view. Omit/null to leave it out of any plan. Options — `demo`: Demo session. | `screening`: Screening-interview practice. | `2nd`: Second-interview practice. | `3rd`: Third-interview practice. | `closing`: Closing / salary-negotiation practice. | `job-specific`: Job-specific coaching. | `other`: Anything that does not fit the other buckets..
visibilityNoWho can discover and access the interview. Options — `merchant_public`: Listed on the merchant's public interview list — anyone with the merchant link can find and start it. | `merchant_invite`: Invite-only — only candidates explicitly invited (by email/link) can access it; not listed anywhere. | `merchant_unlisted`: Reachable only via a direct link — not listed anywhere; share the link manually..
descriptionNoShort interview description.
environmentNoWhich of your webhook environments results from this interview are delivered to. Defaults to production. Options — `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..
position_idYesId of the interview definition (single-stage) or position definition (multi-stage) to update. The same id you pass to job-interview-get.
result_viewNoResult screen shown to the candidate after finishing. With any value other than `none`, the candidate sees a results screen where they can provide feedback, record an intro video and edit the transcript, and must then submit the result; the value sets how much score/result detail is shown. Options — `none`: No results screen at all — the interview is submitted immediately when the candidate finishes (no feedback, intro video, transcript edit or manual submit step). | `minimal`: Minimal results layout, no score shown. | `minimal_with_score`: Minimal results layout including the overall score. | `advanced`: Advanced results layout with more detail. | `full`: Full results layout with all sections. | `full_expand_scores`: Full results with every score breakdown expanded..
type_creditNoCredit bucket the session draws from. Only meaningful for candidate-paid coaching/persona sessions; hiring interviews and assessments are merchant-billed and carry null. Options — `resume_check`: Resume-check credits. | `interview_coach_starter`: Coaching credits — starter tier. | `interview_coach_contributor`: Coaching credits — contributor tier. | `interview_coach_manager`: Coaching credits — manager tier. | `cover_letter`: Cover-letter credits..
max_durationNoLive session limit in seconds. Also the basis for the credit multiplier.
max_followupsNoMaximum number of AI follow-up questions. 0 disables follow-ups; presets are 0-3 (none/low/normal/high) and custom values start at 4; null uses the template default (Normal).
custom_scoringNoResult-scoring overrides (max_score, early_stop, speech_cadence, ai_pronunciation, sentiment_analysis, ai_assessment_answer, ai_assessment_resume, ai_assessment_session). Merged onto the stored configuration, so keys you omit keep their current value.
interview_toneNoTone — configures the AI avatar's speaking style and the follow-up questions it generates. Stored in creation_parameters; existing questions are NOT regenerated. Case-insensitive; omit to default to relaxed. Options — `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level — short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing — for interviews built from your own questions (create_interview_from_questions) where the wording is a script..
interview_typeNoInterview style — configures the AI avatar and the follow-up questions it generates during the interview. Stored in creation_parameters; existing questions are NOT regenerated. Options — `pre-screening`: Pre-screening — quick qualification check focusing on basic requirements and availability. | `pre-screening-with-test-questions`: Pre-screening with test questions — pre-screening plus practical questions to test relevant skills. | `second-interview`: Second round interview — deeper dive for candidates who passed initial screening. | `remote-freelancer-verification`: Remote worker verification — verify remote work capabilities and communication skills. | `strength-based-interview`: Strength-based interview — focus on what candidates enjoy and excel at to predict job satisfaction. | `potential-based-interview`: Potential-based interview — assess learning ability and growth potential rather than past experience. | `process-verification-from-knowledge-base`: Knowledge Base interview — generate questions from your knowledge base documents..
conversation_idNoPass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request.
cover_image_urlNoCover image URL.
seniority_levelNoTarget seniority level for the role; auto-detected from the job description when omitted. Options — `entry-level`: Early-career or graduate roles. | `intermediate`: Some experience required. | `senior`: Experienced professional. | `managerial`: Team or department lead. | `director`: Director-level responsibility. | `executive`: C-suite or executive role..
description_longNoLong-form interview description (column `interview_description_long`). Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown
interview_salaryNoSalary range shown for the position. Blank is stored as null.
hiring_for_companyNoWho the position is really for. null (or an object with name null/blank) means hiring for yourself; { name: 'undisclosed' } for an unnamed external client; or { name: '<company>' } plus optional description/location/sector/company_size. Stored in creation_parameters.hiring_for_company.
interview_attemptsNoAllowed candidate attempts (1-20). Stored as result_scoring.max_retries.
country_availabilityNoWhich countries the interview / position is open to on the candidate portal, judged by the IP address the candidate opens it from (an unknown location only passes when countries_allowed / countries_allowed_eu are empty). From a closed country it is left out of the portal listings, and a direct link shows "not available in your region". Invited candidates (register_users / invite links) and candidates who already started keep access; API and MCP calls themselves are never restricted. Null = not used, every country.
interview_departmentNoDepartment the position belongs to. Blank is stored as null.
recruiter_profile_idNoProfile id of the recruiter owning this interview. Must be a merchant/merchant_owner/admin profile of the same merchant. null clears it.
interview_template_idNoId of the interview template (avatar/voice) to use. Must reference an existing interview_templates row. Also decides the modality — see list_avatars / merchant-avatar-list.
candidate_expectationsNoFree-text candidate expectations.
pdf_export_auto_configNoAuto-generate a candidate PDF report with these options once the interview completes. null disables auto-export.
recording_full_sessionNoFull interview-session recording (includes the avatar and voice) produced as a single file. Independent of `recording`. Omit/null to disable. Options — `audio_all`: Record the whole session audio (avatar + candidate voice) into a single file. Adds +0.2 credits. | `video_all`: Record the whole session video + audio (avatar + candidate) into a single file. Adds +0.4 credits..
required_pronunciationNoRequire pronunciation assessment (restricts to pronunciation-capable languages).
knowledge_base_store_idNoKnowledge base store id the interview draws context from; validated for existence. null unlinks it.
questions_random_subsetNoAsk only a random subset of the questions, as a fraction between 0.01 and 0.9. null asks all questions.
interview_available_tillNoISO date/time after which the interview is no longer available to candidates. null keeps it always available.
candidate_expectations_jsonNoStructured candidate expectations (the scoring rubric), bucketed by requirement level (weak/moderate/strong). null clears the rubric. Extra keys are preserved.
candidate_video_introductionNoWhether a candidate video introduction is hidden, optional or required. null is treated like hidden.
interview_conversation_speedNoConversation pace of the AI avatar. Omit/null keeps the template default pace. Options — `slower`: The avatar speaks more slowly — easier to follow for non-native speakers. | `normal`: Default speaking pace. | `faster`: The avatar speaks more quickly for a snappier conversation..
result_enable_edit_transcriptNoAllow editing the transcript on the result view.
candidate_notification_channelNoSMS / WhatsApp notifications to the candidate, sent alongside the e-mails: "reminders" = with both e-mail reminders (day 1 and day 3); "last_reminder" = only with the final day-3 reminder; "all" = invitation, both reminders and the pre-screening-accepted step. null switches them off. WhatsApp is tried first, SMS when the number is not on WhatsApp. Available on paid plans (Starter and above) and needs a phone number on the candidate.
regenerate_candidate_expectationsNoRe-derive the interview-level `candidate_expectations_json` scoring rubric from the resulting question list, the way job-interview-create-from-array derives it at creation time. Only applies when `questions` is sent, the interview type is `interview`, and `candidate_expectations_json` is not also being set explicitly (an explicit value wins).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
position_idYesThe id that was updated.
is_multistageYesTrue when the id resolved to a multi-stage position (position_def_set) rather than a single interview.
questions_diffNoWhat the question diff decided, question by question. Absent when `questions` was not sent.
updated_fieldsYesNames of the stored columns that were written, plus `status` when the lifecycle status was changed and `questions` when the question list was diffed.
_mcp_instructionsNoServer-issued metadata for this conversation.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedInput schema / properties / country_availability
      Added value: +{
      +  "description": "Which countries the interview / position is open to on the candidate portal, judged by the IP address the candidate opens it from (an unknown location only passes when countries_allowed / countries_allowed_eu are empty). From a closed country it is left out of the portal listings, and a direct link shows \"not available in your region\". Invited candidates (register_users / invite links) and candidates who already started keep access; API and MCP calls themselves are never restricted. Null = not used, every country.",
      +  "properties": {
      +    "countries_allowed": {
      +      "description": "Available ONLY to candidates in these countries (ISO 3166-1 alpha-2).",
      +      "example": [
      +        "PH",
      +        "IN"
      +      ],
      +      "items": {
      +        "pattern": "^[A-Za-z]{2}$",
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "countries_allowed_eu": {
      +      "description": "Adds every EU country (plus EEA and Switzerland) to countries_allowed.",
      +      "type": [
      +        "boolean",
      +        "null"
      +      ]
      +    },
      +    "countries_blocked": {
      +      "description": "NOT available to candidates in these countries (ISO 3166-1 alpha-2). Wins over the allowed side.",
      +      "example": [
      +        "US"
      +      ],
      +      "items": {
      +        "pattern": "^[A-Za-z]{2}$",
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "countries_blocked_eu": {
      +      "description": "Adds every EU country (plus EEA and Switzerland) to countries_blocked.",
      +      "type": [
      +        "boolean",
      +        "null"
      +      ]
      +    }
      +  },
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
  2. Changed1 schema field changed
    • changedInput schema / properties / conversation_id / description
      Previous value: -"Echo the conversation_id from the server's previous response. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it."New value: +"Pass the exact conversation_id from the server's previous response, unchanged. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it. Keep passing the same conversation_id for the rest of the conversation, including after later user messages or on a different task; do not reset it when the user starts a new request."
  3. Changed1 schema field changed
    • addedInput schema / properties / candidate_notification_channel
      Added value: +{
      +  "description": "SMS / WhatsApp notifications to the candidate, sent alongside the e-mails: \"reminders\" = with both e-mail reminders (day 1 and day 3); \"last_reminder\" = only with the final day-3 reminder; \"all\" = invitation, both reminders and the pre-screening-accepted step. null switches them off. WhatsApp is tried first, SMS when the number is not on WhatsApp. Available on paid plans (Starter and above) and needs a phone number on the candidate.",
      +  "enum": [
      +    "reminders",
      +    "last_reminder",
      +    "all",
      +    null
      +  ],
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  4. Changed2 schema fields changed
    • addedInput schema / properties / conversation_id
      Added value: +{
      +  "description": "Echo the conversation_id from the server's previous response. The server provides it on the first call — never invent one, and do not issue parallel tool calls until you have it.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / _mcp_instructions
      Added value: +{
      +  "description": "Server-issued metadata for this conversation.",
      +  "properties": {
      +    "conversation_id": {
      +      "description": "The server-issued conversation identifier.",
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
  5. Changed4 schema fields changed
    • changedInput schema / properties / interview_tone / description
      Previous value: -"Tone — configures the AI avatar's speaking style and the follow-up questions it generates. Stored in creation_parameters; existing questions are NOT regenerated. Suggested values — `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level — short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate.. Case-insensitive; other strings are accepted but unknown tones fall back to the default."New value: +"Tone — configures the AI avatar's speaking style and the follow-up questions it generates. Stored in creation_parameters; existing questions are NOT regenerated. Case-insensitive; omit to default to relaxed. Options — `relaxed`: Friendly and conversational tone that helps candidates feel at ease. | `simple`: Plain language at CEFR A2 level — short sentences and simple words. | `professional`: Formal and business-like approach suitable for senior roles. | `persuasive`: Engaging style that encourages candidates to elaborate. | `exact`: Asks the questions exactly as provided, without rephrasing — for interviews built from your own questions (create_interview_from_questions) where the wording is a script.."
    • addedInput schema / properties / interview_tone / enum
      Added value: +[
      +  "relaxed",
      +  "simple",
      +  "professional",
      +  "persuasive",
      +  "exact",
      +  null
      +]
    • changedInput schema / properties / pdf_export_auto_config / properties / mojito_language_code / description
      Previous value: -"Report language code (platform-languages.json code)."New value: +"Report language code (a platform-languages.json code)."
    • addedInput schema / properties / pdf_export_auto_config / properties / mojito_language_code / enum
      Added value: +[
      +  "ar",
      +  "bg",
      +  "zh",
      +  "hr",
      +  "cs",
      +  "da",
      +  "nl",
      +  "en",
      +  "fil",
      +  "fi",
      +  "fr",
      +  "de",
      +  "el",
      +  "hi",
      +  "hu",
      +  "id",
      +  "it",
      +  "ja",
      +  "ko",
      +  "ms",
      +  "no",
      +  "pl",
      +  "pt",
      +  "br",
      +  "ro",
      +  "ru",
      +  "sk",
      +  "es",
      +  "sv",
      +  "ta",
      +  "th",
      +  "tr",
      +  "uk",
      +  "vi",
      +  null
      +]
  6. Changed1 schema field changed
    • addedInput schema / properties / environment
      Added value: +{
      +  "description": "Which of your webhook environments results from this interview are delivered to. Defaults to production. Options — `production`: Live hiring. Results reach the webhooks configured as production. This is the default when the field is omitted. | `uat`: User-acceptance testing - an isolated environment for pre-release verification. | `development`: Development/testing. Use for interviews created by a test or preview app so their results never reach the production webhook. | `demo`: Demonstrations and sales trials..",
      +  "enum": [
      +    "production",
      +    "uat",
      +    "development",
      +    "demo",
      +    null
      +  ],
      +  "example": "production",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  7. Changed1 schema field changed
    • changedInput schema / properties / pdf_export_auto_config / properties / template / description
      Previous value: -"Report layout: classic (default), modern, or one_pager."New value: +"Report layout: classic, modern, or one_pager. Omit for the merchant default (modern when unset)."
  8. Changed1 schema field changed
    • addedInput schema / properties / pdf_export_auto_config / properties / template
      Added value: +{
      +  "description": "Report layout: classic (default), modern, or one_pager.",
      +  "enum": [
      +    "classic",
      +    "modern",
      +    "one_pager",
      +    null
      +  ],
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  9. Changed1 schema field changed
    • changedInput schema / properties / description_long / description
      Previous value: -"Long-form interview description (column `interview_description_long`), Markdown."New value: +"Long-form interview description (column `interview_description_long`). Rendered as Markdown on the candidate-facing position page, including chips, callouts, cards, columns and buttons — formatting guide: https://developer.jobmojito.com/cookbooks/format-content-with-markdown"
  10. Changed2 schema fields changed
    • changedOutput schema / properties / questions_diff / description
      Previous value: -"What the question diff decided, question by question. Null when `questions` was not sent."New value: +"What the question diff decided, question by question. Absent when `questions` was not sent."
    • changedOutput schema / required
      Previous value: -[
      -  "position_id",
      -  "is_multistage",
      -  "updated_fields",
      -  "questions_diff"
      -]New value: +[
      +  "position_id",
      +  "is_multistage",
      +  "updated_fields"
      +]
  11. Changed5 schema fields changed
    • addedInput schema / properties / questions
      Added value: +{
      +  "description": "OPTIONAL. Omit this field entirely and the interview's questions are left exactly as they are — this endpoint only touches questions when you send the array. When you do send it, send the COMPLETE list you want the interview to end up with, in order, in the same format job-interview-create-from-array accepts and job-interview-get returns: there is no way to change a single question on its own, so read the interview, edit that array, and send the whole thing back. An empty array is rejected. It is applied as a DIFF, not a replace, so resending the array job-interview-get gave you changes nothing at all. Each entry is matched against what is stored — first on `external_id`, then on `id`, then on identical content — and: an entry matching an unchanged question keeps that question exactly as it is, including its answer rules and any rendered avatar video; an entry matching a question whose content differs unlinks the old question and creates a new one in its place (fields you omit are carried over from the old one); an entry matching nothing is created; and a stored question no entry matches is unlinked. `questions_diff` in the response reports exactly what was decided. Questions are shared records, so nothing is ever deleted — removing one only unlinks it from this interview, and an edit is always unlink-old + create-new so the change cannot leak into another interview reusing the same question. The welcome, thank-you and instructional-video steps are not part of this array and are left in place. Single-stage interviews only; for a multi-stage position, update its interview stages individually.",
      +  "items": {
      +    "additionalProperties": {},
      +    "properties": {
      +      "candidate_expectations_json": {
      +        "description": "Per-question candidate expectations, bucketed by requirement level (weak/moderate/strong). Extra keys are preserved.",
      +        "properties": {
      +          "moderate": {
      +            "description": "Requirements expected of a solid, competent candidate.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": [
      +              "array",
      +              "null"
      +            ]
      +          },
      +          "strong": {
      +            "description": "High-bar requirements only standout candidates clear.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": [
      +              "array",
      +              "null"
      +            ]
      +          },
      +          "weak": {
      +            "description": "Baseline requirements every viable candidate should meet (table stakes).",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": [
      +              "array",
      +              "null"
      +            ]
      +          }
      +        },
      +        "type": [
      +          "object",
      +          "null"
      +        ]
      +      },
      +      "conditional_question_main_id": {
      +        "description": "For a conditional question, the id (the \"id\" field above) of the parent question in this same array that triggers it. The parent must appear earlier in the array than the conditional question referencing it.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "duration": {
      +        "description": "Answer duration in seconds for this question.",
      +        "type": [
      +          "number",
      +          "null"
      +        ]
      +      },
      +      "external_data": {
      +        "additionalProperties": {},
      +        "description": "Arbitrary JSON metadata stored on the question.",
      +        "type": [
      +          "object",
      +          "null"
      +        ]
      +      },
      +      "external_id": {
      +        "description": "External identifier stored on the question. job-interview-update matches on this first, so an ATS that owns stable ids can send its own array and have the diff line up without round-tripping our ids.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "id": {
      +        "description": "Identifier for this question. job-interview-get returns the question's real id here; send it back to job-interview-update so an unchanged question keeps its existing record (and with it its answer rules and any rendered avatar video). Also the handle another question references via conditional_question_main_id. On job-interview-create-from-array it is a caller-local value, only needed for those references.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "is_candidate_asking_recruiter": {
      +        "description": "Candidate-asks-recruiter prompt (view 'candidate asking recruiter').",
      +        "type": [
      +          "boolean",
      +          "null"
      +        ]
      +      },
      +      "is_conditional": {
      +        "description": "Conditional follow-up question (view 'with listening conditional'). Use with conditional_question_main_id.",
      +        "type": [
      +          "boolean",
      +          "null"
      +        ]
      +      },
      +      "is_expert": {
      +        "description": "Expert listening question (view 'with listening expert').",
      +        "type": [
      +          "boolean",
      +          "null"
      +        ]
      +      },
      +      "is_multiple_choice": {
      +        "description": "Multiple-choice question (view 'multiple choice').",
      +        "type": [
      +          "boolean",
      +          "null"
      +        ]
      +      },
      +      "is_without_scoring": {
      +        "description": "Question is asked but not scored (view 'without scoring').",
      +        "type": [
      +          "boolean",
      +          "null"
      +        ]
      +      },
      +      "knowledge_base_id": {
      +        "description": "Knowledge-base store id (uuid) the question draws context from.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "label": {
      +        "description": "Optional label/tag stored on the question.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "mojito_language_code": {
      +        "description": "Per-question language override (one of the platform-languages.json codes). Inherits the interview language when omitted.",
      +        "enum": [
      +          "ar",
      +          "bg",
      +          "zh",
      +          "hr",
      +          "cs",
      +          "da",
      +          "nl",
      +          "en",
      +          "fil",
      +          "fi",
      +          "fr",
      +          "de",
      +          "el",
      +          "hi",
      +          "hu",
      +          "id",
      +          "it",
      +          "ja",
      +          "ko",
      +          "ms",
      +          "no",
      +          "pl",
      +          "pt",
      +          "br",
      +          "ro",
      +          "ru",
      +          "sk",
      +          "es",
      +          "sv",
      +          "ta",
      +          "th",
      +          "tr",
      +          "uk",
      +          "vi",
      +          null
      +        ],
      +        "example": "en",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "question": {
      +        "description": "The question text shown to the candidate.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "question_alternatives": {
      +        "description": "Alternative phrasings for the question.",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": [
      +          "array",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "question"
      +    ],
      +    "type": "object"
      +  },
      +  "minItems": 1,
      +  "type": [
      +    "array",
      +    "null"
      +  ]
      +}
    • addedInput schema / properties / regenerate_candidate_expectations
      Added value: +{
      +  "description": "Re-derive the interview-level `candidate_expectations_json` scoring rubric from the resulting question list, the way job-interview-create-from-array derives it at creation time. Only applies when `questions` is sent, the interview type is `interview`, and `candidate_expectations_json` is not also being set explicitly (an explicit value wins).",
      +  "example": false,
      +  "type": [
      +    "boolean",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / questions_diff
      Added value: +{
      +  "description": "What the question diff decided, question by question. Null when `questions` was not sent.",
      +  "properties": {
      +    "added": {
      +      "description": "Ids of the questions created for entries that matched nothing stored.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "kept": {
      +      "description": "Questions left exactly as they were, record and all.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "question_ids": {
      +      "description": "The interview's full ordered step list after the update, including the welcome / thank-you / instructional steps this endpoint does not manage.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "reactivated": {
      +      "description": "True when the interview was already active and was re-published so the new questions go live.",
      +      "type": [
      +        "boolean",
      +        "null"
      +      ]
      +    },
      +    "removed": {
      +      "description": "Ids unlinked because no entry in the request matched them. The question records themselves still exist.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "replaced": {
      +      "description": "Edited questions: the old record was unlinked and a new one created, so the change cannot leak into other interviews reusing it.",
      +      "items": {
      +        "properties": {
      +          "from": {
      +            "description": "The id that was unlinked.",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "to": {
      +            "description": "The id of the question created in its place.",
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          }
      +        },
      +        "required": [
      +          "from",
      +          "to"
      +        ],
      +        "type": "object"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    }
      +  },
      +  "required": [
      +    "kept",
      +    "added",
      +    "removed",
      +    "replaced",
      +    "question_ids",
      +    "reactivated"
      +  ],
      +  "type": "object"
      +}
    • changedOutput schema / properties / updated_fields / description
      Previous value: -"Names of the stored columns that were written, plus `status` when the lifecycle status was changed."New value: +"Names of the stored columns that were written, plus `status` when the lifecycle status was changed and `questions` when the question list was diffed."
    • changedOutput schema / required
      Previous value: -[
      -  "position_id",
      -  "is_multistage",
      -  "updated_fields"
      -]New value: +[
      +  "position_id",
      +  "is_multistage",
      +  "updated_fields",
      +  "questions_diff"
      +]
  12. Added

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true and idempotentHint=true, so the safety profile is known, and the description goes well beyond them: partial-update semantics (only sent fields written, null clears nullable), the diff mechanics (match on external_id then id then content; edited questions unlink-and-recreate; nothing is ever deleted because questions are shared records), the active-interview restriction on question edits, and the immutable `mojito_language_code`.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and scannable, but the description is essentially written twice: the second paragraph restates the first's points about questions handling, the welcome/thank-you steps, and the multi-stage 422. A large fraction of the text is redundant with itself, which dilutes rather than adds information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 44-parameter mutation tool with an output schema available, the description covers what the structured fields cannot: partial-write semantics, question-diff behavior and its response field (`questions_diff`), status-dependent editability, and immutable fields. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real operational meaning on top of the schema — the read-edit-resend workflow for `questions`, the fact that re-sending an unchanged array is a no-op, and the `tags`-as-catalogue-mapping key. These are workflow semantics rather than mere parameter restatement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Update the configuration of an existing interview/position') and immediately scopes it: single-stage interview vs multi-stage position, with the exact field families affected (name, description, avatar template, recording, scoring, tags). An agent can distinguish it from create_interview and set_interview_state without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when/when-not guidance: omit `questions` to leave questions alone, read the interview first and send the whole array back, use `tags` for coaching-catalogue placement, and for multi-stage positions update the individual stage rather than sending interview-only fields. It even names the failing field (`candidate_expectations_json`) and the 422 outcome.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.