Sessions
Understanding how conversations work in the Copilot SDK.
What is a Session?
A session is an independent conversation with Copilot. Think of it like opening a new chat window - each session has its own:
- Message history
- System prompt (optional)
- Tool configurations
- State (running, stopped)
Creating Sessions
// Basic session
const session = await client.createSession();
// Session with custom system prompt
const session = await client.createSession({
systemMessage: "You are a helpful code reviewer. Be concise and direct."
});
// Session with specific tools
const session = await client.createSession({
tools: [myWeatherTool, mySearchTool]
});
The Turn Model
Interaction happens in turns. A turn starts when you send a message and ends when Copilot finishes responding.
sequenceDiagram
participant App
participant Session as Copilot Session
participant Tool as Optional Tool Handler
App->>Session: send()
Session-->>App: turnStart
Session-->>App: textDelta*
opt Tool needed
Session-->>App: toolCall
App->>Tool: Run handler
Tool-->>App: Tool result
App->>Session: submitToolResult()
end
Session-->>App: turnEnd
Events in a turn:
turnStart- Copilot begins generatingtextDelta(repeated) - Response tokens stream intoolCall(optional) - Copilot wants to use a toolturnEnd- Generation complete
Sending Messages
Simple send (wait for completion)
const response = await session.send("Explain async/await in JavaScript");
console.log(response.text); // Full response text
Streaming (handle events as they arrive)
for await (const event of session.send("Explain async/await")) {
switch (event.type) {
case "textDelta":
process.stdout.write(event.delta); // Print as it streams
break;
case "turnEnd":
console.log("\n[Done]");
break;
}
}
With attachments
// Attach file content
const response = await session.send({
content: "Review this code",
attachments: [{
type: "text",
filename: "app.ts",
content: "const x = 1;\nconst y = 2;"
}]
});
// Attach image
const response = await session.send({
content: "What's in this image?",
attachments: [{
type: "image",
mediaType: "image/png",
data: base64ImageData
}]
});
Session Isolation
Sessions are completely independent:
const session1 = await client.createSession();
const session2 = await client.createSession();
// These don't affect each other
await session1.send("My name is Alice");
await session2.send("My name is Bob");
// session1 knows "Alice", session2 knows "Bob"
await session1.send("What's my name?"); // "Alice"
await session2.send("What's my name?"); // "Bob"
Use cases for multiple sessions:
- Parallel task processing
- Different system prompts for different purposes
- Isolating user conversations in a multi-tenant app
Session Lifecycle
stateDiagram-v2
[*] --> Active: createSession()
Active --> Processing: send()
Processing --> Processing: toolCall / submitToolResult()
Processing --> Active: turnEnd
Active --> Stopped: stopSession()
Processing --> Stopped: stopSession()
Stopped --> [*]
Activemeans the session is ready for a new turn.Processingmeans a turn is currently in flight, including any tool-call pauses.- One session processes one turn at a time; use multiple sessions for parallel work.
Stopping Sessions
// Stop a specific session
await client.stopSession(session.id);
// Or close the entire client (stops all sessions)
await client.close();
When to stop sessions:
- User conversation ends
- Task is complete
- Error requires session reset
- Resource cleanup
Session Persistence
Sessions exist only in memory by default. For persistence across restarts, you’ll need to implement session serialization.
Basic pattern:
- Export session state (messages, system prompt)
- Save to disk/database
- On restart, recreate session with saved state
Concurrency
Multiple sends on the same session are queued (only one turn at a time). For parallel work:
// Sequential (one at a time on same session)
await session.send("Question 1");
await session.send("Question 2");
// Parallel (different sessions)
const [r1, r2] = await Promise.all([
session1.send("Question 1"),
session2.send("Question 2")
]);
Common Patterns
Context window management
Copilot automatically handles context, but long conversations may lose early messages. Reset periodically for long-running apps:
// Summarize and restart
const summary = await session.send("Summarize our conversation so far");
await client.stopSession(session.id);
const newSession = await client.createSession({
systemMessage: `Previous context: ${summary.text}`
});
Branching conversations
Create new sessions from a “checkpoint”:
const checkpoint = session.getMessages(); // If API supports this
// Branch 1
const branch1 = await client.createSession({ messages: checkpoint });
await branch1.send("What if we use React?");
// Branch 2
const branch2 = await client.createSession({ messages: checkpoint });
await branch2.send("What if we use Vue?");