> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowyte.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Add a knowledge base & verify coverage

> Add a URL or FAQ source, wait for it to index, preview what the agent retrieves, and close the gaps callers expose.

**Knowledge** is what your agent answers from. You add sources — a help-center URL, an
uploaded document, plain text, or structured FAQs — and the platform indexes them so the agent
retrieves the right passage at answer time instead of guessing. This guide adds a source,
confirms it indexed, previews retrieval, and reviews the questions callers ask that you don't
yet cover.

<Note>
  Authenticate with `Authorization: Bearer flowyte_sk_…`. All paths below are relative to `https://builder.flowyte.com/api/v1`.
</Note>

## What you'll use

| Action             | Endpoint                                         | Scope             |
| ------------------ | ------------------------------------------------ | ----------------- |
| Add a source       | `POST /agents/{agentId}/knowledge/sources`       | `knowledge:write` |
| Poll ingest status | `GET /agents/{agentId}/knowledge/sources/{id}`   | `knowledge:read`  |
| Preview retrieval  | `POST /agents/{agentId}/knowledge/preview`       | `knowledge:read`  |
| Review gaps        | `GET /agents/{agentId}/knowledge-gaps`           | `analytics:read`  |
| Curate a gap       | `PATCH /agents/{agentId}/knowledge-gaps/{gapId}` | `analytics:write` |

<Steps>
  <Step title="Add a source">
    A source has a `kind` (`url`, `file`, `text`, or `faq`) and a `label`. Use `url` to crawl a
    page, `text` to paste content inline, or `file` with a `file_id` from an upload.

    <CodeGroup>
      ```bash curl theme={null}
      curl -X POST https://builder.flowyte.com/api/v1/agents/$AGENT_ID/knowledge/sources \
        -H "Authorization: Bearer $FLOWYTE_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{ "kind": "url", "label": "Help center", "url": "https://acme.com/help" }'
      ```

      ```ts Node theme={null}
      const res = await fetch(
        `https://builder.flowyte.com/api/v1/agents/${agentId}/knowledge/sources`,
        {
          method: "POST",
          headers: {
            Authorization: `Bearer ${process.env.FLOWYTE_API_KEY}`,
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ kind: "url", label: "Help center", url: "https://acme.com/help" }),
        },
      );
      const { data: source } = await res.json();
      ```

      ```python Python theme={null}
      import os, requests
      r = requests.post(
          f"https://builder.flowyte.com/api/v1/agents/{agent_id}/knowledge/sources",
          headers={"Authorization": f"Bearer {os.environ['FLOWYTE_API_KEY']}"},
          json={"kind": "url", "label": "Help center", "url": "https://acme.com/help"},
      )
      source = r.json()["data"]
      ```
    </CodeGroup>

    The source is created with `status: "pending"`. Capture `data.id` as `SOURCE_ID`.
  </Step>

  <Step title="Poll until indexed">
    Ingestion is **asynchronous** — the source moves `pending` → `indexed`. Poll the source every
    few seconds until `data.status` is `indexed`. Don't rely on it before then.

    ```bash theme={null}
    curl https://builder.flowyte.com/api/v1/agents/$AGENT_ID/knowledge/sources/$SOURCE_ID \
      -H "Authorization: Bearer $FLOWYTE_API_KEY"
    # { "data": { "id": "...", "status": "indexed", ... } }
    ```
  </Step>

  <Step title="Preview retrieval">
    Before you trust it, ask what the agent would retrieve for a real question. `preview` returns
    the matching chunks and a `topScore` — a low score or empty `chunks` means the answer isn't
    covered yet.

    ```bash theme={null}
    curl -X POST https://builder.flowyte.com/api/v1/agents/$AGENT_ID/knowledge/preview \
      -H "Authorization: Bearer $FLOWYTE_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "query": "Do you offer same-day appointments?" }'
    ```

    <Tip>
      Pass `sourceIds` to scope the preview to specific sources. Use this to confirm a newly added
      source actually answers the question you added it for.
    </Tip>
  </Step>

  <Step title="Review knowledge gaps">
    Once callers start talking to the agent, the questions it couldn't answer surface as
    **knowledge gaps** — deduped and, above a small volume floor, ranked by how often and how
    recently they hit. This is the loop that makes the agent better over time.

    ```bash theme={null}
    curl "https://builder.flowyte.com/api/v1/agents/$AGENT_ID/knowledge-gaps?status=open" \
      -H "Authorization: Bearer $FLOWYTE_API_KEY"
    ```

    The response's `dataState` is `collecting` until enough calls land, then `ready`. When
    `ranked` is `true`, each gap carries a `gapId`, `rankScore`, and `classification`.
  </Step>

  <Step title="Close or curate a gap">
    Fix a real gap by adding a source that covers it (back to step 1), then mark the gap handled.
    You can set a ranked gap to `in_progress`, `dismissed`, or back to `open` — `covered` is set
    automatically once the live knowledge base answers it.

    ```bash theme={null}
    curl -X PATCH https://builder.flowyte.com/api/v1/agents/$AGENT_ID/knowledge-gaps/$GAP_ID \
      -H "Authorization: Bearer $FLOWYTE_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "status": "in_progress" }'
    ```
  </Step>
</Steps>

Learn how retrieval fits the rest of the agent in [Knowledge](/concepts/knowledge).
