Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8283fb9
Refactor `CopilotClient.create_session()` to have parameters
brettcannon Feb 25, 2026
84372b7
Address PR review comments for create_session refactor
brettcannon Feb 26, 2026
6b03aae
Add test for None permission handler validation
brettcannon Feb 26, 2026
3a6773f
Merge branch 'main' of https://github.com/github/copilot-sdk into cre…
brettcannon Feb 26, 2026
95341f8
Merge remote-tracking branch 'upstream/main' into create_session
brettcannon Feb 27, 2026
402dc80
Merge remote-tracking branch 'upstream/main' into create_session
brettcannon Mar 12, 2026
90b0e46
Merge with main
brettcannon Mar 12, 2026
56b51cd
Resolve merge conflicts with main
brettcannon Mar 13, 2026
768ddc8
Fix test to use SubprocessConfig instead of dict
brettcannon Mar 13, 2026
bae8862
Change the call signature of `resume_session()`
brettcannon Mar 13, 2026
d3295ae
Merge remote-tracking branch 'upstream' into create_session
brettcannon Mar 16, 2026
2b9bdf1
Fix formatting
brettcannon Mar 16, 2026
92d2ef8
Make on_permission_request and model keyword-only in Python SDK
brettcannon Mar 16, 2026
a71f8b0
Fix Python E2E tests for keyword-only create_session parameters
brettcannon Mar 16, 2026
b6c8fd6
Fix formatting
brettcannon Mar 16, 2026
d68f2a4
Format docstrings
brettcannon Mar 16, 2026
ed3954c
Merge remote-tracking branch 'upstream/main' into create_session
brettcannon Mar 18, 2026
efba357
Merge remote-tracking branch 'upstream/main' into create_session
brettcannon Mar 19, 2026
f2af0ae
Fix a merge mistake
brettcannon Mar 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions docs/auth/byok.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Azure AI Foundry (formerly Azure OpenAI) is a common BYOK deployment target for
```python
import asyncio
import os
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

FOUNDRY_MODEL_URL = "https://your-resource.openai.azure.com/openai/v1/"
# Set FOUNDRY_API_KEY environment variable
Expand All @@ -32,14 +32,11 @@ async def main():
client = CopilotClient()
await client.start()

session = await client.create_session({
"model": "gpt-5.2-codex", # Your deployment name
"provider": {
"type": "openai",
"base_url": FOUNDRY_MODEL_URL,
"wire_api": "responses", # Use "completions" for older models
"api_key": os.environ["FOUNDRY_API_KEY"],
},
session = await client.create_session(PermissionHandler.approve_all, "gpt-5.2-codex", provider={
"type": "openai",
"base_url": FOUNDRY_MODEL_URL,
"wire_api": "responses", # Use "completions" for older models
"api_key": os.environ["FOUNDRY_API_KEY"],
})

done = asyncio.Event()
Expand Down
29 changes: 9 additions & 20 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ Create `main.py`:

```python
import asyncio
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

async def main():
client = CopilotClient()
await client.start()

session = await client.create_session({"model": "gpt-4.1"})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1")
response = await session.send_and_wait({"prompt": "What is 2 + 2?"})

print(response.data.content)
Expand Down Expand Up @@ -274,17 +274,14 @@ Update `main.py`:
```python
import asyncio
import sys
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler
from copilot.generated.session_events import SessionEventType

async def main():
client = CopilotClient()
await client.start()

session = await client.create_session({
"model": "gpt-4.1",
"streaming": True,
})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1", streaming=True)

# Listen for response chunks
def handle_event(event):
Expand Down Expand Up @@ -565,7 +562,7 @@ Update `main.py`:
import asyncio
import random
import sys
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field
Expand All @@ -588,11 +585,7 @@ async def main():
client = CopilotClient()
await client.start()

session = await client.create_session({
"model": "gpt-4.1",
"streaming": True,
"tools": [get_weather],
})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1", streaming=True, tools=[get_weather])

def handle_event(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
Expand Down Expand Up @@ -837,7 +830,7 @@ Create `weather_assistant.py`:
import asyncio
import random
import sys
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler
from copilot.tools import define_tool
from copilot.generated.session_events import SessionEventType
from pydantic import BaseModel, Field
Expand All @@ -857,11 +850,7 @@ async def main():
client = CopilotClient()
await client.start()

session = await client.create_session({
"model": "gpt-4.1",
"streaming": True,
"tools": [get_weather],
})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1", streaming=True, tools=[get_weather])

def handle_event(event):
if event.type == SessionEventType.ASSISTANT_MESSAGE_DELTA:
Expand Down Expand Up @@ -1218,7 +1207,7 @@ client = CopilotClient({
await client.start()

# Use the client normally
session = await client.create_session({"on_permission_request": PermissionHandler.approve_all})
session = await client.create_session(PermissionHandler.approve_all)
# ...
```

