> ## 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.

# Chat

> Run stateless grounded chat and streaming chat with the SDK.

`rag.chat()` runs retrieval and answer generation together. It is stateless: pass `history` in and persist the returned `history` for the next turn.

```python theme={null}
from ragrails import RagRails

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

## Basic Chat

```python theme={null}
history = []
result = rag.chat("How long do I have to request a refund?", history=history)

print(result.answer)
history = result.history
```

Result fields:

```python theme={null}
result.answer
result.sources
result.history
result.retrieval
result.llm
result.errors
result.retrieval_quality
result.answer_confidence
result.compacted
result.intent
```

## Streaming Chat

`chat_stream()` yields structured event dicts and ends with a `final` event.

```python theme={null}
for event in rag.chat_stream("How long do I have to request a refund?", history=[]):
    if event["type"] == "progress":
        print(event["stage"], event["message"])
    elif event["type"] == "token":
        print(event["data"]["text"], end="")
    elif event["type"] == "final":
        result = event["data"]
```

Typical event types are `progress`, `token`, `error`, and `final`.

<Note>`chat_stream()` streams normal RAG chat. It does not stream agentic tool execution.</Note>

## Chat Tuning

```python theme={null}
from ragrails import (
    ChatRetrievalQualityConfig,
    HistoryCompactionConfig,
    IntentRoutingConfig,
    QueryRewriteConfig,
)

result = rag.chat(
    "What about the second step?",
    history=history,
    persona="Answer as a concise support engineer.",
    query_rewrite=QueryRewriteConfig(enabled=True, session_context="Refund policy flow"),
    history_compaction=HistoryCompactionConfig(enabled=True, history_limit=15, keep_recent=5),
    intent_routing=IntentRoutingConfig(enabled=True),
    retrieval_quality=ChatRetrievalQualityConfig(
        min_retrieval_score=0.35,
        min_rerank_score=0.50,
        low_confidence_mode="answer_with_caution",
        max_context_chunks=5,
    ),
)
```

Low-confidence modes are `answer_with_caution`, `ask_clarifying_question`, `refuse_grounded_answer`, and `return_no_answer`.

## Reranking in Chat

```python theme={null}
from ragrails.core.stg_05_retriever import RetrieverConfig

result = rag.chat(
    "How long do refunds take?",
    history=[],
    retrieval_config=RetrieverConfig(use_rerank=True, rerank_top_k=5),
)
```

Configure `reranker={"provider": "voyage", "model": "rerank-2-lite"}` on `RagRails(...)`, or pass `reranker=rag.reranker(...)` to one call.

## `llm()`

```python theme={null}
llm = rag.llm(provider="openai", model="gpt-4o-mini", max_tokens=1024)
result = rag.chat("Summarize the refund policy", llm=llm, history=[])
```

| Parameter    | Default                            | Description                                               |
| ------------ | ---------------------------------- | --------------------------------------------------------- |
| `provider`   | constructor default                | `openai`, `anthropic`, or `google`.                       |
| `model`      | constructor default, else required | Model name. `rag.llm()` does not choose a fallback model. |
| `max_tokens` | `1024`                             | Max output tokens.                                        |

## Agentic Tools and Tool Calling

`rag.chat()` does not execute tools. Tool execution requires application-owned authorization, confirmation, allowlists, secrets, side-effect policy, and audit logs.

For SDK apps, use the lower-level LLM method `complete_with_tools()` and run the tool loop inside your own application boundary. The ready-made `web_fetch` and `api_call` loop is available in the interactive CLI (`ragrails chat` with no query argument), not in `rag.chat()`.

<CardGroup cols={2}>
  <Card title="Tool Calling" icon="wrench" href="/capabilities/tool-calling">Build your own SDK tool loop.</Card>
  <Card title="Query" icon="search-check" href="/usage/sdk/query">Use chat in the query workflow.</Card>
</CardGroup>
