Skip to content

Add reasoningEffort to setModel/session.model.switchTo across all SDKs#712

Open
patniko wants to merge 2 commits intomainfrom
fix/setmodel-reasoning-effort-and-byok
Open

Add reasoningEffort to setModel/session.model.switchTo across all SDKs#712
patniko wants to merge 2 commits intomainfrom
fix/setmodel-reasoning-effort-and-byok

Conversation

@patniko
Copy link
Contributor

@patniko patniko commented Mar 8, 2026

Summary

All four SDKs now support passing reasoningEffort when switching models mid-session via setModel(). The parameter is optional and fully backward-compatible.

API Changes

SDK Signature
Node.js setModel(model, options?: { reasoningEffort? })
Python set_model(model, *, reasoning_effort=None)
Go SetModel(ctx, model, opts ...*SetModelOptions)
.NET SetModelAsync(model, reasoningEffort?, cancellationToken?)

Usage Examples

// Node.js
await session.setModel("claude-sonnet-4.6", { reasoningEffort: "high" });
# Python
await session.set_model("claude-sonnet-4.6", reasoning_effort="high")
// Go
session.SetModel(ctx, "claude-sonnet-4.6", &copilot.SetModelOptions{ReasoningEffort: "high"})
// .NET
await session.SetModelAsync("claude-sonnet-4.6", reasoningEffort: "high");

Files Changed

  • nodejs/src/session.ts + nodejs/src/generated/rpc.ts
  • python/copilot/session.py + python/copilot/generated/rpc.py
  • go/session.go + go/rpc/generated_rpc.go
  • dotnet/src/Session.cs + dotnet/src/Generated/Rpc.cs

Companion PR

Fixes #687

Copilot AI review requested due to automatic review settings March 8, 2026 04:55
@patniko patniko requested a review from a team as a code owner March 8, 2026 04:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for passing an optional reasoningEffort when switching models mid-session (session.model.switchTo / setModel / set_model) across the Node.js, Python, Go, and .NET SDKs, aligning with the runtime capability introduced in the companion runtime PR.

Changes:

  • Extend each SDK’s session-level “switch model” API to accept optional reasoningEffort.
  • Update generated RPC parameter types in each language to serialize reasoningEffort as reasoningEffort on the wire.
  • Update inline docs/examples to demonstrate setting reasoningEffort during a model switch.

Reviewed changes

Copilot reviewed 5 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
python/copilot/session.py Adds keyword-only reasoning_effort to set_model() and forwards it to RPC.
python/copilot/generated/rpc.py Extends SessionModelSwitchToParams to include optional reasoning_effort serialization.
nodejs/src/session.ts Extends setModel() to accept an options bag and forwards reasoningEffort.
nodejs/src/generated/rpc.ts Extends SessionModelSwitchToParams to include optional reasoningEffort union type.
go/session.go Adds SetModelOptions and forwards ReasoningEffort (as optional) to RPC.
go/rpc/generated_rpc.go Extends SessionModelSwitchToParams and request building to include reasoningEffort.
dotnet/src/Session.cs Adds optional reasoningEffort parameter and forwards it to RPC.
dotnet/src/Generated/Rpc.cs Extends the generated request type and SwitchToAsync signature to include reasoningEffort.

Comment on lines 671 to 675
public async Task<SessionModelSwitchToResult> SwitchToAsync(string modelId, string? reasoningEffort = null, CancellationToken cancellationToken = default)
{
var request = new SessionModelSwitchToRequest { SessionId = _sessionId, ModelId = modelId };
var request = new SessionModelSwitchToRequest { SessionId = _sessionId, ModelId = modelId, ReasoningEffort = reasoningEffort };
return await CopilotClient.InvokeRpcAsync<SessionModelSwitchToResult>(_rpc, "session.model.switchTo", [request], cancellationToken);
}
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ModelApi.SwitchToAsync now takes (string modelId, string? reasoningEffort = null, CancellationToken cancellationToken = default), which similarly breaks any existing callers that passed a CancellationToken as the second positional argument. Consider adding a backward-compatible overload SwitchToAsync(string modelId, CancellationToken cancellationToken = default) that forwards to the new method (or otherwise avoid inserting parameters before cancellationToken in public APIs).

