> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.twelvelabs.io/v1.3/agents/guides/create-a-response/multi-turn-sessions/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.twelvelabs.io/_mcp/server. # Multi-turn sessions Maintain conversation context across multiple requests. Use multi-turn sessions when you want to ask follow-up questions, explore your videos and images iteratively, or build a chat interface that preserves context across turns. This guide shows you how to start a session, continue it with follow-up messages, and build a reusable chat pattern. # Key concepts * **Session**: A server-side conversation state that [Jockey](/v1.3/agents/concepts/jockey) maintains across requests. You do not need to resend previous messages. The session retains the full conversation history. Each response includes a session identifier that you pass on subsequent requests to continue the conversation. # Prerequisites * You've already uploaded your videos and images, and the assets have reached the `ready` status. See the [Upload content](/v1.3/agents/guides/upload-content) page for details. * You've already created a knowledge store. See the [Create a knowledge store](/v1.3/agents/guides/create-a-knowledge-store) page for details. * You've already added at least one asset to the knowledge store, and the item has reached the `ready` status. See the [Add assets to a knowledge store](/v1.3/agents/guides/add-assets) page for details. * You've already read the [Create a response](/v1.3/agents/guides/create-a-response) page and understand the basic request and response format. # Example Copy and paste the code below, replacing the placeholders surrounded by `<>` with your values. **`Python`** ```python Python maxlines=25 from twelvelabs import TwelveLabs client = TwelveLabs(api_key="") # Step 1: Start a session by omitting session_id response = client.responses.create( knowledge_store_id="", input=[{"type": "message", "role": "user", "content": "What are the main themes in these videos and images?"}], ) session_id = response.session_id print(f"Session started: {session_id}") # Step 2: Continue the conversation with the session_id from the previous response response = client.responses.create( knowledge_store_id="", session_id=session_id, input=[{"type": "message", "role": "user", "content": "Which items best represent the first theme?"}], ) ``` **`Node.js`** ```javascript Node.js maxlines=25 import { TwelveLabs } from "twelvelabs-js"; const client = new TwelveLabs({ apiKey: "" }); // Step 1: Start a session by omitting sessionId let response = await client.responses.create({ knowledgeStoreId: "", input: [{ type: "message", role: "user", content: "What are the main themes in these videos and images?" }], }); const sessionId = response.sessionId; console.log(`Session started: ${sessionId}`); // Step 2: Continue the conversation with the sessionId from the previous response response = await client.responses.create({ knowledgeStoreId: "", sessionId, input: [{ type: "message", role: "user", content: "Which items best represent the first theme?" }], }); ``` # Code explanation #### Python #### Start a session Omit the `session_id` field on the first request. Jockey creates a new session and returns its identifier in the response.\ **Function call**: You call the [`responses.create`](/v1.3/sdk-reference/python/responses#create-a-response) method.\ **Parameters**: * `knowledge_store_id`: The unique identifier of the knowledge store to reason over. * `input`: An array of input items. Each item is a message you send to Jockey.\ **Return value**: An object of type `ResponseObject`. Read the `session_id` field and store it to continue the conversation. #### Continue the conversation Pass the `session_id` from the previous response to send a follow-up message. Jockey uses the full conversation history, so you do not resend earlier messages.\ **Function call**: You call the [`responses.create`](/v1.3/sdk-reference/python/responses#create-a-response) method.\ **Parameters**: * `knowledge_store_id`: The unique identifier of the knowledge store. Keep it the same across turns. * `session_id`: The session identifier from the previous response. * `input`: An array of input items. Each item is a message you send to Jockey.\ **Return value**: An object of type `ResponseObject`. Reuse the same `session_id` for later turns. #### Node.js #### Start a session Omit the `sessionId` field on the first request. Jockey creates a new session and returns its identifier in the response.\ **Function call**: You call the [`responses.create`](/v1.3/sdk-reference/node-js/responses#create-a-response) method.\ **Parameters**: You pass all parameters as properties of a single object. * `knowledgeStoreId`: The unique identifier of the knowledge store to reason over. * `input`: An array of input items. Each item is a message you send to Jockey.\ **Return value**: An `HttpResponsePromise` that resolves to an object of type `ResponseObject`. Read the `sessionId` field and store it to continue the conversation. #### Continue the conversation Pass the `sessionId` from the previous response to send a follow-up message. Jockey uses the full conversation history, so you do not resend earlier messages.\ **Function call**: You call the [`responses.create`](/v1.3/sdk-reference/node-js/responses#create-a-response) method.\ **Parameters**: You pass all parameters as properties of a single object. * `knowledgeStoreId`: The unique identifier of the knowledge store. Keep it the same across turns. * `sessionId`: The session identifier from the previous response. * `input`: An array of input items. Each item is a message you send to Jockey.\ **Return value**: An `HttpResponsePromise` that resolves to an object of type `ResponseObject`. Reuse the same `sessionId` for later turns. # Build a reusable chat function For chat UIs or interactive applications, wrap the session logic in a function. The function creates a new session on the first call and reuses it for subsequent calls. **`Python`** ```python Python maxlines=20 session_id = None def chat(message, store_id): global session_id response = client.responses.create( knowledge_store_id=store_id, session_id=session_id, input=[{"type": "message", "role": "user", "content": message}], ) session_id = response.session_id # Extract text from response for output in response.output: if output.type == "message": for content in output.content: return content.text ``` **`Node.js`** ```javascript Node.js maxlines=20 let sessionId: string | undefined; async function chat(message: string, storeId: string) { const response = await client.responses.create({ knowledgeStoreId: storeId, sessionId, input: [{ type: "message", role: "user", content: message }], }); sessionId = response.sessionId; // Extract text from response for (const output of response.output ?? []) { if (output.type === "message") { for (const content of output.content ?? []) { return content.text; } } } } ``` # Common pitfalls * **Store the session identifier.** Without the `session_id` value you cannot continue a conversation, and must start a new one. * **Query the same knowledge store across turns.** A session is tied to one store; pass the same `knowledge_store_id` on every turn. * **Do not resend conversation history.** The session stores it server-side. # Next steps * [Streaming](/v1.3/agents/guides/create-a-response/streaming) - combine multi-turn sessions with real-time streaming * [Structured output](/v1.3/agents/guides/create-a-response/structured-output) - receive typed JSON responses within a session * [Create a response](/v1.3/agents/guides/create-a-response) - review the basic request and response format # Jupyter notebook [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/twelvelabs-io/twelvelabs-developer-experience/blob/main/quickstarts/jockey/guides/multi_turn_sessions.ipynb)