> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan/json-interfaces.md).

# Start Building—Use JSON Format

For more complex filtering conditions, use JSON to specify IDs directly at each level, such as knowledge bases and individual documents.

## Query Metadata Control Items <a href="#querymetadata-kong-zhi-xiang-mu-shuo-ming" id="querymetadata-kong-zhi-xiang-mu-shuo-ming"></a>

<table><thead><tr><th width="108.66668701171875">Item Category</th><th width="140.66668701171875">Key Name</th><th>Description</th><th>Usage</th></tr></thead><tbody><tr><td>Knowledge base</td><td><code>knowledge_base</code></td><td>Knowledge bases the Agent references when generating conversations</td><td>Wrap entries in an <code>Array→[...]</code> named knowledge_bases and pass knowledge base IDs to allow access to multiple knowledge bases</td></tr><tr><td>Knowledge base documents</td><td><code>Chatbot_file</code></td><td>Documents that can be referenced in the knowledge base specified by knowledge_base</td><td>Define them in the <code>Object→{...}</code> passed within knowledge_base</td></tr><tr><td>Q&#x26;A dataset</td><td><code>FAQ</code></td><td>FAQs that can be referenced in the knowledge base specified by knowledge_base</td><td>Same as above</td></tr><tr><td>Knowledge base document labels</td><td><code>label</code></td><td>Labels on documents. Even without specifying Chatbot_file, you can specify label to restrict retrieval to documents matching that label, enabling finer-grained document permissions</td><td>Pass an object named label_relations, use <code>"OR"/"AND"</code> to define document label conditions, and define them in an <code>Array→[...]</code> named conditions</td></tr></tbody></table>

### Structure Example and Explanation

```json
{
  "query_metadata": {
    "knowledge_bases": [
      {
        "knowledge_base_id": "123e4567-e89b-12d3-a456-426614174000",
        "chatbot_file_ids": ["9f7a9f7b-2b2b-4c4c-9d9d-8e8e8e8e8e8e"],
        "faq_ids": ["a1b2c3d4-e5f6-7890-abcd-1234567890ab"],
        "has_user_selected_all": false
      },
      {
        "knowledge_base_id": "223e4567-e89b-12d3-a456-426614174001",
        "has_user_selected_all": true
      }
    ],
    "label_relations": {
      "operator": "OR",
      "conditions": [
        { "label_id": "11111111-2222-3333-4444-555555555555" },
        {
          "operator": "AND",
          "conditions": [
            { "label_id": "66666666-7777-8888-9999-000000000000" },
            { "label_id": "aaaaaaa1-bbbb-cccc-dddd-eeeeeeeeeeee" }
          ]
        }
      ]
    }
  }
}
```

Example explanation:

* `knowledge_bases` accepts multiple objects to configure accessible documents and FAQs across multiple knowledge bases at once.
* In the first knowledge base, `has_user_selected_all: false` allows only the explicitly listed documents and FAQs; in the second, `has_user_selected_all: true` allows all content in that knowledge base.
* `label_relations.operator` combines conditions with `"OR"` (match any label) or `"AND"` (match all labels), and supports nesting for complex conditions.
* The example above is valid JSON that you can copy directly (JSON does not support `//` comments).

## Empty Collections vs. Unset Values (Important) <a href="#empty-vs-unset" id="empty-vs-unset"></a>

Empty collections and unset values have different meanings. Incorrect configuration can grant or deny all access:

| Setting                                                                      | Effect                                                                                                                                                                                                                 |
| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Omitted or `null`                                                            | Unset → continue to the next level. If all three levels are unset, apply the Agent default label filter. If the Agent has no filter either, retrieval is unrestricted across all knowledge bases attached to the Agent |
| `{}` (empty object)                                                          | **Treated as unrestricted (select all)**. Since it counts as configured, it stops lookup at lower levels. To deny access, you must use `"knowledge_bases": []`                                                         |
| `"knowledge_bases": []` (empty array)                                        | No knowledge bases can be searched—**use this setting to deny access**                                                                                                                                                 |
| `"label_relations": {"operator": "OR", "conditions": []}` (empty conditions) | No label filtering: all content in the selected knowledge bases is searchable. This does **not** deny access                                                                                                           |
| Populated value                                                              | Filter by conditions, progressively narrowing the scope from knowledge bases → documents/FAQs → labels                                                                                                                 |

{% hint style="warning" %}
`label_relations` must be provided together with `knowledge_bases`. If you provide only `label_relations` (without `knowledge_bases`), knowledge base retrieval does not apply label filtering (equivalent to unrestricted access).
{% endhint %}