Copilot uses AI. Check for mistakes.
>>> await session.set_model("claude-sonnet-4.6", reasoning_effort="high")
"""
await self.rpc.model.switch_to(SessionModelSwitchToParams(model_id=model))
await self.rpc.model.switch_to(SessionModelSwitchToParams(model_id=model, reasoning_effort=reasoning_effort))
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call is long enough that it will be reformatted by ruff format (the repo enforces ruff format --check in CI with a 100 character line length). To avoid CI formatting diffs/failures, wrap the SessionModelSwitchToParams(...) construction and/or the switch_to(...) call across multiple lines in the style used elsewhere in this file.

Suggested change
await self.rpc.model.switch_to(SessionModelSwitchToParams(model_id=model, reasoning_effort=reasoning_effort))
await self.rpc.model.switch_to(
SessionModelSwitchToParams(
model_id=model,
reasoning_effort=reasoning_effort,
)
)

Copilot uses AI. Check for mistakes.
go/session.go Outdated
Comment on lines +705 to +710
func (s *Session) SetModel(ctx context.Context, model string, opts ...*SetModelOptions) error {
params := &rpc.SessionModelSwitchToParams{ModelID: model}
if len(opts) > 0 && opts[0] != nil && opts[0].ReasoningEffort != "" {
re := opts[0].ReasoningEffort
params.ReasoningEffort = &re
}
Copy link

Copilot AI Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SetModel accepts a variadic opts ...*SetModelOptions, but only opts[0] is ever read. This makes it easy to accidentally pass multiple option structs and have all but the first silently ignored. Consider either validating len(opts) <= 1 (and returning an error if more are provided) or changing the API shape to avoid a variadic when only a single options value is supported.

Copilot uses AI. Check for mistakes.
@patniko patniko force-pushed the fix/setmodel-reasoning-effort-and-byok branch from fbffd30 to 2910573 Compare March 8, 2026 05:10
@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

✅ Cross-SDK Consistency Review

This PR demonstrates excellent cross-SDK consistency for adding reasoningEffort support to the model switching APIs. All four SDKs (Node.js, Python, Go, .NET) receive the same feature with appropriate language-specific patterns.

Consistency Highlights

Feature parity: All SDKs now support reasoningEffort when switching models
Naming conventions: Each language follows its idiomatic casing (camelCase, snake_case, PascalCase)
Type safety: All SDKs use proper enums/unions for the four effort levels (low, medium, high, xhigh)
Documentation: Examples updated across all SDKs showing the new parameter
Backward compatibility: Most SDKs maintain full backward compatibility via optional parameters

API Signatures (all semantically equivalent)

SDK Signature
Node.js setModel(model, options?: { reasoningEffort? })
Python set_model(model, *, reasoning_effort=None)
Go SetModel(ctx, model, opts *SetModelOptions)
.NET SetModelAsync(model, reasoningEffort?, cancellationToken?)

Note: Go Breaking Change

⚠️ The Go SDK signature changes from SetModel(ctx, model) to SetModel(ctx, model, opts), requiring existing callers to pass nil for the options parameter if they don't need reasoning effort. This is acceptable for Go's idioms, and the PR description clearly documents the new signature.

Additional Feature

This PR also consistently adds session.log() RPC support across all generated files, maintaining the same level of cross-SDK parity for this bonus feature.

Recommendation: Approve — this PR maintains excellent consistency across all SDK implementations. 🚀

Generated by SDK Consistency Review Agent for issue #712 ·

@patniko patniko force-pushed the fix/setmodel-reasoning-effort-and-byok branch from 2910573 to f35bf5c Compare March 8, 2026 05:15
@github github deleted a comment from Copilot AI Mar 8, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

✅ SDK Consistency Review: APPROVED with one minor observation

Great work on maintaining consistency across all four SDKs! This PR successfully adds the reasoningEffort parameter to the setModel/set_model/SetModel/SetModelAsync methods across all four language implementations.

✅ What's Consistent

  1. Feature parity: All SDKs (Node.js, Python, Go, .NET) now support reasoningEffort
  2. API naming: Follows proper language conventions:
    • Node.js: reasoningEffort (camelCase)
    • Python: reasoning_effort (snake_case)
    • Go: ReasoningEffort (PascalCase)
    • .NET: reasoningEffort parameter, ReasoningEffort enum (PascalCase)
  3. Optional parameter: All implementations make it optional/nullable
  4. Enum values: Consistent across all SDKs: "low" | "medium" | "high" | "xhigh"
  5. Documentation: Examples added for all languages
  6. Backward compatibility:
    • Node.js/Python: Optional parameter (backward compatible)
    • Go: Uses options pattern with nil default (requires signature change but idiomatic)
    • .NET: Provides overload for backward compatibility
  7. Tests updated: All breaking test calls updated to pass nil/null for the new parameter

📋 Minor Observation

I noticed that the generated RPC files include a new session.log RPC method in Node.js, Python, and Go, but this doesn't appear in the .NET generated file. This is likely expected if the .NET code generation hasn't been run yet, or if there's a difference in what schema version each SDK is using for codegen.

Recommendation: If session.log is intended as a new feature, ensure all SDKs regenerate from the same schema version. If it's not part of this PR's scope, you can ignore this note.


Verdict: The reasoningEffort feature is excellently consistent across all four SDKs. No action required for the core feature of this PR. 🎉

Generated by SDK Consistency Review Agent for issue #712 ·

@patniko patniko force-pushed the fix/setmodel-reasoning-effort-and-byok branch from f35bf5c to f6ee586 Compare March 8, 2026 05:22
@github-actions
Copy link
Contributor

github-actions bot commented Mar 8, 2026

✅ Cross-SDK Consistency Review: PASSED

I've reviewed this PR for consistency across all four SDK implementations (Node.js, Python, Go, and .NET). The changes maintain excellent cross-SDK consistency.

Summary

All four SDKs now support the reasoningEffort parameter when switching models via setModel/set_model/SetModel/SetModelAsync, with:

  • Full feature parity across all languages
  • Appropriate language-specific idioms (optional param in TS, keyword-only in Python, options struct in Go, nullable enum in .NET)
  • Consistent valid values: "low", "medium", "high", "xhigh"
  • Backward compatibility maintained in all implementations
  • Updated documentation and examples in all SDKs
  • Test coverage added/updated appropriately

Implementation Details

SDK Signature Pattern
Node.js setModel(model, options?: { reasoningEffort? }) Optional parameter object
Python set_model(model, *, reasoning_effort=None) Keyword-only argument
Go SetModel(ctx, model, opts *SetModelOptions) Options struct (idiomatic Go)
.NET SetModelAsync(model, reasoningEffort?, cancellationToken?) Nullable enum + overload

Each approach follows the established conventions for that language while maintaining semantic equivalence.

No consistency issues found. 🎉

Generated by SDK Consistency Review Agent for issue #712 ·

@patniko patniko force-pushed the fix/setmodel-reasoning-effort-and-byok branch from f6ee586 to 518256d Compare March 8, 2026 05:37
@patniko
Copy link
Contributor Author

patniko commented Mar 8, 2026

@SteveSandersonMS need to get #4408 in and released first.


/// <summary>Calls "session.model.switchTo".</summary>
public async Task<SessionModelSwitchToResult> SwitchToAsync(string modelId, CancellationToken cancellationToken = default)
public async Task<SessionModelSwitchToResult> SwitchToAsync(string modelId, SessionModelSwitchToRequestReasoningEffort? reasoningEffort, CancellationToken cancellationToken = default)
Copy link

@IeuanWalker IeuanWalker Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note, the reasoning effort is currently a string? everywhere else (getting list of models, creating/ resuming session, etc), so feels a bit weird that its an enum here.

As it would require us to parse the string? that the SDK returns into this enum to change it mid session

Wouldnt be an issue if it was an enum throughout SDK

All four SDKs now support passing reasoningEffort when switching models
mid-session via setModel(). The parameter is optional and backward-compatible.

- Node.js: setModel(model, { reasoningEffort? })
- Python:  set_model(model, *, reasoning_effort=None)
- Go:      SetModel(ctx, model, opts ...*SetModelOptions)
- .NET:    SetModelAsync(model, reasoningEffort?, cancellationToken?)

Fixes #687

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@SteveSandersonMS SteveSandersonMS force-pushed the fix/setmodel-reasoning-effort-and-byok branch from 518256d to c0c4635 Compare March 10, 2026 16:35
@github-actions
Copy link
Contributor

✅ Cross-SDK Consistency Review: PASSED

This PR demonstrates excellent consistency across all four SDK implementations. The reasoningEffort parameter has been added to setModel/SetModel with appropriate language-specific idioms while maintaining semantic equivalence.

Consistency Analysis

✅ API Signatures (accounting for language conventions)

SDK Signature Idiomatic ✓
Node.js setModel(model, options?: { reasoningEffort? }) ✅ camelCase, optional object parameter
Python set_model(model, *, reasoning_effort=None) ✅ snake_case, keyword-only argument
Go SetModel(ctx, model, opts *SetModelOptions) ✅ PascalCase (exported), options struct pattern
.NET SetModelAsync(model, reasoningEffort?, cancellationToken?) ✅ PascalCase, optional parameter with overload

✅ Implementation Details

  1. Parameter optionality: All implementations make reasoningEffort optional and backward-compatible
  2. Type constraints: All SDKs support the same effort levels: "low", "medium", "high", "xhigh"
  3. Documentation: All implementations include:
    • Updated docstrings/XML docs
    • Usage examples with the new parameter
    • Clear descriptions of the parameter's purpose
  4. Backward compatibility:
    • Node.js: Optional parameter (existing calls still work)
    • Python: Keyword-only argument with default None
    • Go: Nullable options struct (pass nil to skip)
    • .NET: Optional parameter + explicit overload for CancellationToken scenarios
  5. Test coverage: Tests updated in Go and .NET to pass the new parameter

✅ RPC Layer Consistency

All SDKs correctly pass the parameter to the underlying RPC method:

  • Node.js: Spreads options into rpc.model.switchTo()
  • Python: Passes to SessionModelSwitchToParams
  • Go: Conditionally sets params.ReasoningEffort if opts provided
  • .NET: Passes directly to Rpc.Model.SwitchToAsync()

Recommendation

No consistency issues found. This PR maintains excellent feature parity across all SDKs. The implementation respects language-specific conventions while ensuring the same functionality is available everywhere. ✅

Generated by SDK Consistency Review Agent for issue #712 ·

…, fix .NET overloads

- Go: use variadic ...SetModelOptions for backward compatibility
- TypeScript: reuse ReasoningEffort type instead of inline union
- .NET: remove redundant default on reasoningEffort param, make CancellationToken optional in both overloads
- Revert unrelated dotnet/test/RpcTests.cs change

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor

✅ Cross-SDK Consistency Review

Great work on maintaining consistency across all four SDK implementations! The reasoningEffort parameter has been added uniformly to the setModel/set_model/SetModel APIs.

API Consistency ✓

All four SDKs follow the expected language conventions:

SDK Signature Pattern
Node.js setModel(model, options?: { reasoningEffort? }) Optional options object (idiomatic TS)
Python set_model(model, *, reasoning_effort=None) Keyword-only argument (idiomatic Python)
Go SetModel(ctx, model, opts ...SetModelOptions) Variadic options struct (idiomatic Go)
.NET SetModelAsync(model, reasoningEffort?, cancellationToken?) Two overloads for backward compatibility

Implementation Details ✓

  • All SDKs properly pass the parameter through to the underlying session.model.switchTo RPC
  • All use the same generated ReasoningEffort type/enum with values: low, medium, high, xhigh
  • All implementations are fully backward-compatible
  • Documentation and examples are consistent across all SDKs

Minor Suggestion: Test Coverage

The PR includes a test in Node.js (nodejs/test/client.test.ts) that verifies reasoningEffort is properly sent with the RPC call. Consider adding equivalent tests for the other three SDKs to ensure consistent test coverage:

  • python/test/test_client.py or similar
  • go/session_test.go or go/client_test.go
  • dotnet/test/GitHub.Copilot.SDK.Test/SessionTests.cs or similar

This would ensure the feature is equally well-tested across all implementations and help catch any regression in the future.


Summary: This PR maintains excellent cross-SDK consistency. The only recommendation is to add tests for Python, Go, and .NET matching the Node.js test coverage.

Generated by SDK Consistency Review Agent for issue #712 ·

@SteveSandersonMS
Copy link
Contributor

SteveSandersonMS commented Mar 10, 2026

@patniko I'm trying to work out how well this is going to fit for custom providers/BYOK. Relates to @IeuanWalker's point above too. Having a fixed set of values works for OpenAI/CAPI (though the set might expand over time, or maybe some newer models won't support all of these values), but not for custom providers.

Do you think we should redefine reasoning effort to accept arbitrary strings? That way provider-specific effort values can be accommodated, and we don't falsely imply that these specific reasoning effort values are always supported for all models.

We can also offer a set of consts for SDK consumers that define well-known OpenAI/CAPI values. If so I need to make a change in the underlying runtime which I've already started in the background, so please let me know what you think.

@patniko
Copy link
Contributor Author

patniko commented Mar 10, 2026

@SteveSandersonMS strings sound good for a longer term approach. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

session.setModel() missing ReasoningEffort value

4 participants