3131 PermissionRequestResult ,
3232 ResumeSessionConfig ,
3333 SessionConfig ,
34+ SystemMessageConfig ,
3435 ToolInvocation ,
3536 ToolResult ,
3637)
5758class GitHubCopilotOptions (TypedDict , total = False ):
5859 """GitHub Copilot-specific options."""
5960
60- instructions : str
61- """System message to append to the session."""
61+ system_message : SystemMessageConfig
62+ """System message configuration for the session. Use mode 'append' to add to the default
63+ system prompt, or 'replace' to completely override it."""
6264
6365 cli_path : str
6466 """Path to the Copilot CLI executable. Defaults to GITHUB_COPILOT_CLI_PATH environment variable
@@ -139,6 +141,7 @@ def get_weather(city: str) -> str:
139141
140142 def __init__ (
141143 self ,
144+ instructions : str | None = None ,
142145 * ,
143146 client : CopilotClient | None = None ,
144147 id : str | None = None ,
@@ -157,6 +160,9 @@ def __init__(
157160 ) -> None :
158161 """Initialize the GitHub Copilot Agent.
159162
163+ Args:
164+ instructions: System message for the agent.
165+
160166 Keyword Args:
161167 client: Optional pre-configured CopilotClient instance. If not provided,
162168 a new client will be created using the other parameters.
@@ -188,7 +194,10 @@ def __init__(
188194
189195 # Parse options
190196 opts : dict [str , Any ] = dict (default_options ) if default_options else {}
191- instructions = opts .pop ("instructions" , None )
197+
198+ # Handle instructions - direct parameter takes precedence over default_options.system_message
199+ self ._prepare_system_message (instructions , opts )
200+
192201 cli_path = opts .pop ("cli_path" , None )
193202 model = opts .pop ("model" , None )
194203 timeout = opts .pop ("timeout" , None )
@@ -208,7 +217,6 @@ def __init__(
208217 except ValidationError as ex :
209218 raise ServiceInitializationError ("Failed to create GitHub Copilot settings." , ex ) from ex
210219
211- self ._instructions = instructions
212220 self ._tools = normalize_tools (tools )
213221 self ._permission_handler = on_permission_request
214222 self ._mcp_servers = mcp_servers
@@ -302,7 +310,7 @@ async def run(
302310 opts : dict [str , Any ] = dict (options ) if options else {}
303311 timeout = opts .pop ("timeout" , None ) or self ._settings .timeout or DEFAULT_TIMEOUT_SECONDS
304312
305- session = await self ._get_or_create_session (thread , streaming = False )
313+ session = await self ._get_or_create_session (thread , streaming = False , runtime_options = opts )
306314 input_messages = normalize_messages (messages )
307315 prompt = "\n " .join ([message .text for message in input_messages ])
308316
@@ -365,7 +373,9 @@ async def run_stream(
365373 if not thread :
366374 thread = self .get_new_thread ()
367375
368- session = await self ._get_or_create_session (thread , streaming = True )
376+ opts : dict [str , Any ] = dict (options ) if options else {}
377+
378+ session = await self ._get_or_create_session (thread , streaming = True , runtime_options = opts )
369379 input_messages = normalize_messages (messages )
370380 prompt = "\n " .join ([message .text for message in input_messages ])
371381
@@ -400,6 +410,29 @@ def event_handler(event: SessionEvent) -> None:
400410 finally :
401411 unsubscribe ()
402412
413+ @staticmethod
414+ def _prepare_system_message (
415+ instructions : str | None ,
416+ opts : dict [str , Any ],
417+ ) -> None :
418+ """Prepare system message configuration in opts.
419+
420+ If instructions is provided, it takes precedence for content.
421+ If system_message is also provided, its mode is preserved.
422+ Modifies opts in place.
423+
424+ Args:
425+ instructions: Direct instructions parameter for content.
426+ opts: Options dictionary to modify.
427+ """
428+ opts_system_message = opts .pop ("system_message" , None )
429+ if instructions is not None :
430+ # Use instructions for content, but preserve mode from system_message if provided
431+ mode = opts_system_message .get ("mode" , "append" ) if opts_system_message else "append"
432+ opts ["system_message" ] = {"mode" : mode , "content" : instructions }
433+ elif opts_system_message is not None :
434+ opts ["system_message" ] = opts_system_message
435+
403436 def _prepare_tools (
404437 self ,
405438 tools : list [ToolProtocol | MutableMapping [str , Any ]],
@@ -459,12 +492,14 @@ async def _get_or_create_session(
459492 self ,
460493 thread : AgentThread ,
461494 streaming : bool = False ,
495+ runtime_options : dict [str , Any ] | None = None ,
462496 ) -> CopilotSession :
463497 """Get an existing session or create a new one for the thread.
464498
465499 Args:
466500 thread: The conversation thread.
467501 streaming: Whether to enable streaming for the session.
502+ runtime_options: Runtime options from run/run_stream that take precedence.
468503
469504 Returns:
470505 A CopilotSession instance.
@@ -479,33 +514,47 @@ async def _get_or_create_session(
479514 if thread .service_thread_id :
480515 return await self ._resume_session (thread .service_thread_id , streaming )
481516
482- session = await self ._create_session (streaming )
517+ session = await self ._create_session (streaming , runtime_options )
483518 thread .service_thread_id = session .session_id
484519 return session
485520 except Exception as ex :
486521 raise ServiceException (f"Failed to create GitHub Copilot session: { ex } " ) from ex
487522
488- async def _create_session (self , streaming : bool ) -> CopilotSession :
489- """Create a new Copilot session."""
523+ async def _create_session (
524+ self ,
525+ streaming : bool ,
526+ runtime_options : dict [str , Any ] | None = None ,
527+ ) -> CopilotSession :
528+ """Create a new Copilot session.
529+
530+ Args:
531+ streaming: Whether to enable streaming for the session.
532+ runtime_options: Runtime options that take precedence over default_options.
533+ """
490534 if not self ._client :
491535 raise ServiceException ("GitHub Copilot client not initialized. Call start() first." )
492536
537+ opts = runtime_options or {}
493538 config : SessionConfig = {"streaming" : streaming }
494539
495- if self ._settings .model :
496- config ["model" ] = self ._settings .model # type: ignore[typeddict-item]
540+ model = opts .get ("model" ) or self ._settings .model
541+ if model :
542+ config ["model" ] = model # type: ignore[typeddict-item]
497543
498- if self ._instructions :
499- config ["system_message" ] = {"mode" : "append" , "content" : self ._instructions }
544+ system_message = opts .get ("system_message" ) or self ._default_options .get ("system_message" )
545+ if system_message :
546+ config ["system_message" ] = system_message
500547
501548 if self ._tools :
502549 config ["tools" ] = self ._prepare_tools (self ._tools )
503550
504- if self ._permission_handler :
505- config ["on_permission_request" ] = self ._permission_handler
551+ permission_handler = opts .get ("on_permission_request" ) or self ._permission_handler
552+ if permission_handler :
553+ config ["on_permission_request" ] = permission_handler
506554
507- if self ._mcp_servers :
508- config ["mcp_servers" ] = self ._mcp_servers
555+ mcp_servers = opts .get ("mcp_servers" ) or self ._mcp_servers
556+ if mcp_servers :
557+ config ["mcp_servers" ] = mcp_servers
509558
510559 return await self ._client .create_session (config )
511560
0 commit comments