> For the complete documentation index, see [llms.txt](https://k-ai.gitbook.io/knowledge-ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://k-ai.gitbook.io/knowledge-ai/k-ai-mcp/audit-tools.md).

# Audit tools

Server: `https://api-audit.kai-studio.ai/mcp`. Authenticate with an [OAuth 2.1](/knowledge-ai/k-ai-mcp/oauth-flow.md) Bearer token, or — for unattended agents — an [Organization API key](/knowledge-ai/k-ai-mcp/autonomous-agents.md) sent directly in the `Authorization` header. Twenty-one curated tools — a subset of the 48 REST endpoints of the K-AI Audit API. The selection is conflict-first: start at the dashboard, iterate on open conflicts, confirm modifications, close (or ignore). Admin operations (instance create/delete, user membership, daily/per-user stats, duplicates, owner assignment) remain REST-only. See [Schema stability policy](/knowledge-ai/k-ai-mcp/schema-stability.md) for our compatibility commitments.

Every response is wrapped as `{"response": <payload>}`. Identifiers are prefixed and must be passed back as-is: `ki_` (K-AI instance), `qc_` (question conflict), `fc_` (full-audit conflict), `mq_` (mandatory question), `ms_` (missing subject), `kd_` (K-AI document).

## Priority

Two conflict surfaces exist, and they are not equal. Resolve **priority conflicts first**:

* Every **question conflict** (`audit_question_conflict_list`) is priority by definition — a user explicitly asked about the affected documents.
* Every **full-audit conflict linked to a mandatory question** — list with `only_linked_to_question=true`; these come back flagged `is_important` and share priority with question conflicts.

Unlinked full-audit conflicts are the secondary worklist — the broad per-instance review. Surface them only after the priority conflicts are exhausted, or when the expert explicitly asks for the broad audit.

## Tools by workflow

| Workflow group                      | Tools                                                                                                                                                                                          |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Workflow entry                      | `audit_dashboard_get`                                                                                                                                                                          |
| Conflict-first flow (primary)       | `audit_question_conflict_list` · `audit_question_conflict_get` · `audit_question_conflict_set_answer` · `audit_question_conflict_close` · `audit_question_conflict_ignore`                     |
| Document helpers                    | `audit_documents_get_by_ids` · `audit_documents_get_recommendations`                                                                                                                           |
| Mandatory questions (admin surface) | `audit_mandatory_question_list` · `audit_mandatory_question_create` · `audit_mandatory_question_force_analyze`                                                                                 |
| Missing subjects                    | `audit_missing_subject_list` · `audit_missing_subject_find` · `audit_missing_subject_list_questions` · `audit_missing_subject_set_state` · `audit_missing_subject_generate_compagnon_document` |
| Full-audit broad review             | `audit_full_audit_conflict_list` · `audit_full_audit_conflict_get` · `audit_full_audit_conflict_set_answer` · `audit_full_audit_conflict_ignore` · `audit_full_audit_conflict_close`           |

## Workflow entry

### audit\_dashboard\_get

Returns a summary of every audit instance the authenticated user can access, with per-instance counts of unresolved conflicts (questions + full-audit), pending mandatory questions, and pending missing subjects. The recommended entrypoint before drilling into a specific instance — every other audit operation needs a `ki_*` instance\_id taken from this dashboard.

**Input schema**

| Field    | Type | Required | Description        |
| -------- | ---- | -------- | ------------------ |
| *(none)* | —    | —        | Empty object `{}`. |

**Output schema**

| Field                                                  | Type            | Description                        |
| ------------------------------------------------------ | --------------- | ---------------------------------- |
| `response.instances`                                   | array           | Per-instance dashboard rows.       |
| `response.instances[].id`                              | string (`ki_*`) | K-AI instance identifier.          |
| `response.instances[].name`                            | string          | Display name.                      |
| `response.instances[].unresolved_conflicts`            | integer         | Open question-driven conflicts.    |
| `response.instances[].unresolved_full_audit_conflicts` | integer         | Open full-audit conflicts.         |
| `response.instances[].pending_mandatory_questions`     | integer         | Questions not yet resolved.        |
| `response.instances[].pending_missing_subjects`        | integer         | Missing subjects not yet resolved. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool("audit_dashboard_get", {})
print(result.structuredContent)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_dashboard_get",
  arguments: {},
});
console.log(result.structuredContent);
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/dashboard/get-my-dashboard \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{}'
```

{% endtab %}
{% endtabs %}

## Conflict-first flow (primary)

The canonical resolution path. Conflicts are surfaced from the dashboard, listed, inspected, answered, and closed. `audit_question_conflict_set_answer` returns inline AI recommendations the expert must apply (and confirm) before calling `audit_question_conflict_close`.

```mermaid
flowchart LR
    A[audit_dashboard_get] --> B[audit_question_conflict_list]
    B --> C[audit_question_conflict_get]
    C --> D[audit_question_conflict_set_answer]
    D -->|expert confirms modifications applied| E[audit_question_conflict_close]
    C -->|false positive, no change needed| F[audit_question_conflict_ignore]