Expand Down
7 changes: 2 additions & 5 deletions docs/guides/session-persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,13 @@ await session.sendAndWait({ prompt: "Analyze my codebase" });
### Python

```python
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

client = CopilotClient()
await client.start()

# Create a session with a meaningful ID
session = await client.create_session({
"session_id": "user-123-task-456",
"model": "gpt-5.2-codex",
})
session = await client.create_session(PermissionHandler.approve_all, "gpt-5.2-codex", session_id="user-123-task-456")

# Do some work...
await session.send_and_wait({"prompt": "Analyze my codebase"})
Expand Down
44 changes: 20 additions & 24 deletions docs/guides/setup/azure-managed-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import asyncio
import os

from azure.identity import DefaultAzureCredential
from copilot import CopilotClient, ProviderConfig, SessionConfig
from copilot import CopilotClient, PermissionHandler

COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default"

Expand All @@ -58,15 +58,14 @@ async def main():
await client.start()

session = await client.create_session(
SessionConfig(
model="gpt-4.1",
provider=ProviderConfig(
type="openai",
base_url=f"{foundry_url.rstrip('/')}/openai/v1/",
bearer_token=token, # Short-lived bearer token
wire_api="responses",
),
)
PermissionHandler.approve_all,
"gpt-4.1",
provider={
"type": "openai",
"base_url": f"{foundry_url.rstrip('/')}/openai/v1/",
"bearer_token": token, # Short-lived bearer token
"wire_api": "responses",
},
)

response = await session.send_and_wait({"prompt": "Hello from Managed Identity!"})
Expand All @@ -84,7 +83,7 @@ Bearer tokens expire (typically after ~1 hour). For servers or long-running agen

```python
from azure.identity import DefaultAzureCredential
from copilot import CopilotClient, ProviderConfig, SessionConfig
from copilot import CopilotClient, PermissionHandler

COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default"

Expand All @@ -98,24 +97,21 @@ class ManagedIdentityCopilotAgent:
self.credential = DefaultAzureCredential()
self.client = CopilotClient()

def _get_session_config(self) -> SessionConfig:
"""Build a SessionConfig with a fresh bearer token."""
def _get_provider_config(self) -> dict:
"""Build a provider config dict with a fresh bearer token."""
token = self.credential.get_token(COGNITIVE_SERVICES_SCOPE).token
return SessionConfig(
model=self.model,
provider=ProviderConfig(
type="openai",
base_url=f"{self.foundry_url}/openai/v1/",
bearer_token=token,
wire_api="responses",
),
)
return {
"type": "openai",
"base_url": f"{self.foundry_url}/openai/v1/",
"bearer_token": token,
"wire_api": "responses",
}

async def chat(self, prompt: str) -> str:
"""Send a prompt and return the response text."""
# Fresh token for each session
config = self._get_session_config()
session = await self.client.create_session(config)
provider = self._get_provider_config()
session = await self.client.create_session(PermissionHandler.approve_all, self.model, provider=provider)

response = await session.send_and_wait({"prompt": prompt})
await session.destroy()
Expand Down
7 changes: 2 additions & 5 deletions docs/guides/setup/backend-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,14 @@ res.json({ content: response?.data.content });
<summary><strong>Python</strong></summary>

```python
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

client = CopilotClient({
"cli_url": "localhost:4321",
})
await client.start()

session = await client.create_session({
"session_id": f"user-{user_id}-{int(time.time())}",
"model": "gpt-4.1",
})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1", session_id=f"user-{user_id}-{int(time.time())}")

response = await session.send_and_wait({"prompt": message})
```
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/setup/bundled-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ await client.stop();
<summary><strong>Python</strong></summary>

