Skip to content

Commit 7390a28

Browse files
brettcannonCopilot
andauthored
[python] Refactor CopilotClient.create_session() and resume_session() to have parameters (#587)
* Refactor `CopilotClient.create_session()` to have parameters * Address PR review comments for create_session refactor - Add validation for on_permission_request in create_session to fail fast when handler is missing/invalid - Fix lambda signatures to accept two args (request, invocation) in test scenario and docs - Fix permissionDecision key to use camelCase in pre_tool_use hook Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add test for None permission handler validation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Merge with main * Fix test to use SubprocessConfig instead of dict Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Change the call signature of `resume_session()` * Fix formatting * Make on_permission_request and model keyword-only in Python SDK Update create_session() and resume_session() signatures so that on_permission_request and model are keyword-only parameters (after *). Update all call sites across test scenarios, unit tests, E2E tests, samples, and documentation to use keyword argument syntax. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Python E2E tests for keyword-only create_session parameters - Restore accidentally deleted custom_agents dict entries in test_agent_and_compact_rpc.py - Convert positional on_permission_request to keyword arg in test_compaction.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix formatting * Format docstrings * Fix a merge mistake --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 01208ca commit 7390a28

File tree

72 files changed

+825
-983
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+825
-983
lines changed

docs/auth/byok.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Azure AI Foundry (formerly Azure OpenAI) is a common BYOK deployment target for
2323
```python
2424
import asyncio
2525
import os
26-
from copilot import CopilotClient
26+
from copilot import CopilotClient, PermissionHandler
2727

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

35-
session = await client.create_session({
36-
"model": "gpt-5.2-codex", # Your deployment name
37-
"provider": {
38-
"type": "openai",
39-
"base_url": FOUNDRY_MODEL_URL,
40-
"wire_api": "responses", # Use "completions" for older models
41-
"api_key": os.environ["FOUNDRY_API_KEY"],
42-
},
35+
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5.2-codex", provider={
36+
"type": "openai",
37+
"base_url": FOUNDRY_MODEL_URL,
38+
"wire_api": "responses", # Use "completions" for older models
39+
"api_key": os.environ["FOUNDRY_API_KEY"],
4340
})
4441

4542
done = asyncio.Event()

docs/features/custom-agents.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ from copilot.types import PermissionRequestResult
7070
client = CopilotClient()
7171
await client.start()
7272

73-
session = await client.create_session({
74-
"model": "gpt-4.1",
75-
"custom_agents": [
73+
session = await client.create_session(
74+
on_permission_request=lambda req, inv: PermissionRequestResult(kind="approved"),
75+
model="gpt-4.1",
76+
custom_agents=[
7677
{
7778
"name": "researcher",
7879
"display_name": "Research Agent",
@@ -88,8 +89,7 @@ session = await client.create_session({
8889
"prompt": "You are a code editor. Make minimal, surgical changes to files as requested.",
8990
},
9091
],
91-
"on_permission_request": lambda req, inv: PermissionRequestResult(kind="approved"),
92-
})
92+
)
9393
```
9494

9595
</details>
@@ -258,8 +258,9 @@ const session = await client.createSession({
258258

259259
<!-- docs-validate: skip -->
260260
```python
261-
session = await client.create_session({
262-
"custom_agents": [
261+
session = await client.create_session(
262+
on_permission_request=PermissionHandler.approve_all,
263+
custom_agents=[
263264
{
264265
"name": "researcher",
265266
"prompt": "You are a research assistant. Analyze code and answer questions.",
@@ -269,8 +270,8 @@ session = await client.create_session({
269270
"prompt": "You are a code editor. Make minimal, surgical changes.",
270271
},
271272
],
272-
"agent": "researcher", # Pre-select the researcher agent
273-
})
273+
agent="researcher", # Pre-select the researcher agent
274+
)
274275
```
275276

276277
</details>

docs/features/hooks.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,15 @@ from copilot import CopilotClient
6565
client = CopilotClient()
6666
await client.start()
6767

68-
session = await client.create_session({
69-
"hooks": {
68+
session = await client.create_session(
69+
on_permission_request=lambda req, inv: {"kind": "approved"},
70+
hooks={
7071
"on_session_start": on_session_start,
7172
"on_pre_tool_use": on_pre_tool_use,
7273
"on_post_tool_use": on_post_tool_use,
7374
# ... add only the hooks you need
7475
},
75-
"on_permission_request": lambda req, inv: {"kind": "approved"},
76-
})
76+
)
7777
```
7878

7979
</details>
@@ -245,10 +245,10 @@ async def on_pre_tool_use(input_data, invocation):
245245
}
246246
return {"permissionDecision": "allow"}
247247

248-
session = await client.create_session({
249-
"hooks": {"on_pre_tool_use": on_pre_tool_use},
250-
"on_permission_request": lambda req, inv: {"kind": "approved"},
251-
})
248+
session = await client.create_session(
249+
on_permission_request=lambda req, inv: {"kind": "approved"},
250+
hooks={"on_pre_tool_use": on_pre_tool_use},
251+
)
252252
```
253253

254254
</details>
@@ -567,16 +567,16 @@ async def on_session_end(input_data, invocation):
567567
await f.write(json.dumps(audit_log, indent=2))
568568
return None
569569

570-
session = await client.create_session({
571-
"hooks": {
570+
session = await client.create_session(
571+
on_permission_request=lambda req, inv: {"kind": "approved"},
572+
hooks={
572573
"on_session_start": on_session_start,
573574
"on_user_prompt_submitted": on_user_prompt_submitted,
574575
"on_pre_tool_use": on_pre_tool_use,
575576
"on_post_tool_use": on_post_tool_use,
576577
"on_session_end": on_session_end,
577578
},
578-
"on_permission_request": lambda req, inv: {"kind": "approved"},
579-
})
579+
)
580580
```
581581

582582
</details>
@@ -666,13 +666,13 @@ async def on_error_occurred(input_data, invocation):
666666
])
667667
return None
668668

669-
session = await client.create_session({
670-
"hooks": {
669+
session = await client.create_session(
670+
on_permission_request=lambda req, inv: {"kind": "approved"},
671+
hooks={
671672
"on_session_end": on_session_end,
672673
"on_error_occurred": on_error_occurred,
673674
},
674-
"on_permission_request": lambda req, inv: {"kind": "approved"},
675-
})
675+
)
676676
```
677677

678678
</details>
@@ -905,15 +905,15 @@ async def on_session_end(input_data, invocation):
905905
)
906906
return None
907907

908-
session = await client.create_session({
909-
"hooks": {
908+
session = await client.create_session(
909+
on_permission_request=lambda req, inv: {"kind": "approved"},
910+
hooks={
910911
"on_session_start": on_session_start,
911912
"on_user_prompt_submitted": on_user_prompt_submitted,
912913
"on_pre_tool_use": on_pre_tool_use,
913914
"on_session_end": on_session_end,
914915
},
915-
"on_permission_request": lambda req, inv: {"kind": "approved"},
916-
})
916+
)
917917
```
918918

919919
</details>

docs/features/image-input.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ from copilot.types import PermissionRequestResult
7474
client = CopilotClient()
7575
await client.start()
7676

77-
session = await client.create_session({
78-
"model": "gpt-4.1",
79-
"on_permission_request": lambda req, inv: PermissionRequestResult(kind="approved"),
80-
})
77+
session = await client.create_session(
78+
on_permission_request=lambda req, inv: PermissionRequestResult(kind="approved"),
79+
model="gpt-4.1",
80+
)
8181

8282
await session.send(
8383
"Describe what you see in this image",

docs/features/mcp.md

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,32 +59,29 @@ const session = await client.createSession({
5959

6060
```python
6161
import asyncio
62-
from copilot import CopilotClient
62+
from copilot import CopilotClient, PermissionHandler
6363

6464
async def main():
6565
client = CopilotClient()
6666
await client.start()
6767

68-
session = await client.create_session({
69-
"model": "gpt-5",
70-
"mcp_servers": {
71-
# Local MCP server (stdio)
72-
"my-local-server": {
73-
"type": "local",
74-
"command": "python",
75-
"args": ["./mcp_server.py"],
76-
"env": {"DEBUG": "true"},
77-
"cwd": "./servers",
78-
"tools": ["*"],
79-
"timeout": 30000,
80-
},
81-
# Remote MCP server (HTTP)
82-
"github": {
83-
"type": "http",
84-
"url": "https://api.githubcopilot.com/mcp/",
85-
"headers": {"Authorization": "Bearer ${TOKEN}"},
86-
"tools": ["*"],
87-
},
68+
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5", mcp_servers={
69+
# Local MCP server (stdio)
70+
"my-local-server": {
71+
"type": "local",
72+
"command": "python",
73+
"args": ["./mcp_server.py"],
74+
"env": {"DEBUG": "true"},
75+
"cwd": "./servers",
76+
"tools": ["*"],
77+
"timeout": 30000,
78+
},
79+
# Remote MCP server (HTTP)
80+
"github": {
81+
"type": "http",
82+
"url": "https://api.githubcopilot.com/mcp/",
83+
"headers": {"Authorization": "Bearer ${TOKEN}"},
84+
"tools": ["*"],
8885
},
8986
})
9087

docs/features/session-persistence.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,13 @@ await session.sendAndWait({ prompt: "Analyze my codebase" });
4646
### Python
4747

4848
```python
49-
from copilot import CopilotClient
49+
from copilot import CopilotClient, PermissionHandler
5050

5151
client = CopilotClient()
5252
await client.start()
5353

5454
# Create a session with a meaningful ID
55-
session = await client.create_session({
56-
"session_id": "user-123-task-456",
57-
"model": "gpt-5.2-codex",
58-
})
55+
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5.2-codex", session_id="user-123-task-456")
5956

6057
# Do some work...
6158
await session.send_and_wait({"prompt": "Analyze my codebase"})
@@ -160,7 +157,7 @@ await session.sendAndWait({ prompt: "What did we discuss earlier?" });
160157

161158
```python
162159
# Resume from a different client instance (or after restart)
163-
session = await client.resume_session("user-123-task-456")
160+
session = await client.resume_session("user-123-task-456", on_permission_request=PermissionHandler.approve_all)
164161

165162
# Continue where you left off
166163
await session.send_and_wait({"prompt": "What did we discuss earlier?"})

docs/features/skills.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ async def main():
4949
client = CopilotClient()
5050
await client.start()
5151

52-
session = await client.create_session({
53-
"model": "gpt-4.1",
54-
"skill_directories": [
52+
session = await client.create_session(
53+
on_permission_request=lambda req, inv: {"kind": "approved"},
54+
model="gpt-4.1",
55+
skill_directories=[
5556
"./skills/code-review",
5657
"./skills/documentation",
5758
],
58-
"on_permission_request": lambda req, inv: PermissionRequestResult(kind="approved"),
59-
})
59+
)
6060

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

162162
```python
163-
session = await client.create_session({
164-
"skill_directories": ["./skills"],
165-
"disabled_skills": ["experimental-feature", "deprecated-tool"],
166-
})
163+
from copilot import PermissionHandler
164+
165+
session = await client.create_session(
166+
on_permission_request=PermissionHandler.approve_all,
167+
skill_directories=["./skills"],
168+
disabled_skills=["experimental-feature", "deprecated-tool"],
169+
)
167170
```
168171

169172
</details>

docs/features/steering-and-queueing.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ async def main():
7676
client = CopilotClient()
7777
await client.start()
7878

79-
session = await client.create_session({
80-
"model": "gpt-4.1",
81-
"on_permission_request": lambda req, inv: PermissionRequestResult(kind="approved"),
82-
})
79+
session = await client.create_session(
80+
on_permission_request=lambda req, inv: PermissionRequestResult(kind="approved"),
81+
model="gpt-4.1",
82+
)
8383

8484
# Start a long-running task
8585
msg_id = await session.send({
@@ -235,10 +235,10 @@ async def main():
235235
client = CopilotClient()
236236
await client.start()
237237

238-
session = await client.create_session({
239-
"model": "gpt-4.1",
240-
"on_permission_request": lambda req, inv: PermissionRequestResult(kind="approved"),
241-
})
238+
session = await client.create_session(
239+
on_permission_request=lambda req, inv: PermissionRequestResult(kind="approved"),
240+
model="gpt-4.1",
241+
)
242242

243243
# Send an initial task
244244
await session.send({"prompt": "Set up the project structure"})
@@ -431,10 +431,10 @@ await session.send({
431431
<summary><strong>Python</strong></summary>
432432

433433
```python
434-
session = await client.create_session({
435-
"model": "gpt-4.1",
436-
"on_permission_request": lambda req, inv: PermissionRequestResult(kind="approved"),
437-
})
434+
session = await client.create_session(
435+
on_permission_request=lambda req, inv: PermissionRequestResult(kind="approved"),
436+
model="gpt-4.1",
437+
)
438438

439439
# Start a task
440440
await session.send({"prompt": "Refactor the database layer"})

0 commit comments

Comments
 (0)