```

### audit\_question\_conflict\_list

Paginated flat list of question-driven conflicts. Default `state_in=['OPEN']` — the primary expert worklist. Allowed states: `OPEN`, `ANSWERED`, `RECOMMENDATIONS_READY`, `MANAGED`, `IGNORED`. Filter by `question_id_in` (`mq_*`) or `document_id_in` (`kd_*`) to scope to a question or a document.

**Input schema**

| Field            | Type                             | Required        | Description                                                                                                                                      |
| ---------------- | -------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `instance_id`    | string (`ki_*`)                  | yes             | K-AI instance identifier.                                                                                                                        |
| `offset`         | integer (0–100000)               | no (default 0)  | Number of conflicts to skip.                                                                                                                     |
| `limit`          | integer (1–1000)                 | no (default 25) | Maximum conflicts to return.                                                                                                                     |
| `state_in`       | array of state \| null           | no              | Defaults to `['OPEN']`. One or more of `OPEN`, `ANSWERED`, `RECOMMENDATIONS_READY`, `MANAGED`, `IGNORED`. Empty array disables the state filter. |
| `question_id_in` | array of string (`mq_*`) \| null | no              | Restrict to conflicts triggered by these questions.                                                                                              |
| `document_id_in` | array of string (`kd_*`) \| null | no              | Restrict to conflicts touching these documents.                                                                                                  |

**Output schema**

| Field                                  | Type            | Description                                                                            |
| -------------------------------------- | --------------- | -------------------------------------------------------------------------------------- |
| `response`                             | array           | Conflicts, hydrated with `document_name` and `document_url`.                           |
| `response[].id`                        | string (`qc_*`) | Question-conflict identifier.                                                          |
| `response[].instance_id`               | string (`ki_*`) | Owning instance.                                                                       |
| `response[].question_id`               | string (`mq_*`) | Triggering mandatory question.                                                         |
| `response[].state`                     | enum            | `OPEN` \| `ANSWERED` \| `RECOMMENDATIONS_READY` \| `MANAGED` \| `IGNORED`.             |
| `response[].extraproperties.documents` | array           | Contradicting excerpts with `document_id`, `document_name`, `document_url`, `excerpt`. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_question_conflict_list",
    {"instance_id": "ki_abc123", "offset": 0, "limit": 25},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_question_conflict_list",
  arguments: { instance_id: "ki_abc123", offset: 0, limit: 25 },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/conflict/list-conflicts-for-instance \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "offset": 0, "limit": 25}'
```

{% endtab %}
{% endtabs %}

### audit\_question\_conflict\_get

Returns the full detail of a conflict — contradicting excerpts, triggering question, companion questions, state, and any saved expert answer. Required before calling `audit_question_conflict_set_answer` unless the list response already provides the full context.

**Input schema**

| Field         | Type            | Required | Description                   |
| ------------- | --------------- | -------- | ----------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.     |
| `conflict_id` | string (`qc_*`) | yes      | Question-conflict identifier. |

**Output schema**

