Skip to content
vocapable.Docs

Custom questions

Your agent asks questions two ways: objectives configured on the agent (every call of that version asks them), and per-call questions attached to a single POST /v1/calls launch. Both record answers through the same tool, land in the same SurveyResponse, and arrive in the same webhooks.

Open Agents → your agent → Settings → Tasks and questions. Add the question text, then select Score this answer to compare responses in results. Choose satisfaction (1–5), recommendation (0–10), yes/no, or custom choices. Standard answer types include their scores automatically; expand Answer scores to review or change them. Custom choices let you name each answer and choose its score. Include the choices in the question so callers know how to answer.

The editor assigns a stable question ID. Existing IDs, scores and custom fields are retained when you edit the wording. Advanced scoring contains the question weight and ID; keep the ID when updating the same question. Changing answer type replaces its score mapping, so review the new scores before saving.

Saving scored questions also enables answer capture on that draft if needed, retaining its other actions. Turning scoring off does not disable existing answer capture. Removing a question asks for confirmation. Save prepares the draft; publishing, release checks and the company’s paid service access remain separate. If someone updated the draft while you were editing, reload the saved questions before trying again.

Objectives live on the agent definition and freeze into each published version. A scored question carries a scoring block:

{
"objectives": [
{
"id": "csat_overall",
"prompt": "How satisfied were you with your visit, one to five?",
"scoring": {
"scale": "csat",
"mapping": { "1": 1, "2": 2, "3": 3, "4": 4, "5": 5 },
"weight": 1
}
},
{
"id": "would_return",
"prompt": "Would you come back?",
"scoring": {
"scale": "ordinal",
"points": 3,
"mapping": { "no": 1, "maybe": 2, "yes": 3 }
}
},
{ "id": "verbatim", "prompt": "Anything else you want us to know?" }
]
}

Four scales: csat (1–5), nps (0–10), boolean ("true"/"false" keys), and ordinal (declare points and a mapping with exactly that many choices). A question with no scoring block is unscored - the answer is still recorded verbatim. A scored question requires an id (answers key on it) and question text.

The shape is contract-enforced: a malformed block - an unknown scale, mapping keys outside the scale’s answer set, ordinal without a matching points - is a 422 at write time and a 409 objective_scoring_invalid at publish, with errors[] naming each broken field. It cannot silently publish and yield score: null.

An objective can also declare capture_type as string, number, or boolean for information extracted into post-call summaries. For example:

{
"id": "years_experience",
"prompt": "How many years of driving experience do you have?",
"capture_type": "number"
}

Typed captures require a unique id or legacy name and question text. In the portal objective editor, choose Text, Number, or Yes or no under Captured answer type. Unspecified preserves the existing behavior. This setting controls summary extraction; it does not alter survey scoring or make an assignment or hiring decision.

Where automatic summaries are enabled, missing or refused answers remain absent; an explicit no or zero remains a captured answer. Replies with incorrect types are rejected and retried instead of silently converting strings into answers. Declaring a type does not enable automatic summaries for a deployment without a qualified model.

POST /v1/calls accepts up to 10 additional questions and up to 20 context facts for that one call:

{
"agent_id": "agnt_01J9…",
"contact_id": "cont_01J9…",
"questions": [
{
"id": "q_delivered",
"prompt": "Did yesterday's delivery arrive on time?",
"scoring": { "scale": "boolean", "mapping": { "true": 1, "false": 0 } }
}
],
"context": { "order_number": "A-1009", "delivery_date": "yesterday" }
}

The rules:

  • Additive only. A per-call question may not reuse an id the version’s objectives already carry - 409 call_question_conflict. The published, evaluation-gated objectives are never overridden per call.
  • The version must grant record_survey_answer. Otherwise the answers would have no tool to record them - 409 call_questions_unsupported at launch, not a silent no-op after the call.
  • Context keys are snake_case strings, ≤500 characters each, ≤8 KiB total. Platform-authored keys (current_datetime, contact_name, …) are refused - you cannot shadow what the platform tells the agent.

Per-call questions ride outside the agent’s cached prompt prefix, so they add no latency penalty, and they score into the same SurveyResponse as version objectives.

  • Push: survey.completed and call.ended webhooks carry answers and score inline - see Receive results.
  • Pull: GET /v1/survey-responses?call_id=… returns {answers: {id: {answer, verbatim_quote, confidence}}, score, completion_status}.
  • Aggregate: GET /v1/campaigns/{id}/survey-rollup for campaign questions.

The score is computed once, at call completion, from the exact question set the call ran - deterministic and reproducible; editing the agent later never restates a past response.