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.
┌─────────────────────────────────────────────────────────────────┐
│ ONE TURN │
├─────────────────────────────────────────────────────────────────┤
│ │
│ send() Events │
│ │ │ │
│ │ ┌──────────────────────────┼─────────────────────────┐ │
│ └──►│ turnStart → textDelta* → [toolCall*] → turnEnd │ │
│ └──────────────────────────┼─────────────────────────┘ │
│ │ │
│ ▼ │
│ Your handlers │
│ │
└─────────────────────────────────────────────────────────────────┘
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
┌───────────────┐
│ CREATED │
└───────┬───────┘
│ createSession()
▼
┌───────────────┐
┌─────►│ ACTIVE │◄─────┐
│ └───────┬───────┘ │
│ │ │
send() │ tool result
│ ▼ │
│ ┌───────────────┐ │
└──────│ PROCESSING │──────┘
└───────┬───────┘
│ stopSession()
▼
┌───────────────┐
│ STOPPED │
└───────────────┘
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, see the Persisting Sessions cookbook recipe.
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?");