create_campaign, update_campaign, start_campaign, pause_campaign, resume_campaign,
add_contacts, add_webhook, remove_webhook, chat_project, start_full_corpus_analysis) require the write capability —
read-only keys receive a structured read_only_key error. Legacy mcp-scoped keys have full ordinary
tool access.
The three confidential-corpus read tools are intentionally stricter. get_corpus_manifest,
get_corpus_manifest_page, and get_corpus_record require the exact
protected_corpus:<campaign UUID> scope for that campaign.
Ordinary read-only, full-access, *, and legacy keys do not grant this access. A workspace admin must
create the short-lived Confidential analysis key, which pairs normal read access with the exact
campaign grant and no write capability.
Errors are structured: {"error": "<human message>", "code": "<stable code>", "hint": "<what to do next>"}.
Exceeding the per-key tool-call budget returns code rate_limited; retry after a minute.
Campaigns
list_campaigns
Lists campaigns in the workspace, most recently updated first.
Returns:
{"campaigns": [...], "limit", "offset", "has_more"} — each campaign summary carries id, name, status, channel, language, schedule (timeframe_start, response_deadline, timezone, invitations_scheduled_for), contact counts, and completion_threshold_percent.
get_campaign
Fetches a single campaign by id: full config, schedule, topics with typed questions (type, options, component_config), contacts (with invitation_sent_at), and progress counts.
create_campaign
Creates a new campaign in draft status. Call start_campaign to launch it.
Topic shape:
{name, goal, priority, success_threshold, sub_topics, questions}. Question shape: {text, required, type, options, component_config} with types open_ended (default), single_choice, multiple_choice, likert_scale, ranking, statement, range_slider, matrix. Ranking/matrix/range_slider questions need a component_config (e.g. ranking {items: [{id, label}]}, matrix {rows, columns}, range_slider {min, max, step}).
update_campaign
Partially updates a campaign — only the fields you pass change. Works on draft, active, and paused campaigns (completed ones are read-only; the channel is locked after launch). Schedule changes on an active campaign retarget the pending invitation send; already-sent invitations are never re-sent.
Takes interview_id plus any of the create_campaign fields above (except topics/contacts).
start_campaign
Launches a campaign: validates, marks it active, and sends the invitations on the campaign’s channel — or, when the campaign has a future start date, schedules them (invitations_scheduled_for in the response tells you when). Validation failures leave the campaign in draft and say what to fix.
pause_campaign / resume_campaign
Lifecycle controls. Each takes interview_id and returns the new status.
add_contacts
Bulk-adds contacts. On an active campaign the new contacts are invited right away — unless the campaign’s start date is still in the future, in which case their invitations are held with everyone else’s.
Returns
{created, invitations_sent, invitations_scheduled_for, message}.
get_progress
Returns per-status contact counts, completion percent vs. completion_threshold_percent, the soft response_deadline, and invitations_scheduled_for when the send is still pending.
Transcripts
list_conversations
Lists individually accessible conversations in a campaign, newest first. Report-only responses do not appear here;
use start_full_corpus_analysis when they should contribute through protected aggregate patterns.
Returns:
{"conversations": [...], "limit", "offset", "has_more"}.
get_transcript
Returns full transcript text plus contact metadata (respecting the campaign’s anonymity settings).
get_corpus_manifest
Returns the complete, untruncated index of every completed or contentful non-test response in one
campaign (scope: "completed_or_contentful_conversations"). Completed responses remain represented
even when no transcript content is available; unfinished responses enter only after they contain
source material. Use this when a specifically authorized agent must analyze protected interviews
without Ontora first summarizing or cutting their source material.
Each record reference carries a stable pseudonymous
response_id, completion and transcript state,
release status, transcript source/revision/turn count, answered-question count, guide_hash,
question_mapping_status, question_mapping_conflict_count, and record_hash. The manifest also reports
complete coverage counts, counts by transcript source, how many records contain question-mapping gaps or
source/resolution conflicts, exclusions, the interview guide and its hash, manifest_hash,
max_record_count: 500, max_turns_per_record, max_record_bytes, max_export_bytes, and
truncated: false. A corpus over any advertised bound fails as a whole; it never returns a misleading
prefix or partial record.
This is the full manifest contract used by REST clients, the Ontora CLI, and local export integrity
checks. In LangDock, prefer the compact paginated tool below so a large record index does not consume
the analysis context.
get_corpus_manifest_page
Returns one compact, ordered window of the same canonical manifest. It omits the full guide and
nonessential reference fields while retaining the snapshot hash, complete-corpus coverage totals,
release-status counts, mapping quality counts, exclusions, guide hash, and the stable IDs/hashes needed
to fetch records.
The response includes
schema_version, campaign_id, manifest_hash, truncated,
total_records, completion and transcript coverage, counts_by_release_status, question-mapping gap
and conflict totals, excluded_by_reason, guide_hash, and pagination fields offset, limit,
returned_count, has_more, and next_offset. records contains compact references with each
response_id and record_hash.
truncated: false describes the complete source corpus; a page with has_more: true is intentionally
partial, not truncated. Follow next_offset until has_more is false and verify that the collected set
contains exactly total_records unique response IDs.
get_corpus_record
Returns one full available source record with minimal preprocessing: campaign-guide fields, raw
response text, structured choice metadata when captured, and ordered transcript turns. A guide field’s
question_type remains authoritative—do not treat every field as mechanically closed-choice. Name,
email, person id, contact id, conversation id, and person-profile seniority_level metadata are not part of this
wire contract. Campaign-specific answers such as Q1 and Q2 remain in questions and the transcript. Job title and
department appear only when participant_metadata_output_allowed is true on an eligible
raw_citable record. metadata_sources gives field-level provenance: either
stored_interview_contact, linked_person, or null. The compatibility field
contact_metadata_source is one of those sources, mixed when the two fields came from different
sources, or null. audience_filter_attributes is a strict allowlist of the linked Personio
participant’s raw workgroup1, workgroup2, and workgroup3 values; Ontora does not map or derive
them. It may be populated for raw_citable and named, transcript-hidden aggregate_only records.
Anonymous-citable, name-hidden, report-only, and contactless records use an empty object. For
aggregate_only, workgroups are analysis dimensions only and must
not be reproduced as an individual attribution. The stable pseudonymous response_id remains
available for support and deduplication.
question_mapping_status: "gaps_present" and unmapped_response_turn_indexes explicitly identify
nonblank participant turns that could not be tied to the current guide. Do not silently assign those
turns to the nearest question. For every transcript turn, source_question_id preserves its stored
provenance while question_id and question_key are the resolved guide mapping;
question_mapping_source says whether that resolution came from a structured choice, an interviewer
prompt, surrounding context, or remained unmapped. Each question repeats this provenance as
mapping_source_counts and mapping_conflict_turn_indexes; structured_answer_present distinguishes
a captured choice/component answer from transcript-only content. The record-level
question_mapping_conflict_turn_indexes marks turns
where stored question/topic provenance conflicts with that independently resolved mapping. A record can
therefore have a complete mapping and still report conflicts. Use the resolved question_id/question_key
for Q grouping, retain the source/conflict fields for audit, and never overwrite or guess either. The
record and manifest guide_hash bind all Q1/Q2 aliases to the exact guide used for extraction.
Every record includes
release_status, verbatim_output_allowed, and output_policy:
raw_citablemay be quoted and cited under the approved analysis purpose.anonymous_citableandaggregate_onlyboth haveverbatim_output_allowed: falseandoutput_policy: "aggregate_paraphrase_only". Never quote, reproduce, attribute, expose, or make their individual answers reconstructable. Never infer or output participant department, job title, seniority, identity, or missing workgroups. They may contribute only non-reconstructable paraphrases and aggregates; their pseudonymous response IDs may be listed as support IDs.
get_corpus_manifest_page to collect the complete compact ID/hash
set in pages of 10–15 and pin every later page to the first manifest_hash. Then process one record per
Workflow Loop Agent execution. Visit every record exactly once with its expected_record_hash and
reduce only compact structured codings. Coverage is proven only when the Loop iteration count equals
total_records and its unique processed-ID set exactly equals the paged manifest ID set.
Finally, call page zero with the original expected_manifest_hash; any page, record, or snapshot hash
failure invalidates the partial analysis. A normal long chat cannot prove complete processing because
tool results consume context and older context may be optimized into summaries. Returning NDJSON as an
MCP file does not bypass that context constraint. For a verified local NDJSON snapshot, use ontora corpus export instead. See Connect Ontora to LangDock for the complete Workflow.
export_transcript_markdown
Returns the transcript rendered as Markdown.
export_report_markdown
Returns the full synthesis report (cartography + roadmap + personas) as Markdown. Takes interview_id.
Synthesis
get_roadmap
Returns solutions grouped by horizon. Takes interview_id.
get_personas
Returns per-contact personas, optionally filtered by department.
query_campaign
Runs a GraphRAG query across the campaign’s transcripts.
Returns:
{answer, patterns[], divergences[]}.
start_full_corpus_analysis
Starts a durable exhaustive analysis over every eligible completed answer in one campaign. Transcript-visible
answers may be cited. Responses marked report only also influence shared aggregate patterns, but their raw
turns, identities, conversation ids, and individual observations are never returned. Starting a run persists an
internal audit chat and consumes analysis compute, so this tool requires a write-capable key.
Returns the durable
run_id, internal audit session_id, status/phase, model, and coverage. Coverage separates
processed, usable, contributing, suppressed, citable, and aggregate-only answers.
get_full_corpus_analysis
Reads progress for a queued/running run or one paginated section of a completed result. It applies the same
serve-time privacy and source-freshness checks as Insights Chat. If transcript content or privacy changed after the
snapshot, it returns rerun_required: true instead of serving a stale result.
Ready results return
items, pagination metadata, citation keys, and coverage. Evidence can only contain sources
that are currently citable; report-only source material remains aggregate-only. If more answers finish after the
run snapshot, the response keeps the immutable result but also returns rerun_required: true,
rerun_reason: "new_responses_since_snapshot", coverage.added_since_snapshot, and current_completed. Start a
new run to include the current total.
People
list_people
Lists people in the workspace people directory, newest first.
Returns:
{"people": [...], "limit", "offset", "has_more"}.
get_person
Returns one person with their campaign participation and transcripts. Takes person_id.
list_people_groups
Returns the workspace’s people groups with member counts.
Knowledge graph
query
Full GraphRAG over the workspace knowledge graph: vector search → graph traversal → answer with citations. Takes prompt, optional vault_ids, depth, top_k.
search_documents
Semantic document search without LLM generation. Takes query, optional vault_ids, top_k, source_type.
get_entities
Browse entities and relationships. Optional entity_type, name_query, limit, include_relationships.
chat_project
Chat within a project context using the project’s vaults for retrieval. Takes project_id, message, optional session_id for follow-ups. Persists the chat session, so it requires the write capability — for stateless analysis use query or query_campaign.
Webhooks
list_webhooks
Returns the workspace’s webhook subscriptions.
add_webhook
Creates a subscription.
Returns
{id, secret, url, events} — the secret is only shown here.
remove_webhook
Deletes a subscription. Takes endpoint_id.