| Field                                | Type            | Description                                                                |
| ------------------------------------ | --------------- | -------------------------------------------------------------------------- |
| `response`                           | object \| null  | Conflict detail, or null if not found.                                     |
| `response.id`                        | string (`qc_*`) | Conflict identifier.                                                       |
| `response.state`                     | enum            | `OPEN` \| `ANSWERED` \| `RECOMMENDATIONS_READY` \| `MANAGED` \| `IGNORED`. |
| `response.question_id`               | string (`mq_*`) | Triggering question.                                                       |
| `response.extraproperties.documents` | array           | Contradicting excerpts.                                                    |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_question_conflict_get",
    {"instance_id": "ki_abc123", "conflict_id": "qc_xyz789"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_question_conflict_get",
  arguments: { instance_id: "ki_abc123", conflict_id: "qc_xyz789" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/conflict/get \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "conflict_id": "qc_xyz789"}'
```

{% endtab %}
{% endtabs %}

### audit\_question\_conflict\_set\_answer

Records the expert resolution and immediately returns per-document modification recommendations inline. Sync LLM call (\~5s typical, \~10s p99). After receiving the response, render `recommendations` as a markdown table (`Document | Action`) and ask the expert whether each modification was applied before calling `audit_question_conflict_close`. The conflict stays in `RECOMMENDATIONS_READY` until `_close` is called. If `recommendations` is empty, the analysis could not be generated for this conflict — re-call `set_answer` to retry (do NOT call `audit_documents_get_recommendations`, it only reads persisted recommendations).

**Input schema**

| Field         | Type            | Required | Description                   |
| ------------- | --------------- | -------- | ----------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.     |
| `conflict_id` | string (`qc_*`) | yes      | Question-conflict identifier. |
| `answer`      | string          | yes      | Expert resolution text.       |

**Output schema**

| Field                                      | Type            | Description                                                     |
| ------------------------------------------ | --------------- | --------------------------------------------------------------- |
| `response.conflict`                        | object          | The updated conflict (state typically `RECOMMENDATIONS_READY`). |
| `response.recommendations`                 | array           | Per-document modification recommendations.                      |
| `response.recommendations[].conflict_id`   | string          | Source conflict.                                                |
| `response.recommendations[].document_id`   | string (`kd_*`) | Target document.                                                |
| `response.recommendations[].document_name` | string \| null  | Document name.                                                  |
| `response.recommendations[].document_url`  | string \| null  | Document URL for citation.                                      |
| `response.recommendations[].type`          | string          | Recommendation type.                                            |
| `response.recommendations[].action`        | string          | Recommended action text.                                        |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_question_conflict_set_answer",
    {"instance_id": "ki_abc123", "conflict_id": "qc_xyz789",
     "answer": "The 30-day refund window is the canonical policy."},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_question_conflict_set_answer",
  arguments: {
    instance_id: "ki_abc123",
    conflict_id: "qc_xyz789",
    answer: "The 30-day refund window is the canonical policy.",
  },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/conflict/set-answer \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id":"ki_abc123","conflict_id":"qc_xyz789","answer":"The 30-day refund window is the canonical policy."}'
```

{% endtab %}
{% endtabs %}

### audit\_question\_conflict\_close

Transitions a conflict to `MANAGED`. Requires the conflict to be in `RECOMMENDATIONS_READY` (or `ANSWERED`, if the expert decides to close without recommendations). Idempotent if already `MANAGED`. Call only after the expert confirmed every modification was applied (or accepts a partial application).

**Input schema**

| Field         | Type            | Required | Description                   |
| ------------- | --------------- | -------- | ----------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.     |
| `conflict_id` | string (`qc_*`) | yes      | Question-conflict identifier. |

**Output schema**

| Field      | Type           | Description                                |
| ---------- | -------------- | ------------------------------------------ |
| `response` | object \| null | The conflict in its new state (`MANAGED`). |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_question_conflict_close",
    {"instance_id": "ki_abc123", "conflict_id": "qc_xyz789"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_question_conflict_close",
  arguments: { instance_id: "ki_abc123", conflict_id: "qc_xyz789" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/conflict/set-managed \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "conflict_id": "qc_xyz789"}'
```

{% endtab %}
{% endtabs %}

### audit\_question\_conflict\_ignore

Marks a question conflict as `IGNORED` — the expert judged it a non-issue or a false positive that needs no change. Terminal: the conflict leaves the active worklist. Use this instead of `_close` when no document modification is warranted. Idempotent if already `IGNORED`. This is the `qc_` counterpart of `audit_full_audit_conflict_ignore`.

**Input schema**

| Field         | Type            | Required | Description                   |
| ------------- | --------------- | -------- | ----------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.     |
| `conflict_id` | string (`qc_*`) | yes      | Question-conflict identifier. |

**Output schema**

| Field      | Type           | Description                                |
| ---------- | -------------- | ------------------------------------------ |
| `response` | object \| null | The conflict in its new state (`IGNORED`). |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_question_conflict_ignore",
    {"instance_id": "ki_abc123", "conflict_id": "qc_xyz789"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_question_conflict_ignore",
  arguments: { instance_id: "ki_abc123", conflict_id: "qc_xyz789" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/conflict/set-ignored \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "conflict_id": "qc_xyz789"}'
```

{% endtab %}
{% endtabs %}

## Document helpers

Lookup tools used to enrich conflict displays and re-surface past recommendations.

### audit\_documents\_get\_by\_ids

Resolves document name, URL, and extra properties for up to 100 `kd_*` ids in one call. Side effect: caches the resolved `web_url` on `audit.documents` so subsequent conflict reads surface the URL directly from the database.

**Input schema**

| Field          | Type                                  | Required | Description               |
| -------------- | ------------------------------------- | -------- | ------------------------- |
| `instance_id`  | string (`ki_*`)                       | yes      | K-AI instance identifier. |
| `document_ids` | array of string (`kd_*`), 1–100 items | yes      | Document IDs to resolve.  |

**Output schema**

| Field                        | Type                    | Description                |
| ---------------------------- | ----------------------- | -------------------------- |
| `response`                   | array                   | Resolved document records. |
| `response[].id`              | string (`kd_*`) \| null | Document identifier.       |
| `response[].name`            | string \| null          | Document name.             |
| `response[].url`             | string \| null          | Web URL of the document.   |
| `response[].extraproperties` | object                  | Additional metadata.       |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_documents_get_by_ids",
    {"instance_id": "ki_abc123",
     "document_ids": ["kd_def456", "kd_ghi789"]},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_documents_get_by_ids",
  arguments: {
    instance_id: "ki_abc123",
    document_ids: ["kd_def456", "kd_ghi789"],
  },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/document/get-by-ids \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id":"ki_abc123","document_ids":["kd_def456","kd_ghi789"]}'
```

{% endtab %}
{% endtabs %}

### audit\_documents\_get\_recommendations

Returns every AI-generated modification recommendation accumulated on a document across all resolved conflicts of the current instance. Use when the expert returns to a document later or asks what to change without naming a specific conflict — **not** as a retry for a freshly-failed `audit_question_conflict_set_answer` (this endpoint only reads persisted recommendations).

**Input schema**

| Field         | Type            | Required | Description               |
| ------------- | --------------- | -------- | ------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier. |
| `document_id` | string (`kd_*`) | yes      | Target document.          |

**Output schema**

| Field                                    | Type            | Description                       |
| ---------------------------------------- | --------------- | --------------------------------- |
| `response.document_id`                   | string (`kd_*`) | Document identifier.              |
| `response.name`                          | string          | Document name.                    |
| `response.recommendations`               | array           | Persisted recommendation entries. |
| `response.recommendations[].conflict_id` | string (`qc_*`) | Originating conflict.             |
| `response.recommendations[].document_id` | string (`kd_*`) | Target document.                  |
| `response.recommendations[].type`        | string          | Recommendation type.              |
| `response.recommendations[].action`      | string          | Recommended action text.          |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_documents_get_recommendations",
    {"instance_id": "ki_abc123", "document_id": "kd_def456"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_documents_get_recommendations",
  arguments: { instance_id: "ki_abc123", document_id: "kd_def456" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/document/get-recommendations \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "document_id": "kd_def456"}'
```

{% endtab %}
{% endtabs %}

## Mandatory questions (admin surface)

Auxiliary worklist — the primary expert worklist is the conflict-first flow. Use these tools to inspect or manage mandatory questions directly, or to recover a `REFUSED` question by forcing re-analysis.

### audit\_mandatory\_question\_list

Lists mandatory questions for an instance. Use to inspect or manage questions directly, or to find a `REFUSED` question to pass to `audit_mandatory_question_force_analyze`.

**Input schema**

| Field         | Type               | Required | Description                               |
| ------------- | ------------------ | -------- | ----------------------------------------- |
| `instance_id` | string (`ki_*`)    | yes      | K-AI instance identifier.                 |
| `offset`      | integer (0–100000) | yes      | Number of items to skip.                  |
| `limit`       | integer (1–1000)   | yes      | Maximum items to return.                  |
| `state`       | string \| null     | no       | Optional mandatory-question state filter. |

**Output schema**

| Field                         | Type                     | Description                                   |
| ----------------------------- | ------------------------ | --------------------------------------------- |
| `response`                    | array                    | Mandatory questions.                          |
| `response[].id`               | string (`mq_*`)          | Question identifier.                          |
| `response[].question`         | string                   | Question text.                                |
| `response[].state`            | string                   | Current state.                                |
| `response[].instance_id`      | string (`ki_*`)          | Owning instance.                              |
| `response[].linked_conflicts` | array of string (`fc_*`) | Full-audit conflicts linked to this question. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_mandatory_question_list",
    {"instance_id": "ki_abc123", "offset": 0, "limit": 50},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_mandatory_question_list",
  arguments: { instance_id: "ki_abc123", offset: 0, limit: 50 },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/mandatory-question/list \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "offset": 0, "limit": 50}'
```

{% endtab %}
{% endtabs %}

### audit\_mandatory\_question\_create

Creates a mandatory question for an instance. The audit worker will analyse the question and surface any resulting conflicts on the conflict worklist.

**Input schema**

| Field         | Type            | Required | Description               |
| ------------- | --------------- | -------- | ------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier. |
| `question`    | string          | yes      | Question text.            |

**Output schema**

| Field      | Type    | Description                           |
| ---------- | ------- | ------------------------------------- |
| `response` | boolean | True when the question was persisted. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_mandatory_question_create",
    {"instance_id": "ki_abc123",
     "question": "What is the refund window for damaged goods?"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_mandatory_question_create",
  arguments: {
    instance_id: "ki_abc123",
    question: "What is the refund window for damaged goods?",
  },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/mandatory-question/create \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id":"ki_abc123","question":"What is the refund window for damaged goods?"}'
```

{% endtab %}
{% endtabs %}

### audit\_mandatory\_question\_force\_analyze

Forces re-analysis of a refused mandatory question. Only valid when the question is in `REFUSED` state. Recomputes its embedding and re-enqueues a `CheckQuestionTask` for the audit worker.

**Input schema**

| Field         | Type            | Required | Description                    |
| ------------- | --------------- | -------- | ------------------------------ |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.      |
| `question_id` | string (`mq_*`) | yes      | Mandatory question identifier. |

**Output schema**

| Field      | Type    | Description                       |
| ---------- | ------- | --------------------------------- |
| `response` | boolean | True when re-analysis was queued. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_mandatory_question_force_analyze",
    {"instance_id": "ki_abc123", "question_id": "mq_jkl012"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_mandatory_question_force_analyze",
  arguments: { instance_id: "ki_abc123", question_id: "mq_jkl012" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/mandatory-question/force-analyze \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "question_id": "mq_jkl012"}'
```

{% endtab %}
{% endtabs %}

## Missing subjects

Topics that should be covered but are absent from the document corpus. Workflow: list -> find detail -> list triggering questions -> answer companion questions -> generate companion document.

### audit\_missing\_subject\_list

Lists missing subjects for an instance.

**Input schema**

| Field         | Type               | Required | Description               |
| ------------- | ------------------ | -------- | ------------------------- |
| `instance_id` | string (`ki_*`)    | yes      | K-AI instance identifier. |
| `offset`      | integer (0–100000) | yes      | Number of items to skip.  |
| `limit`       | integer (1–1000)   | yes      | Maximum items to return.  |

**Output schema**

| Field                                              | Type            | Description                               |
| -------------------------------------------------- | --------------- | ----------------------------------------- |
| `response`                                         | array           | Missing subjects.                         |
| `response[].id`                                    | string (`ms_*`) | Missing-subject identifier.               |
| `response[].instance_id`                           | string (`ki_*`) | Owning instance.                          |
| `response[].state`                                 | string          | Current state.                            |
| `response[].extraproperties.compagnon_proposition` | string \| null  | Saved AI companion document text, if any. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_missing_subject_list",
    {"instance_id": "ki_abc123", "offset": 0, "limit": 50},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_missing_subject_list",
  arguments: { instance_id: "ki_abc123", offset: 0, limit: 50 },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/missing-subject/list \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "offset": 0, "limit": 50}'
```

{% endtab %}
{% endtabs %}

### audit\_missing\_subject\_find

Gets a missing subject detail.

**Input schema**

| Field         | Type            | Required | Description                 |
| ------------- | --------------- | -------- | --------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.   |
| `subject_id`  | string (`ms_*`) | yes      | Missing-subject identifier. |

**Output schema**

| Field                                            | Type            | Description                      |
| ------------------------------------------------ | --------------- | -------------------------------- |
| `response`                                       | object \| null  | Missing-subject detail, or null. |
| `response.id`                                    | string (`ms_*`) | Identifier.                      |
| `response.state`                                 | string          | Current state.                   |
| `response.extraproperties.compagnon_proposition` | string \| null  | Saved companion proposition.     |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_missing_subject_find",
    {"instance_id": "ki_abc123", "subject_id": "ms_mno345"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_missing_subject_find",
  arguments: { instance_id: "ki_abc123", subject_id: "ms_mno345" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/missing-subject/find \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "subject_id": "ms_mno345"}'
```

{% endtab %}
{% endtabs %}

### audit\_missing\_subject\_list\_questions

Lists the questions that triggered a missing-subject cluster.

**Input schema**

| Field         | Type            | Required | Description                 |
| ------------- | --------------- | -------- | --------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.   |
| `subject_id`  | string (`ms_*`) | yes      | Missing-subject identifier. |

**Output schema**

| Field                 | Type            | Description          |
| --------------------- | --------------- | -------------------- |
| `response`            | array           | Subject-questions.   |
| `response[].id`       | string (`mq_*`) | Question identifier. |
| `response[].question` | string          | Question text.       |
| `response[].state`    | string          | Question state.      |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_missing_subject_list_questions",
    {"instance_id": "ki_abc123", "subject_id": "ms_mno345"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_missing_subject_list_questions",
  arguments: { instance_id: "ki_abc123", subject_id: "ms_mno345" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/missing-subject/questions \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "subject_id": "ms_mno345"}'
```

{% endtab %}
{% endtabs %}

### audit\_missing\_subject\_set\_state

Updates the state of a missing subject.

**Input schema**

| Field         | Type            | Required | Description                 |
| ------------- | --------------- | -------- | --------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.   |
| `subject_id`  | string (`ms_*`) | yes      | Missing-subject identifier. |
| `state`       | string          | yes      | Target state.               |

**Output schema**

| Field      | Type | Description                                                |
| ---------- | ---- | ---------------------------------------------------------- |
| `response` | any  | Result of the transition (shape depends on the new state). |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_missing_subject_set_state",
    {"instance_id": "ki_abc123", "subject_id": "ms_mno345",
     "state": "MANAGED"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_missing_subject_set_state",
  arguments: {
    instance_id: "ki_abc123",
    subject_id: "ms_mno345",
    state: "MANAGED",
  },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/missing-subject/set-state \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id":"ki_abc123","subject_id":"ms_mno345","state":"MANAGED"}'
```

{% endtab %}
{% endtabs %}

### audit\_missing\_subject\_generate\_compagnon\_document

Produces an AI proposition for a document that would fill the gap identified by this missing subject. All companion questions must have been answered before generation can proceed.

**Input schema**

| Field         | Type            | Required | Description                 |
| ------------- | --------------- | -------- | --------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.   |
| `subject_id`  | string (`ms_*`) | yes      | Missing-subject identifier. |

**Output schema**

| Field      | Type   | Description                        |
| ---------- | ------ | ---------------------------------- |
| `response` | string | Generated companion document text. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_missing_subject_generate_compagnon_document",
    {"instance_id": "ki_abc123", "subject_id": "ms_mno345"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_missing_subject_generate_compagnon_document",
  arguments: { instance_id: "ki_abc123", subject_id: "ms_mno345" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/missing-subject/generate-compagnon-document \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "subject_id": "ms_mno345"}'
```

{% endtab %}
{% endtabs %}

## Full-audit broad review

The full-audit surface is a per-instance broad review independent of mandatory questions. **Lower priority than the conflict-first flow** — surface only after question-based conflicts are exhausted or when the expert explicitly asks for the broad audit.

### audit\_full\_audit\_conflict\_list

Lists full-audit conflicts for an instance. Default `state_in=['DETECTED']`. Allowed states: `DETECTED`, `REDETECTED`, `MANAGED`, `IGNORED`, `DISAPPEARED`. Pass `state_in=[]` for all states except `DISAPPEARED`. Pass `only_linked_to_question=true` to get just the priority subset — conflicts linked to a mandatory question, flagged `is_important` (see [Priority](#priority)).

**Input schema**

| Field                     | Type                   | Required           | Description                                                                              |
| ------------------------- | ---------------------- | ------------------ | ---------------------------------------------------------------------------------------- |
| `instance_id`             | string (`ki_*`)        | yes                | K-AI instance identifier.                                                                |
| `offset`                  | integer (0–100000)     | no (default 0)     | Number of conflicts to skip.                                                             |
| `limit`                   | integer (1–1000)       | no (default 500)   | Maximum conflicts to return.                                                             |
| `state_in`                | array of state \| null | no                 | Defaults to `['DETECTED']`.                                                              |
| `only_linked_to_question` | boolean                | no (default false) | When `true`, return only conflicts linked to a mandatory question (the priority subset). |

**Output schema**

| Field                         | Type                     | Description                                                                            |
| ----------------------------- | ------------------------ | -------------------------------------------------------------------------------------- |
| `response`                    | array                    | Full-audit conflicts.                                                                  |
| `response[].id`               | string (`fc_*`)          | Full-audit conflict identifier.                                                        |
| `response[].state`            | enum                     | `DETECTED` \| `REDETECTED` \| `MANAGED` \| `IGNORED` \| `DISAPPEARED`.                 |
| `response[].subject`          | string \| null           | Subject of the conflict.                                                               |
| `response[].explanation`      | string \| null           | Explanation of the conflict.                                                           |
| `response[].documents`        | array                    | Involved documents (`doc_id`, `document_name`, `document_url`).                        |
| `response[].linked_questions` | array of string (`mq_*`) | Mandatory questions this conflict is linked to.                                        |
| `response[].is_important`     | boolean                  | `true` when `linked_questions` is non-empty — shares priority with question conflicts. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_full_audit_conflict_list",
    {"instance_id": "ki_abc123", "offset": 0, "limit": 100},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_full_audit_conflict_list",
  arguments: { instance_id: "ki_abc123", offset: 0, limit: 100 },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/full-audit/list \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "offset": 0, "limit": 100}'
```

{% endtab %}
{% endtabs %}

### audit\_full\_audit\_conflict\_get

Returns subject, explanation, involved documents (hydrated with `document_name` + `document_url`), companion questions (`compagnon_questions`), the expert answer if saved, and structured per-document recommendations (`compagnon_recommendations`) if generated. Present companion questions to the expert before collecting an answer.

**Input schema**

| Field         | Type            | Required | Description                     |
| ------------- | --------------- | -------- | ------------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.       |
| `conflict_id` | string (`fc_*`) | yes      | Full-audit conflict identifier. |

**Output schema**

| Field                       | Type                     | Description                                                              |
| --------------------------- | ------------------------ | ------------------------------------------------------------------------ |
| `response.id`               | string (`fc_*`)          | Conflict identifier.                                                     |
| `response.state`            | enum                     | Current state.                                                           |
| `response.subject`          | string \| null           | Subject of the conflict.                                                 |
| `response.explanation`      | string \| null           | Explanation.                                                             |
| `response.documents`        | array                    | Involved documents.                                                      |
| `response.linked_questions` | array of string (`mq_*`) | Mandatory questions this conflict is linked to.                          |
| `response.is_important`     | boolean                  | `true` when `linked_questions` is non-empty.                             |
| `response.extraproperties`  | object                   | Includes `compagnon_questions` and optional `compagnon_recommendations`. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_full_audit_conflict_get",
    {"instance_id": "ki_abc123", "conflict_id": "fc_pqr678"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_full_audit_conflict_get",
  arguments: { instance_id: "ki_abc123", conflict_id: "fc_pqr678" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/full-audit/detail \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "conflict_id": "fc_pqr678"}'
```

{% endtab %}
{% endtabs %}

### audit\_full\_audit\_conflict\_set\_answer

Records the expert resolution and returns per-document modification recommendations inline. Sync LLM call (\~5s typical, \~10s p99). After receiving the response, render `recommendations` as a markdown table (`Document | Action`) using `document_url` to turn the document name into a link, and ask the expert whether each modification was applied before calling `audit_full_audit_conflict_close` or `_ignore`. If `recommendations` is empty, the analysis could not be generated for this conflict — offer to retry by calling this endpoint again.

**Input schema**

| Field         | Type            | Required | Description                     |
| ------------- | --------------- | -------- | ------------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.       |
| `conflict_id` | string (`fc_*`) | yes      | Full-audit conflict identifier. |
| `answer`      | string          | yes      | Expert resolution text.         |

**Output schema**

| Field                                      | Type            | Description                                |
| ------------------------------------------ | --------------- | ------------------------------------------ |
| `response.conflict`                        | object          | Updated full-audit conflict.               |
| `response.recommendations`                 | array           | Per-document modification recommendations. |
| `response.recommendations[].document_id`   | string (`kd_*`) | Target document.                           |
| `response.recommendations[].document_name` | string \| null  | Document name.                             |
| `response.recommendations[].document_url`  | string \| null  | Document URL for citation.                 |
| `response.recommendations[].type`          | string          | Recommendation type.                       |
| `response.recommendations[].action`        | string          | Recommended action text.                   |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_full_audit_conflict_set_answer",
    {"instance_id": "ki_abc123", "conflict_id": "fc_pqr678",
     "answer": "The Brussels office is the EU headquarters."},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_full_audit_conflict_set_answer",
  arguments: {
    instance_id: "ki_abc123",
    conflict_id: "fc_pqr678",
    answer: "The Brussels office is the EU headquarters.",
  },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/full-audit/set-expert-answer \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id":"ki_abc123","conflict_id":"fc_pqr678","answer":"The Brussels office is the EU headquarters."}'
```

{% endtab %}
{% endtabs %}

### audit\_full\_audit\_conflict\_ignore

Marks a full-audit conflict as `IGNORED`. The expert chose not to resolve this conflict.

**Input schema**

| Field         | Type            | Required | Description                     |
| ------------- | --------------- | -------- | ------------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.       |
| `conflict_id` | string (`fc_*`) | yes      | Full-audit conflict identifier. |

**Output schema**

| Field              | Type    | Description      |
| ------------------ | ------- | ---------------- |
| `response.success` | boolean | True on success. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_full_audit_conflict_ignore",
    {"instance_id": "ki_abc123", "conflict_id": "fc_pqr678"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_full_audit_conflict_ignore",
  arguments: { instance_id: "ki_abc123", conflict_id: "fc_pqr678" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/full-audit/ignore \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "conflict_id": "fc_pqr678"}'
```

{% endtab %}
{% endtabs %}

### audit\_full\_audit\_conflict\_close

Closes (marks `MANAGED`) a full-audit conflict. Call only after the expert has confirmed every modification listed in the recommendations from `audit_full_audit_conflict_set_answer` was applied.

**Input schema**

| Field         | Type            | Required | Description                     |
| ------------- | --------------- | -------- | ------------------------------- |
| `instance_id` | string (`ki_*`) | yes      | K-AI instance identifier.       |
| `conflict_id` | string (`fc_*`) | yes      | Full-audit conflict identifier. |

**Output schema**

| Field              | Type    | Description      |
| ------------------ | ------- | ---------------- |
| `response.success` | boolean | True on success. |

{% tabs %}
{% tab title="Python (MCP SDK)" %}

```python
result = await session.call_tool(
    "audit_full_audit_conflict_close",
    {"instance_id": "ki_abc123", "conflict_id": "fc_pqr678"},
)
```

{% endtab %}

{% tab title="TypeScript (MCP SDK)" %}

```ts
const result = await client.callTool({
  name: "audit_full_audit_conflict_close",
  arguments: { instance_id: "ki_abc123", conflict_id: "fc_pqr678" },
});
```

{% endtab %}

{% tab title="Raw HTTP" %}

```bash
curl -X POST https://api-audit.kai-studio.ai/audit/full-audit/close \
  -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \
  -d '{"instance_id": "ki_abc123", "conflict_id": "fc_pqr678"}'
```

{% endtab %}
{% endtabs %}

## Not exposed on MCP (REST-only)

The following audit REST operations are intentionally excluded from the MCP surface. They power the K-AI Audit web app, admin flows, or CronJobs — exposing them to a host LLM would invite destructive or high-volume calls without expert oversight. Use the REST API directly when you need them.

**Instance setup and admin (browser-only):**

* `audit_instance_list_for_user` · `audit_instance_get` · `audit_instance_get_kai_instances` — instance discovery & K-AI credentials lookup.
* `audit_instance_update_step` · `audit_instance_update_configuration` — workflow state transitions and configuration edits.

**User membership (admin only):**

* `audit_user_get_users` · `audit_user_list_instances` — membership listing.
* `audit_user_add` · `audit_user_remove` — add/remove user on an instance.
* `audit_user_set_admin` · `audit_user_set_normal` — promote/demote.
* `audit_user_is_admin` — admin check used by the K-AI Audit web app.

**Documents (high-volume queries served by REST):**

* `audit_documents_list` · `audit_documents_list_with_state` — paginated browse with filters.
* `audit_documents_count` — indexation progress monitoring.
* `audit_documents_set_owner` — owner assignment (admin only).

**Duplicates (out of conflict-first scope):**

* `audit_duplicate_list` — duplicate cluster listing.
* `audit_duplicate_set_managed` — mark a cluster as managed.

**Mandatory question writes (driven by the K-AI Audit web app):**

* `audit_mandatory_question_set_answer` — expert resolution at the question level (experts resolve via `audit_question_conflict_set_answer` instead).
* `audit_mandatory_question_set_managed` · `audit_mandatory_question_set_ignored` — question-level state writes.

**Question-conflict analytics:**

* `audit_conflict_get_top_collaborators` — top collaborators sharing conflicts.

**Full-audit (UI helpers and admin transitions):**

* `audit_full_audit_have_to_show` — UI helper that returns whether the full-audit panel is available.
* `audit_full_audit_set_state` — direct state transition (reopen) used by the K-AI Audit web app; the MCP surface uses `audit_full_audit_conflict_close` / `_ignore` instead.

**Stats (dashboard cards on REST):**

* `audit_stats_get_daily` · `audit_stats_get_user` · `audit_stats_get_filtered` — daily, per-user, and aggregated counters.
