Chat
Built-in chat agent that performs RAG over your indexes with session management and streaming responses.
The chat API provides a built-in RAG agent that can answer questions over one or more of your indexes. It manages conversation sessions, streams responses as Server-Sent Events, and handles retrieval, tool use, and reasoning internally.
Create a session
Section titled “Create a session”A session holds the conversation history. You can optionally bind it to specific indexes at creation time — once the first message is sent, the bound indexes are locked for the session’s lifetime.
# Session bound to specific indexessession = await client.beta.chat.create( index_ids=["<index-id-1>", "<index-id-2>"],)print(session.session_id)
# Unbound session (indexes specified per-message)session = await client.beta.chat.create()// Session bound to specific indexesconst session = await client.beta.chat.create({ index_ids: ["<index-id-1>", "<index-id-2>"],});console.log(session.session_id);
// Unbound sessionconst unboundSession = await client.beta.chat.create({});// Session bound to specific indexessession, err := client.Beta.Chat.New(ctx, llamacloud.BetaChatNewParams{ IndexIDs: []string{"<index-id-1>", "<index-id-2>"},})if err != nil { log.Fatal(err)}fmt.Println(session.SessionID)
// Unbound session (indexes specified per-message)session, err = client.Beta.Chat.New(ctx, llamacloud.BetaChatNewParams{})if err != nil { log.Fatal(err)}import ai.llamaindex.llamacloud.models.beta.chat.ChatCreateParams;import ai.llamaindex.llamacloud.models.beta.chat.ChatCreateResponse;
// Session bound to specific indexesChatCreateResponse session = client.beta().chat().create( ChatCreateParams.builder() .addIndexId("<index-id-1>") .addIndexId("<index-id-2>") .build());System.out.println(session.sessionId());
// Unbound session (indexes specified per-message)ChatCreateResponse unboundSession = client.beta().chat().create();# Session bound to specific indexesSESSION_ID=$(llp beta:chat create \ --index-id '["<index-id-1>", "<index-id-2>"]' | jq -r '.session_id')
echo "$SESSION_ID"
# Unbound session (indexes specified per-message)SESSION_ID=$(llp beta:chat create | jq -r '.session_id')Stream messages
Section titled “Stream messages”Send a message and receive the agent’s response as a stream of Server-Sent Events. The stream includes thinking steps, tool calls (retrieval), and the final text response.
Each SDK exposes a raw-response accessor that hands back the unread HTTP body — with_streaming_response in Python, .asResponse() in TypeScript, option.WithResponseBodyInto in Go, and withRawResponse() in Java — so events can be parsed line by line as they arrive.
import json
response = client.beta.chat.with_streaming_response.stream( session.session_id, index_ids=["<index-id>"], prompt="What are the key findings in the Q3 report?",)
async with response as stream: async for line in stream.iter_lines(): if not line or line.startswith(":"): continue if line.startswith("data: "): data = json.loads(line[6:]) if data.get("type") == "text_delta": print(data["content"], end="", flush=True) elif data.get("type") == "stop": print("\n--- Done ---") else: print(data) # handle other event types as neededconst response = await client.beta.chat.stream(session.session_id, { index_ids: ["<index-id>"], prompt: "What are the key findings in the Q3 report?",}).asResponse();
const reader = response.body!.getReader();const decoder = new TextDecoder();
while (true) { const { done, value } = await reader.read(); if (done) break;
const chunk = decoder.decode(value, { stream: true }); for (const line of chunk.split("\n")) { if (line.startsWith("data: ")) { const data = JSON.parse(line.slice(6)); if (data.type === "text_delta") { process.stdout.write(data.content); } else if (data.type === "stop") { console.log("\n--- Done ---"); } else { console.log(data); // handle other event types as needed } } }}import ( "bufio" "encoding/json" "fmt" "log" "net/http" "strings"
llamacloud "github.com/run-llama/llama-parse-go" "github.com/run-llama/llama-parse-go/option")
var raw *http.Responseif _, err := client.Beta.Chat.Stream(ctx, session.SessionID, llamacloud.BetaChatStreamParams{ IndexIDs: []string{"<index-id>"}, Prompt: "What are the key findings in the Q3 report?",}, option.WithResponseBodyInto(&raw)); err != nil { log.Fatal(err)}defer raw.Body.Close()
scanner := bufio.NewScanner(raw.Body)for scanner.Scan() { line := scanner.Text() if !strings.HasPrefix(line, "data: ") { continue } var data map[string]any if err := json.Unmarshal([]byte(line[6:]), &data); err != nil { continue } switch data["type"] { case "text_delta": fmt.Print(data["content"]) case "stop": fmt.Println("\n--- Done ---") default: fmt.Println(data) // handle other event types as needed }}import ai.llamaindex.llamacloud.core.http.HttpResponseFor;import ai.llamaindex.llamacloud.models.beta.chat.ChatStreamParams;import ai.llamaindex.llamacloud.models.beta.chat.ChatStreamResponse;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import java.io.BufferedReader;import java.io.InputStreamReader;import java.nio.charset.StandardCharsets;
ObjectMapper mapper = new ObjectMapper();
try (HttpResponseFor<ChatStreamResponse> response = client.beta().chat().withRawResponse().stream( session.sessionId(), ChatStreamParams.builder() .addIndexId("<index-id>") .prompt("What are the key findings in the Q3 report?") .build()); BufferedReader reader = new BufferedReader(new InputStreamReader(response.body(), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { if (!line.startsWith("data: ")) { continue; } JsonNode data = mapper.readTree(line.substring(6)); String type = data.path("type").asText(); if (type.equals("text_delta")) { System.out.print(data.path("content").asText()); } else if (type.equals("stop")) { System.out.println("\n--- Done ---"); } else { System.out.println(data); // handle other event types as needed } }}llp beta:chat stream \ --session-id "$SESSION_ID" \ --index-id "<index-id>" \ --prompt "What are the key findings in the Q3 report?"The CLI is the exception: llp beta:chat stream buffers the whole turn and prints the accumulated event payload once the agent has finished, so it is useful for inspecting a turn but not for rendering deltas live.
Event types
Section titled “Event types”The stream emits two categories of events:
Delta events (event: delta) — Incremental content for real-time display:
| Type | Description |
|---|---|
text_delta | A chunk of the agent’s response text. |
thinking_delta | A chunk of the agent’s reasoning (if exposed). |
Message events (event: message) — Complete, discrete events:
| Type | Description |
|---|---|
text | Complete agent response text. |
thinking | Complete agent reasoning block. |
user_input | The user’s original message. |
tool_call | A tool invocation by the agent (e.g., retrieval). |
tool_result | The result of a tool call. |
stop | End of the stream, includes token usage. |
warning | Informational warning (e.g., skipped indexes). |
List sessions
Section titled “List sessions”sessions = await client.beta.chat.list()
for s in sessions.items: print(f"{s.session_id}: {s.generated_title or '(untitled)'}")const sessions = await client.beta.chat.list();
for (const s of sessions.items) { console.log(`${s.session_id}: ${s.generated_title ?? "(untitled)"}`);}iter := client.Beta.Chat.ListAutoPaging(ctx, llamacloud.BetaChatListParams{})
for iter.Next() { s := iter.Current() title := s.GeneratedTitle if title == "" { title = "(untitled)" } fmt.Printf("%s: %s\n", s.SessionID, title)}
if err := iter.Err(); err != nil { log.Fatal(err)}import ai.llamaindex.llamacloud.models.beta.chat.ChatListPage;import ai.llamaindex.llamacloud.models.beta.chat.ChatListResponse;
ChatListPage page = client.beta().chat().list();
for (ChatListResponse s : page.autoPager()) { System.out.println(s.sessionId() + ": " + s.generatedTitle().orElse("(untitled)"));}llp beta:chat list \ --max-items 100 \ | jq -r '"\(.session_id): \(.generated_title // "(untitled)")"'Get session details
Section titled “Get session details”Retrieve a session summary or the full session with its event history.
# Summary onlysummary = await client.beta.chat.get_summary(session.session_id)print(summary.generated_title)print(summary.job_metadata)
# Full session with event historyfull = await client.beta.chat.retrieve(session.session_id)for event in full.events: print(event.type, event.content[:100] if hasattr(event, "content") else "")// Summary onlyconst summary = await client.beta.chat.getSummary(session.session_id);console.log(summary.generated_title);
// Full session with eventsconst full = await client.beta.chat.retrieve(session.session_id);for (const event of full.events) { console.log(event.type);}// Summary onlysummary, err := client.Beta.Chat.GetSummary(ctx, session.SessionID, llamacloud.BetaChatGetSummaryParams{})if err != nil { log.Fatal(err)}fmt.Println(summary.GeneratedTitle)
// Full session with event historyfull, err := client.Beta.Chat.Get(ctx, session.SessionID, llamacloud.BetaChatGetParams{})if err != nil { log.Fatal(err)}for _, event := range full.Events { content := event.Content if runes := []rune(content); len(runes) > 100 { content = string(runes[:100]) } fmt.Println(event.Type, content)}import ai.llamaindex.llamacloud.models.beta.chat.ChatGetSummaryResponse;import ai.llamaindex.llamacloud.models.beta.chat.ChatRetrieveResponse;
// Summary onlyChatGetSummaryResponse summary = client.beta().chat().getSummary(session.sessionId());System.out.println(summary.generatedTitle().orElse("(untitled)"));
// Full session with event historyChatRetrieveResponse full = client.beta().chat().retrieve(session.sessionId());for (ChatRetrieveResponse.Event event : full.events()) { if (event.isText()) { System.out.println("text: " + event.asText().content()); } else if (event.isTextDelta()) { System.out.println("text_delta: " + event.asTextDelta().content()); } else if (event.isThinking()) { System.out.println("thinking: " + event.asThinking().content()); } else if (event.isThinkingDelta()) { System.out.println("thinking_delta: " + event.asThinkingDelta().content()); } else if (event.isUserInput()) { System.out.println("user_input: " + event.asUserInput().content()); } else if (event.isToolCall()) { System.out.println("tool_call: " + event.asToolCall().name()); } else if (event.isToolResult()) { System.out.println("tool_result: " + event.asToolResult().name()); } else if (event.isStop()) { System.out.println("stop: " + event.asStop().usage()); }}# Summary onlyllp beta:chat get-summary --session-id "$SESSION_ID" \ | jq -r '.generated_title // "(untitled)"'
# Full session with event historyllp beta:chat retrieve --session-id "$SESSION_ID" \ | jq -r '.events[] | "\(.type): \((.content // "")[0:100])"'Delete a session
Section titled “Delete a session”await client.beta.chat.delete(session.session_id)await client.beta.chat.delete(session.session_id);err := client.Beta.Chat.Delete(ctx, session.SessionID, llamacloud.BetaChatDeleteParams{})if err != nil { log.Fatal(err)}client.beta().chat().delete(session.sessionId());llp beta:chat delete --session-id "$SESSION_ID"