check_content_grounding
Run a grounding scan on a document to check its factual claims against the team's context library, sorting each into supported, conflict, or gap. Waits ~20s inline; poll get_grounding_result with the scan_id if it returns running.
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
content_id | string | No | — | Existing document to scan. Pass it ALONE to scan the document as it stands - the safe default. |
content | string | No | — | Markdown to ground. Alone, it is stored as a new document. WITH content_id, it REPLACES that document's entire body - pass the full document, never a fragment. |
title | string | No | — | Only meaningful with content. Omit it and the title is taken from the first line. |
Input Schema
{
"type": "object",
"anyOf": [
{
"required": [
"content_id"
]
},
{
"required": [
"content"
]
}
],
"properties": {
"title": {
"type": "string",
"description": "Only meaningful with content. Omit it and the title is taken from the first line."
},
"content": {
"type": "string",
"description": "Markdown to ground. Alone, it is stored as a new document. WITH content_id, it REPLACES that document's entire body - pass the full document, never a fragment."
},
"content_id": {
"type": "string",
"format": "uuid",
"description": "Existing document to scan. Pass it ALONE to scan the document as it stands - the safe default."
}
},
"description": "One of content_id or content is required. Passing content TOGETHER with content_id replaces that document's entire body."
}Output Schema
{
"type": "object",
"properties": {
"claims": {
"type": "array",
"items": {
"type": "object",
"properties": {
"refs": {
"type": "array",
"items": {
"type": "object"
},
"description": "The context the claim was matched against."
},
"value": {
"type": [
"string",
"null"
]
},
"bucket": {
"enum": [
"supported",
"conflict",
"gap"
],
"type": "string"
},
"subject": {
"type": [
"string",
"null"
]
},
"claim_text": {
"type": "string"
},
"confidence": {
"type": "string",
"description": "A STRING, not a number - e.g. \"0.82\". Parse it before comparing."
}
}
},
"description": "Every factual claim extracted from the document."
},
"status": {
"enum": [
"running",
"complete",
"failed",
"none"
],
"type": "string",
"description": "running means the scan is still going - poll with scan_id."
},
"scan_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "The scan run. Poll get_grounding_result with this value."
},
"summary": {
"type": "object",
"properties": {
"gaps": {
"type": "integer",
"description": "Claims the library has nothing on."
},
"conflicts": {
"type": "integer",
"description": "Claims the library contradicts."
},
"supported": {
"type": "integer",
"description": "Claims the context library backs."
},
"total_claims": {
"type": "integer"
},
"corpus_freshness": {
"type": "string",
"description": "How current the context the scan checked against is."
}
}
},
"findings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"enum": [
"conflict",
"gap"
],
"type": "string"
},
"status": {
"enum": [
"pending",
"acknowledged",
"dismissed",
"resolved",
null
],
"type": [
"string",
"null"
]
},
"subject": {
"type": [
"string",
"null"
],
"description": "What the finding is about."
},
"link_url": {
"type": [
"string",
"null"
],
"description": "Opens the finding."
},
"severity": {
"type": [
"string",
"null"
]
},
"statement": {
"type": [
"string",
"null"
],
"description": "What the document says versus what the library says."
},
"finding_id": {
"type": "string",
"format": "uuid",
"description": "Pass to apply_grounding_fix."
},
"suggested_fix": {
"type": [
"object",
"null"
],
"description": "The full recommended update. Review this with the user before applying."
},
"recommendation": {
"type": [
"string",
"null"
],
"description": "What Marcora suggests doing."
},
"context_item_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Where applying would write. null means the fix targets the document itself."
}
}
},
"description": "The conflicts and gaps worth acting on. Pass a finding_id to apply_grounding_fix."
},
"link_url": {
"type": "string",
"format": "uri",
"description": "Opens the document with its grounding panel open. Hand this to the user."
},
"content_id": {
"type": "string",
"format": "uuid",
"description": "The document that was scanned."
},
"corpus_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"source": {
"type": [
"string",
"null"
]
},
"link_url": {
"type": [
"string",
"null"
],
"description": "null when there is nothing to link to."
},
"context_item_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "null for entries that are not context items, such as project briefs."
},
"content_category": {
"type": [
"string",
"null"
]
}
}
},
"description": "The context the scan was checked against."
},
"details_visible": {
"type": "boolean",
"description": "false when you are not the document's creator - you get counts only, no claim or finding detail."
}
},
"description": "The grounding envelope. check_content_grounding and get_grounding_result return exactly this shape, so one handler works for both."
}Instructions
When to use: the user wants to know whether a document is accurate and consistent with what their company has already said - "check this against our context", "is this on-message", "fact-check this draft". It is also the natural next step after you draft something for them.
Runs a grounding scan on a document: it extracts the document's factual claims and sorts each one into supported (the context library backs it), conflict (the library says something different), or gap (the library has nothing on it). You get back the claims, the findings, and the context it was checked against.
This closes the loop for agent-driven writing - draft, ground, review, apply, re-ground - without leaving the conversation.
Three entry modes
content_idalone - scan a document that already exists in Marcora. The safe default.contentalone - hand over markdown; Marcora stores it as a new document and scans it. The newcontent_idcomes back in the response.content_id+content- replaces that document's entire body with the markdown you pass, then re-scans. This is the revise-and-re-ground path.
Passing neither is an error.
:warning:
contenttogether withcontent_idis a whole-document overwriteIt replaces the document's ENTIRE body - identical to
update_content.This is never a "check this section" operation. If a user asks you to ground one paragraph or section of a document that already exists, do not pass that fragment with its
content_id. You would replace the whole document with the fragment and destroy the rest of it - silently, with no error and no warning.
- To check part of an existing document: pass
content_idalone and scan the document as it stands.- To revise and re-check: pass the full revised document, not a fragment.
Timing - read this before calling
This waits up to about 20 seconds inline. If the scan finishes inside that window you get the full result straight back. Otherwise you get status: "running" with a scan_id.
A fresh scan usually needs 120-150 seconds. When you get running, poll get_grounding_result with that scan_id every 15-30 seconds. Do not call check_content_grounding again - that starts a second, redundant scan.
:warning: Poll by
scan_id, nevercontent_idWhen polling a running scan, pass the
scan_idyou were handed. Pollingget_grounding_resultbycontent_idreturns the document's previous completed scan markedcomplete- so you would read a stale result and believe the new scan had already finished. Nothing errors; the answer is just quietly the wrong one.
Re-scanning an unchanged document is fast (a few seconds), because unchanged claims are reused.
Requirements
Grounding requires the Command plan with an active subscription and available AI credits.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
content_id |
string (uuid) | No* | Existing document to scan. Pass it alone to scan the document as it stands - the safe default |
content |
string | No* | Markdown to ground. Alone, stored as a new document. With content_id, replaces that document's entire body - pass the full document, never a fragment |
title |
string | No | Only meaningful with content. Omit and the title is taken from the first line |
* One of content_id or content is required.
Output
The grounding envelope: content_id, scan_id, status, link_url, summary, findings[], claims[], corpus_items[], details_visible.
Two field-level traps worth knowing:
confidenceon each claim is a string, e.g."0.82"- not a number.details_visible: falsemeans you are not the document's creator, so you get counts only rather than claim and finding detail.
Hand the user the link_url - it opens the document with its grounding panel.
Errors
- Provide either 'content_id' or 'content' (400) - neither was supplied.
- Not a valid UUID (400) - malformed
content_id. - Content not found (404) - no such document in your team.
- ci_not_eligible (403) - the team is not on the Command plan, has no active subscription, or is out of AI credits.
Example prompts
- "Ground this draft against our context library"
- "Does this blog post contradict anything we've published?"
- "Rewrite the pricing section and re-check it"