Conversations
Send prompts and message history to Gemini Web. Learn how message roles are normalized, how to continue conversations using message history, and how session IDs and temporary chats work.
GeminiWeb.invoke() and GeminiWeb.stream() accept either a string or an array of messages. The input type is GeminiInput, defined as string | readonly GeminiMessage[]. Configure your Gemini Web session cookies and XSRF token before making requests.
Sending a conversation
Pass messages in chronological order. Include previous user messages and assistant replies when you want the model to use that history. The following example initializes an authenticated client and sends a conversation.
import 'dotenv/config'import { GeminiWeb } from '@orcushq/gemini' const cookies = process.env.GEMINI_COOKIESconst xsrfToken = process.env.GEMINI_XSRF_TOKEN if (!cookies?.trim() || !xsrfToken?.trim()) { throw new Error( 'GEMINI_COOKIES and GEMINI_XSRF_TOKEN are required', )} const model = new GeminiWeb({ model: 'gemini-3.6-flash', cookies, xsrfToken,}) const response = await model.invoke([ { role: 'user', content: 'My name is Alex.' }, { role: 'assistant', content: 'Nice to meet you, Alex.' }, { role: 'user', content: 'What is my name?' },]) console.log(response.content)console.log(response.metadata.sessionId)Example response: Your name is Alex. The exact wording depends on the model response. The SDK does not guarantee that the model will always recall or answer correctly.
Supported message roles
GeminiMessage supports four roles: user, assistant, system, and tool. Each message contains a role and content. Tool messages can also include name, while assistant messages can include tool_calls.
- `user` - Supplies user input. Its content is included in the normalized prompt without an additional role prefix.
- `assistant` - Represents a previous assistant reply. The SDK prefixes its text with
[Assistant]:. Assistant messages can also includetool_calls, which are rendered into the prompt. - `system` - Supplies instructions. The SDK prefixes the message with
[System instruction]:and includes it in the normalized prompt. - `tool` - Supplies a tool result. The SDK prefixes the message with
[Tool result for <name>]:. The optionalnameidentifies the tool in the prompt.
Using system messages
Include a system message to provide instructions alongside user input. The example uses the authenticated model initialized in the first code sample.
const response = await model.invoke([ { role: 'system', content: 'Answer in one short sentence.', }, { role: 'user', content: 'Explain what an API is.', },]) console.log(response.content)Message roles are normalized into text
Gemini Web accepts a prompt rather than the SDK’s original message array. The role prefixes are part of the SDK’s prompt normalization; they are not separate native chat roles sent as a message array.
Message content and images
A message’s content can be a string or an array of supported content parts. The current types support text parts and image parts. Images are collected during normalization, uploaded when necessary, and attached to the request.
const response = await model.invoke([ { role: 'user', content: [ { type: 'text', text: 'Describe this image.', }, { type: 'image_url', image_url: 'https://example.com/image.png', }, ], },]) console.log(response.content)Supported image part types include image_url, input_image, and image. Depending on the type, image data can be provided through image_url, url, or data. MIME type hints are also supported through mime_type or media_type. Replace the example URL with a real image URL or valid image data.
The normalization process also tracks messageCount and the first system message as systemInstruction. These are normalization details, not additional fields on the public GeminiResponse.
Conversation history and state
To provide conversation context reliably, send the relevant user and assistant history again on each call. Reusing a sessionId does not remove the need to send history or guarantee that Gemini Web will continue a stateful conversation.
const history = [ { role: 'user', content: 'My name is Alex.' }, { role: 'assistant', content: 'Nice to meet you, Alex.' },] as const const first = await model.invoke(history) const second = await model.invoke([ ...history, { role: 'user', content: 'What is my name?' },]) console.log(first.content)console.log(second.content)Your application manages history
Keep conversation history in your application and pass the relevant messages to each call. This makes the context explicit instead of relying on undocumented server-side conversation persistence.
Session IDs
The SDK generates a session ID when one is not supplied. The ID is included in the request and returned in response.metadata.sessionId. You can pass that ID through the per-call sessionId option when you need to reuse it.
const first = await model.invoke( 'My name is Alex.',) const second = await model.invoke( [ { role: 'user', content: 'My name is Alex.' }, { role: 'assistant', content: first.content }, { role: 'user', content: 'What is my name?' }, ], { sessionId: first.metadata.sessionId, },) console.log(second.content)console.log(second.metadata.sessionId)A session ID is not conversation memory
Reusing an ID does not automatically load earlier messages. Continue sending the relevant conversation history yourself.
Streaming a conversation
stream() accepts the same GeminiInput shape as invoke(). It returns a promise that resolves to an async iterable of GeminiStreamChunk objects. Each chunk contains newly produced text in content and the accumulated text in accumulated.
const chunks = await model.stream([ { role: 'user', content: 'Explain AI memory in simple terms.', },]) for await (const chunk of chunks) { if (chunk.content) { process.stdout.write(chunk.content) } if (chunk.done) { console.log('\nFinished:', chunk.accumulated) }}Stream chunks also expose model and fallback information. The final successful chunk has done: true. Unlike invoke(), streaming does not return a GeminiResponse object with the same response metadata structure.
Temporary chats
Set temporaryChats: true in the client configuration or in individual call options to request the temporary-chat payload format used by Gemini Web. This changes the request payload and does not guarantee any particular upstream data-retention or privacy behavior.
const temporaryModel = new GeminiWeb({ model: 'gemini-3.6-flash', cookies, xsrfToken, temporaryChats: true,}) const clientResponse = await temporaryModel.invoke( 'Explain temporary chats briefly.',) const callResponse = await model.invoke( 'Explain temporary chats briefly.', { temporaryChats: true },) console.log(clientResponse.content)console.log(callResponse.content)Tool calls and tool results
Define tools with a name, description, and JSON Schema parameters. Use bindTools() to create a client configured with those tool definitions. The SDK represents tool instructions in the prompt and can parse tool calls from model output; this is prompt-based behavior rather than a native Gemini Web function-calling channel.
const modelWithTools = model.bindTools([ { name: 'get_weather', description: 'Get the weather for a city.', parameters: { type: 'object', properties: { city: { type: 'string' }, }, required: ['city'], }, },]) const response = await modelWithTools.invoke( 'Explain how a weather lookup tool could help a user.',) console.log(response.content)console.log(response.toolCalls)A tool call returned by the model is not automatically executed by your application. Inspect response.toolCalls, execute the corresponding application-side function, and send the result back as a message with role: "tool" and its name. The current GeminiMessage interface does not define a tool_call_id field. Whether a tool call is returned depends on the model response.
Keep secrets out of conversation history
Only send content intended for the model
The SDK includes supplied message content in the normalized prompt. Do not place passwords, session cookies, API keys, or other secrets in user, assistant, system, or tool message content unless the model genuinely needs that information and you have assessed the security implications.