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

# Trace a response to source documents

> Trace model output back to the original source document using provenance metadata captured at ingestion.

Source tracing lets you prove that any model or agent answer came directly from the exact files you uploaded. Every chunk retrieved from a vector database carries a traceable lineage that connects the model output to the retrieved chunk, its Markdown location, and the original uploaded file. This is designed to support auditability, compliance, and operational decision-making in environments where document-level proof of origin is required.

## How source tracing works

When a file is ingested into a vector database, the pipeline captures provenance metadata for every chunk (line range, character offsets, heading hierarchy, and source page number) and stores it alongside the embedding. No additional configuration is required.

## Retrieve source tracing fields from a run

After a run completes, list the thread's messages to access the assistant response. When the agent invoked the file search tool, each retrieved chunk carries its source tracing fields: `chunk_id` (use it to fetch full provenance), `page`, `lines`, and `section` (the heading hierarchy path from the document root). `page` is `null` for native Markdown and JSON.

**Endpoint:** [`GET /v1/threads/{thread_id}/messages`](/flow/reference/list_messages_endpoint_v1_threads__thread_id__messages_get)

<CodeGroup>
  ```python Python theme={null}
  from seekrai import SeekrFlow

  client = SeekrFlow()

  messages = client.agents.threads.list_messages(thread_id="<thread-id>")

  # The assistant response carries the retrieved chunks and their source tracing fields
  assistant = next(m for m in messages if m.role == "assistant")
  print(assistant.content)  # each file search chunk includes chunk_id, page, lines, and section
  ```
</CodeGroup>

## Retrieve chunk provenance

Use `chunk_id` with the chunk endpoint to retrieve the full provenance record, which includes the `file_id` of the original uploaded file, the chunk `text` as indexed, and a list of `locations`.

**Endpoint:** [`GET /v1/flow/vectordb/{database_id}/chunk/{chunk_id}`](/flow/reference/get_vector_database_chunk_v1_flow_vectordb__database_id__chunk__chunk_id__get)

Retrieve a chunk with the `seekrai` SDK using `retrieve_chunk`. The returned object exposes the same fields as the REST response, so you can read `file_id` and walk each location directly. Requires `seekrai` 0.20.0 or later.

<CodeGroup>
  ```python Python theme={null}
  from seekrai import SeekrFlow

  client = SeekrFlow()

  chunk = client.vector_database.retrieve_chunk(
      database_id="<database-id>",
      chunk_id="<chunk-id>",  # from the file search result
  )

  print(chunk.file_id)   # original uploaded file
  print(chunk.text)      # chunk text as indexed

  for location in chunk.locations:
      print(location["page_number"], location["hierarchy"])
  ```
</CodeGroup>

Use the `file_id` to download the original uploaded file and complete the chain of custody:

<CodeGroup>
  ```python Python theme={null}
  client.files.retrieve_content(chunk.file_id, output="source-document.pdf")
  ```
</CodeGroup>

## Reading the result

Each entry in a chunk's `locations` pins the answer to a precise place in the ingested Markdown: the line range and character offsets, the heading `hierarchy` from the document root to the chunk, and the `page_number` in the source document (1-indexed, and `null` for native Markdown and JSON). Combined with `file_id`, these fields let you open the original document and point to the exact passage an answer was drawn from. For the complete record, see the [chunk endpoint reference](/flow/reference/get_vector_database_chunk_v1_flow_vectordb__database_id__chunk__chunk_id__get).

## Supported file types

| File type | `page_number` | `hierarchy` | `lines` | `char_start` / `char_end` |
| --------- | ------------- | ----------- | ------- | ------------------------- |
| PDF       | ✓             | ✓           | ✓       | ✓                         |
| DOCX      | ✓             | ✓           | ✓       | ✓                         |
| PPTX      | ✓             | ✓           | ✓       | ✓                         |
| Markdown  | —             | ✓           | ✓       | ✓                         |
| JSON      | —             | ✓           | ✓       | ✓                         |

## Complete workflow

The full source tracing workflow follows this sequence:

```mermaid theme={null}
flowchart TD
    A("Run the agent<br/>POST /v1/threads/{thread_id}/runs")
    B("List messages<br/>GET /v1/threads/{thread_id}/messages")
    C("Retrieve chunk provenance<br/>GET /v1/flow/vectordb/{database_id}/chunk/{chunk_id}")
    D("Download source document<br/>GET /v1/flow/files/{file_id}/content")
    A -->|"chunk_id, page, section"| B
    B -->|"file_id, Markdown location"| C
    C -->|"original file"| D
```

1. Run the agent against a thread (**Endpoint:** [`POST /v1/threads/{thread_id}/runs`](/flow/reference/run_agent_v1_threads__thread_id__runs_post)), then wait for the run to complete.
2. List the thread's messages (**Endpoint:** [`GET /v1/threads/{thread_id}/messages`](/flow/reference/list_messages_endpoint_v1_threads__thread_id__messages_get)) to find the assistant response. Each retrieved chunk includes `chunk_id`, `page`, and `section`.
3. Call the chunk endpoint with `chunk_id` to get `file_id` and confirm the exact Markdown lines the answer was drawn from.
4. Use `file_id` with the file download endpoint (**Endpoint:** [`GET /v1/flow/files/{file_id}/content`](/flow/reference/file_download_content_v1_flow_files__file_id__content_get)) to retrieve the original uploaded file and complete the chain of custody.
