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

# Documentation Assistant

> Let users ask your docs in plain language.

## The problem

Documentation grows faster than users can navigate it. Keyword search fails when users ask in their own words, and support tickets pile up for answers that already exist in the docs.

## Why Ragrails fits

Ragrails can crawl a docs site, store it in a vector database, stream progress during long crawls, and answer with citations to the original pages.

| Need                            | Ragrails capability                                                |
| ------------------------------- | ------------------------------------------------------------------ |
| Crawl a full documentation site | [Extraction](/features/extraction)                                 |
| Show crawl and answer progress  | [Streaming](/capabilities/streaming)                               |
| Answer with source citations    | [Chat](/features/chat)                                             |
| Improve follow-up questions     | [Query Rewriting](/capabilities/query-rewriting)                   |
| Keep docs fresh after deploys   | [Knowledge Base Maintenance](/features/knowledge-base-maintenance) |

## Sample

<CodeGroup>
  ```python SDK theme={null}
  from ragrails import QueryRewriteConfig, RagRails

  rag = RagRails(
      collection="docs",
      vector_store={"provider": "qdrant", "url": "http://localhost:6333"},
      embedding={"provider": "voyage", "model": "voyage-3"},
      llm={"provider": "openai", "model": "gpt-4o-mini"},
  )

  for event in rag.scrape_stream("https://docs.example.com", mode="full", max_pages=500):
      if event["type"] == "page":
          print("indexed source page", event["data"]["url"])

  rag.ingest(
      urls="https://docs.example.com",
      ingestion={"urls": {"mode": "full", "max_pages": 500}},
      storage={"collection": "docs"},
  )

  result = rag.chat(
      "How do I rotate an API key?",
      history=[],
      query_rewrite=QueryRewriteConfig(enabled=True),
  )

  print(result.answer)
  print(result.sources)
  ```

  ```bash CLI theme={null}
  ragrails setup-url --browser chromium

  ragrails ingest \
    --source-url https://docs.example.com \
    --vector-db qdrant \
    --collection docs \
    --url http://localhost:6333 \
    --provider voyage \
    --model voyage-3

  ragrails chat "How do I rotate an API key?" \
    --rewrite-query \
    --vector-db qdrant \
    --collection docs \
    --url http://localhost:6333 \
    --embedder-provider voyage \
    --embedder-model voyage-3 \
    --llm-provider openai \
    --llm-model gpt-4o-mini
  ```

  ```bash REST API theme={null}
  curl -N -X POST http://127.0.0.1:8000/v1/ingest/url/stream \
    -H "Content-Type: application/json" \
    -d '{"url": "https://docs.example.com", "mode": "full", "max_pages": 500}'

  curl -X POST http://127.0.0.1:8000/v1/pipelines/ingest \
    -H "Content-Type: application/json" \
    -d '{
      "urls": "https://docs.example.com",
      "ingestion": {"urls": {"mode": "full", "max_pages": 500}},
      "embedding": {"provider": "voyage", "model": "voyage-3"},
      "storage": {"vector_db": "qdrant", "collection": "docs", "url": "http://localhost:6333"}
    }'

  curl -N -X POST http://127.0.0.1:8000/v1/chat/stream \
    -H "Content-Type: application/json" \
    -d '{
      "query": "How do I rotate an API key?",
      "query_rewrite": {"enabled": true},
      "collection": "docs",
      "url": "http://localhost:6333",
      "history": []
    }'
  ```
</CodeGroup>

## Production notes

* Use `max_pages` so crawls are bounded.
* Store returned sources in the UI for click-through citations.
* Re-crawl after docs deploys and delete chunks that disappeared.