```python
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler
from pathlib import Path

client = CopilotClient({
"cli_path": str(Path(__file__).parent / "vendor" / "copilot"),
})
await client.start()

session = await client.create_session({"model": "gpt-4.1"})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1")
response = await session.send_and_wait({"prompt": "Hello!"})
print(response.data.content)

Expand Down
13 changes: 5 additions & 8 deletions docs/guides/setup/byok.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,18 +93,15 @@ await client.stop();

```python
import os
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

client = CopilotClient()
await client.start()

session = await client.create_session({
"model": "gpt-4.1",
"provider": {
"type": "openai",
"base_url": "https://api.openai.com/v1",
"api_key": os.environ["OPENAI_API_KEY"],
},
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1", provider={
"type": "openai",
"base_url": "https://api.openai.com/v1",
"api_key": os.environ["OPENAI_API_KEY"],
})

response = await session.send_and_wait({"prompt": "Hello!"})
Expand Down
7 changes: 2 additions & 5 deletions docs/guides/setup/github-oauth.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ const response = await session.sendAndWait({ prompt: "Hello!" });
<summary><strong>Python</strong></summary>

```python
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

def create_client_for_user(user_token: str) -> CopilotClient:
return CopilotClient({
Expand All @@ -157,10 +157,7 @@ def create_client_for_user(user_token: str) -> CopilotClient:
client = create_client_for_user("gho_user_access_token")
await client.start()

session = await client.create_session({
"session_id": f"user-{user_id}-session",
"model": "gpt-4.1",
})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1", session_id=f"user-{user_id}-session")

response = await session.send_and_wait({"prompt": "Hello!"})
```
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/setup/local-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ await client.stop();
<summary><strong>Python</strong></summary>

```python
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

client = CopilotClient()
await client.start()

session = await client.create_session({"model": "gpt-4.1"})
session = await client.create_session(PermissionHandler.approve_all, "gpt-4.1")
response = await session.send_and_wait({"prompt": "Hello!"})
print(response.data.content)

Expand Down
21 changes: 12 additions & 9 deletions docs/guides/skills.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ async def main():
client = CopilotClient()
await client.start()

session = await client.create_session({
"model": "gpt-4.1",
"skill_directories": [
session = await client.create_session(
lambda req: {"kind": "approved"},
"gpt-4.1",
skill_directories=[
"./skills/code-review",
"./skills/documentation",
],
"on_permission_request": lambda req: {"kind": "approved"},
})
)

# Copilot now has access to skills in those directories
await session.send_and_wait({"prompt": "Review this code for security issues"})
Expand Down Expand Up @@ -159,10 +159,13 @@ const session = await client.createSession({
<summary><strong>Python</strong></summary>

```python
session = await client.create_session({
"skill_directories": ["./skills"],
"disabled_skills": ["experimental-feature", "deprecated-tool"],
})
from copilot import PermissionHandler

session = await client.create_session(
PermissionHandler.approve_all,
skill_directories=["./skills"],
disabled_skills=["experimental-feature", "deprecated-tool"],
)
```

</details>
Expand Down
6 changes: 3 additions & 3 deletions docs/hooks/error-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ const session = await client.createSession({
<summary><strong>Python</strong></summary>

```python
from copilot import PermissionHandler

async def on_error_occurred(input_data, invocation):
print(f"[{invocation['session_id']}] Error: {input_data['error']}")
print(f" Context: {input_data['errorContext']}")
print(f" Recoverable: {input_data['recoverable']}")
return None

session = await client.create_session({
"hooks": {"on_error_occurred": on_error_occurred}
})
session = await client.create_session(PermissionHandler.approve_all, hooks={"on_error_occurred": on_error_occurred})
```

</details>
Expand Down
8 changes: 3 additions & 5 deletions docs/hooks/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const session = await client.createSession({
<summary><strong>Python</strong></summary>

```python
from copilot import CopilotClient
from copilot import CopilotClient, PermissionHandler

async def main():
client = CopilotClient()
Expand All @@ -70,13 +70,11 @@ async def main():
async def on_session_start(input_data, invocation):
return {"additionalContext": "User prefers concise answers."}

session = await client.create_session({
"hooks": {
session = await client.create_session(PermissionHandler.approve_all, hooks={
"on_pre_tool_use": on_pre_tool_use,
"on_post_tool_use": on_post_tool_use,
"on_session_start": on_session_start,
}
})
})
```

</details>
Expand Down
Loading
Loading