### Field Names Must Match Exactly <a href="#exact-field-names" id="exact-field-names"></a>

* Each condition in `conditions` accepts only two forms: `{"label_id": "..."}` or a nested group `{"operator": ..., "conditions": [...]}`. If you use another key such as `label` or `labelid`, the API returns 400 and identifies the incorrect field name.
* Objects in `knowledge_bases` accept only five fields: `knowledge_base_id`, `chatbot_file_ids`, `knowledge_base_file_ids`, `faq_ids`, and `has_user_selected_all`. Other fields also cause a 400 response.
* You can add your own identification fields (such as `_user_id`) at the top level of `query_metadata`. These fields are ignored and do not affect the query scope.

{% hint style="info" %}
Format errors are rejected with 400 at the API boundary (fail-closed), preventing silently broader permissions than intended. After configuration, we still recommend testing once to confirm the scope meets your expectations.
{% endhint %}

### Level Precedence <a href="#metadata-hierarchy" id="metadata-hierarchy"></a>

query\_metadata can be configured at the Message / Conversation / Contact levels. The first configured level is selected in this order: **Message > Conversation > Contact > Agent default label filter**. Higher-level settings override lower-level settings; the Agent default label filter applies only when all three levels are unset. For the full rules, see [Resolution Order](/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan.md#resolution-order).

## How Do I Get IDs at Each Level? <a href="#ru-he-huo-qu-ge-ceng-ji-id" id="ru-he-huo-qu-ge-ceng-ji-id"></a>

Open the content for each level from the left menu to view its ID field (for example, in a knowledge base, click the copy icon to copy the entire ID).

<figure><img src="https://3415477754-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNBTi475lqozGpB7xObpE%2Fuploads%2Fgit-blob-ac377b11864763f6d3b96811593f2262b28eba95%2F%E8%9E%A2%E5%B9%95%E6%93%B7%E5%8F%96%E7%95%AB%E9%9D%A2%202025-08-08%20101733.png?alt=media" alt=""><figcaption><p>Where to find IDs at each level</p></figcaption></figure>

## Key Logic <a href="#guan-jian-luo-ji-shuo-ming" id="guan-jian-luo-ji-shuo-ming"></a>

### 1. label\_relations Logic <a href="#id-1labelrelations-luo-ji" id="id-1labelrelations-luo-ji"></a>

* `OR`: access is allowed if any label matches
* `AND`: access is allowed only if all labels match
* Nested logic: supports multiple levels of nested permission combinations

### 2. knowledge\_bases Configuration <a href="#id-2knowledgebases-she-ding" id="id-2knowledgebases-she-ding"></a>

* `has_user_selected_all = true`: access all content in the knowledge base (excluding items listed in the exclusion lists)
* `has_user_selected_all = false`: access only the specified documents and FAQs
* JSON booleans (`true` / `false`) are recommended; the system also accepts the strings `"True"` / `"False"` for compatibility with existing integrations

## Contact Configuration <a href="#lian-luo-ren-contact-she-ding" id="lian-luo-ren-contact-she-ding"></a>

You can enter query\_metadata settings directly in JSON when editing a contact:

<figure><img src="https://3415477754-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNBTi475lqozGpB7xObpE%2Fuploads%2Fgit-blob-948b74fac65e94e770db5ec15e7f148c07f242c2%2F%E8%9E%A2%E5%B9%95%E6%93%B7%E5%8F%96%E7%95%AB%E9%9D%A2%202025-08-07%20163545.png?alt=media" alt=""><figcaption><p>Contact JSON editing interface</p></figcaption></figure>

The system automatically validates the format and applies the permission settings.

## Web Chat Initialization <a href="#webchat-chu-shi-hua-she-ding" id="webchat-chu-shi-hua-she-ding"></a>

{% hint style="info" %}
For an introduction to Web Chat embedding, see [Web Chat Embedding and SDK](/tech/en/serve/web-chat-sdk.md)
{% endhint %}

To restrict conversation content before a contact is registered (for example, when providing Web Chat to customers without registered contact accounts), provide Query Metadata in the embed configuration. The system enables message-level knowledge base document filtering by default.

### Code Example <a href="#cheng-shi-ma-fan-li" id="cheng-shi-ma-fan-li"></a>

```javascript
<script>
  window.maiagentChatbotConfig = {
    // Configure basic Web Chat parameters
    webChatId: 'Web Chat ID obtained from the Admin embed dialog',
    baseUrl: 'https://chat.maiagent.ai/web-chats',
    primaryColor: '#3854d8',
    
    // Configure the Web Chat knowledge base document search scope
    queryMetadata: {
      labelRelations: { // Labels
        operator: 'OR',
        conditions: [
          { labelId: '186a3012-44ac-4cd2-a132-a76bfda5bcae' },
          {
            operator: 'AND',
            conditions: [
              { labelId: '0267c405-cc26-4497-b17f-180aedf8b0eb' }, 
              { labelId: '60f81de6-a4b6-4d86-9781-5430783ef0b6' }
            ]
          }
        ]
      },
      knowledgeBases: [
        {
          knowledgeBaseId: '123e4567-e89b-12d3-a456-426614174000',
          chatbotFileIds: [
            '9f7a9f7b-2b2b-4c4c-9d9d-8e8e8e8e8e8e' // Documents
          ],
          faqIds: [
            'a1b2c3d4-e5f6-7890-abcd-1234567890ab' // FAQ
          ],
          hasUserSelectedAll: false // Select only the documents and FAQs explicitly listed above
        }
      ]
    },
    
    // Configure Contact
    contactId: '60f81de6-a4b6-4d86-9781-5430783ef0b6'
  };
</script>
<script
  src="https://chat.maiagent.ai/js/embed.min.js"
  defer>
</script>
```

### hasUserSelectedAll Parameter

This parameter controls exclusions or selection of a few items within a single knowledge base. Label filters then apply only to the documents you have made accessible.

<table><thead><tr><th width="82">Parameter Value</th><th>Behavior</th><th>Use Case</th></tr></thead><tbody><tr><td><code>true</code></td><td>The system selects all content in the knowledge base, excluding items listed in <code>chatbotFileIds</code> and <code>faqIds</code></td><td>Use 98 of 100 documents; list the 2 unused documents in the parameters</td></tr><tr><td><code>false</code></td><td>The system selects items explicitly listed in <code>chatbotFileIds</code> and <code>faqIds</code></td><td>Use only 2 of 100 documents</td></tr></tbody></table>

### Code Example

```js
// hasUserSelectedAll: true, list document IDs to exclude
{
  "knowledgeBaseId": "123e4567-e89b-12d3-a456-426614174000",
  "chatbotFileIds": ["excluded_document_ID1", "excluded_document_ID2"],
  "faqIds": ["excluded_FAQ_ID1"],
  "hasUserSelectedAll": true
}

// hasUserSelectedAll: false, list document IDs to include
{
  "knowledgeBaseId": "123e4567-e89b-12d3-a456-426614174000",
  "chatbotFileIds": ["included_document_ID1", "included_document_ID2"],
  "faqIds": ["included_FAQ_ID1"],
  "hasUserSelectedAll": false
}
```

### Precedence of queryMetadata and contactId

* **When neither queryMetadata nor contactId is configured**: the system searches all knowledge bases without exclusions
* **You can configure queryMetadata or contactId independently**
* **When both are configured**: the system uses only the Query Metadata settings of the contact identified by contactId

## Passing Query Metadata with Each Conversation API (completions) Request <a href="#completions-api" id="completions-api"></a>

In addition to Contact and Web Chat embed settings, you can pass Query Metadata with each conversation API call so the same Agent applies a different knowledge scope to each request. This suits integrations where the backend builds conditions dynamically based on the current user identity, for example:

* **Finance/securities**: select accessible plan documents by membership tier, so regular members and VIP customers receive responses with different scopes to the same question
* **Technology/electronics manufacturing**: restrict retrieval to specifications and technical documents for the product line associated with the customer
* **Educational institutions**: provide different levels of admissions and institutional information to current students, alumni, and general visitors
* **Medical/healthcare**: restrict patient education materials by department to prevent content from different departments from interfering with each other

Endpoint: `POST https://api.maiagent.ai/api/v1/chatbots/{chatbotId}/completions/`

{% hint style="warning" %}
Place `queryMetadata` **inside the `message` object**, not at the top level of the request body. An incorrect location does not trigger an error, but the conditions will not take effect; the result is equivalent to having no filters configured.
{% endhint %}

### Complete Example <a href="#completions-full-example" id="completions-full-example"></a>

{% code title="completions + queryMetadata" overflow="wrap" %}

```bash
curl --location 'https://api.maiagent.ai/api/v1/chatbots/550e8400-e29b-41d4-a716-446655440000/completions/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Api-Key YOUR_API_KEY' \
--data '{
    "conversation": null,
    "message": {
        "content": "Which promotional plans are available for my membership tier?",
        "queryMetadata": {
            "knowledgeBases": [
                {
                    "knowledgeBaseId": "123e4567-e89b-12d3-a456-426614174000"
                }
            ],
            "labelRelations": {
                "operator": "AND",
                "conditions": [
                    { "labelId": "186a3012-44ac-4cd2-a132-a76bfda5bcae" }
                ]
            }
        }
    },
    "isStreaming": false
}'
```

{% endcode %}

The example means: retrieve only documents and FAQs in knowledge base `123e4567…` that also match label `186a3012…` (for example, “regular member”). For VIP customers, the backend only needs to pass the corresponding label ID; there is no need to duplicate the Agent.

Nested conditions use the same syntax as Web Chat. You can reuse the `labelRelations` structure from the previous section:

```json
"labelRelations": {
    "operator": "OR",
    "conditions": [
        { "labelId": "186a3012-44ac-4cd2-a132-a76bfda5bcae" },
        {
            "operator": "AND",
            "conditions": [
                { "labelId": "0267c405-cc26-4497-b17f-180aedf8b0eb" },
                { "labelId": "60f81de6-a4b6-4d86-9781-5430783ef0b6" }
            ]
        }
    ]
}
```

### Differences Between the Three Configuration Locations <a href="#three-entry-points" id="three-entry-points"></a>

<table><thead><tr><th width="150">Configuration Location</th><th>Scope</th><th>Use Case</th></tr></thead><tbody><tr><td>Contact</td><td>All conversations for that contact</td><td>Persistently associate permissions with an identity</td></tr><tr><td>Web Chat embed</td><td>Conversations generated by that embedded page</td><td>Restrict the scope for visitors without registered contacts</td></tr><tr><td>Conversation API (<code>message.queryMetadata</code>)</td><td>Only that request</td><td>Build conditions for each request in the backend; one Agent serves multiple permission scopes</td></tr></tbody></table>

### Field Naming: Both camelCase and snake\_case Are Supported <a href="#field-naming" id="field-naming"></a>

The API automatically converts naming styles, so the following two forms are equivalent:

* camelCase：`queryMetadata`、`knowledgeBases`、`knowledgeBaseId`、`labelRelations`、`labelId`、`hasUserSelectedAll`
* snake\_case：`query_metadata`、`knowledge_bases`、`knowledge_base_id`、`label_relations`、`label_id`、`has_user_selected_all`

Use one naming style consistently throughout the request to avoid confusion during maintenance.

### Default Value When hasUserSelectedAll Is Omitted <a href="#default-has-user-selected-all" id="default-has-user-selected-all"></a>

When omitted, `hasUserSelectedAll` defaults to `true`, meaning **all content in that knowledge base**, with label filters applied afterward.

Therefore, to restrict an entire knowledge base using labels, `knowledgeBases` only needs `knowledgeBaseId`:

```json
"knowledgeBases": [
    { "knowledgeBaseId": "123e4567-e89b-12d3-a456-426614174000" }
]
```

### Scope of Label Filtering <a href="#label-filter-scope" id="label-filter-scope"></a>

* Label conditions apply to **both** documents and FAQs in the knowledge base.
* **Attachments uploaded directly by the user in that conversation are not restricted by label conditions** and can still be referenced. Labels restrict only knowledge base content.
* Labels are **created independently for each knowledge base**. Use that knowledge base’s own label IDs for `label_id`; do not reuse labels from another knowledge base.
* `label_relations` is **one shared set for the entire request**, not one set per knowledge base: the platform applies the same conditions to every knowledge base listed in `knowledge_bases`. Since labels are attached only to documents in their own knowledge base, the effects are:
  * Mixing label IDs from multiple knowledge bases in `OR` works: each knowledge base matches only its own labels; labels from other knowledge bases match no documents there.
  * Mixing label IDs from different knowledge bases in `AND` yields **no results in any knowledge base**, because no document carries labels from two knowledge bases at once. To apply different conditions to different knowledge bases, make separate requests or specify documents using `chatbot_file_ids`.
  * Label IDs that do not exist or do not belong to these knowledge bases do not cause errors; they simply match no documents.
* Labels must be **actually attached to documents/FAQs** to take effect. Creating label options in Label Management without attaching them to content does not make filtering effective.
* Requests that directly name a specific file in the question are also subject to label conditions: if the file does not match, the Agent replies that it cannot find the file in the knowledge base.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.maiagent.ai/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan/json-interfaces.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
