1414from ..config .settings import cfg
1515from ..sandbox import SandboxExecutor , SandboxToolInterceptor
1616from ..services .otel import invoke_agent_span , set_span_attribute
17- from ..state .guardrails_config import GuardrailsConfigStore
17+ from ..state .guardrails import GuardrailsConfigStore
1818from ..state .mcp_config import McpConfigStore
1919from .event_handler import EventHandler
2020from .hitl import HitlInterceptor
@@ -352,26 +352,20 @@ async def list_models(self) -> list[dict]:
352352 logger .warning ("Failed to list models: %s" , exc )
353353 return []
354354
355- def _build_session_config (self ) -> dict [str , Any ]:
356- sandbox_active = self ._interceptor and self ._sandbox and self ._sandbox .enabled
357- # Always register the HITL hook when an interceptor exists so that
358- # guardrails config changes (enable/disable) take effect without
359- # requiring a session restart. The hook itself checks hitl_enabled
360- # at call time via resolve_action() which returns "allow" when off.
361- hitl_available = self ._hitl is not None
362-
363- logger .info (
364- "[agent.config] building session config: "
365- "sandbox_active=%s hitl_available=%s hitl_enabled=%s" ,
366- sandbox_active , hitl_available ,
367- self ._guardrails .hitl_enabled if self ._guardrails else "(no store)" ,
355+ def _build_hooks (self ) -> dict [str , Any ]:
356+ """Compose pre/post-tool-use hooks from active interceptors."""
357+ sandbox_active = (
358+ self ._interceptor and self ._sandbox and self ._sandbox .enabled
368359 )
360+ hitl_available = self ._hitl is not None
369361
370362 if sandbox_active and hitl_available :
371363 hitl = self ._hitl
372364 sandbox = self ._interceptor
373365
374- async def chained_pre_tool_use (input_data : dict , invocation : Any ) -> dict :
366+ async def chained_pre_tool_use (
367+ input_data : dict , invocation : Any ,
368+ ) -> dict :
375369 logger .info (
376370 "[agent.hook] chained_pre_tool_use called: tool=%s" ,
377371 input_data .get ("toolName" , "?" ),
@@ -380,7 +374,9 @@ async def chained_pre_tool_use(input_data: dict, invocation: Any) -> dict:
380374 if result .get ("permissionDecision" ) != "allow" :
381375 logger .info ("[agent.hook] hitl denied, skipping sandbox" )
382376 return result
383- logger .info ("[agent.hook] hitl allowed, proceeding to sandbox" )
377+ logger .info (
378+ "[agent.hook] hitl allowed, proceeding to sandbox" ,
379+ )
384380 return await sandbox .on_pre_tool_use (input_data , invocation )
385381
386382 hooks : dict [str , Any ] = {
@@ -399,30 +395,66 @@ async def chained_pre_tool_use(input_data: dict, invocation: Any) -> dict:
399395 logger .info ("[agent.config] hooks: sandbox only" )
400396 else :
401397 hooks = {"on_pre_tool_use" : auto_approve }
402- logger .info ("[agent.config] hooks: auto_approve (no hitl, no sandbox)" )
398+ logger .info (
399+ "[agent.config] hooks: auto_approve (no hitl, no sandbox)" ,
400+ )
401+
402+ return hooks
403+
404+ def _build_session_config (self ) -> dict [str , Any ]:
405+ """Assemble the full session configuration for the Copilot SDK."""
406+ sandbox_active = (
407+ self ._interceptor and self ._sandbox and self ._sandbox .enabled
408+ )
409+ logger .info (
410+ "[agent.config] building session config: "
411+ "sandbox_active=%s hitl_available=%s hitl_enabled=%s" ,
412+ sandbox_active , self ._hitl is not None ,
413+ self ._guardrails .hitl_enabled if self ._guardrails else "(no store)" ,
414+ )
403415
404416 session_cfg : dict [str , Any ] = {
405417 "model" : cfg .copilot_model ,
406418 "streaming" : True ,
407419 "tools" : get_all_tools (),
408- "system_message" : {"mode" : "replace" , "content" : build_system_prompt ()},
409- "hooks" : hooks ,
410- "skill_directories" : [str (cfg .builtin_skills_dir ), str (cfg .user_skills_dir )],
420+ "system_message" : {
421+ "mode" : "replace" ,
422+ "content" : build_system_prompt (),
423+ },
424+ "hooks" : self ._build_hooks (),
425+ "skill_directories" : [
426+ str (cfg .builtin_skills_dir ),
427+ str (cfg .user_skills_dir ),
428+ ],
411429 }
412430
413431 if sandbox_active :
414- session_cfg ["excluded_tools" ] = ["create" , "view" , "edit" , "grep" , "glob" ]
432+ session_cfg ["excluded_tools" ] = [
433+ "create" , "view" , "edit" , "grep" , "glob" ,
434+ ]
415435
416436 try :
417- session_cfg ["mcp_servers" ] = McpConfigStore ().get_enabled_servers ()
437+ session_cfg ["mcp_servers" ] = (
438+ McpConfigStore ().get_enabled_servers ()
439+ )
418440 except Exception :
419- logger .warning ("Failed to load MCP config, using defaults" , exc_info = True )
441+ logger .warning (
442+ "Failed to load MCP config, using defaults" ,
443+ exc_info = True ,
444+ )
420445 session_cfg ["mcp_servers" ] = {
421446 "playwright" : {
422447 "type" : "local" ,
423448 "command" : "npx" ,
424- "args" : ["-y" , "@playwright/mcp@latest" , "--browser" , "chromium" , "--headless" , "--isolated" ],
425- "env" : {"PLAYWRIGHT_CHROMIUM_ARGS" : "--no-sandbox --disable-setuid-sandbox" },
449+ "args" : [
450+ "-y" , "@playwright/mcp@latest" ,
451+ "--browser" , "chromium" ,
452+ "--headless" , "--isolated" ,
453+ ],
454+ "env" : {
455+ "PLAYWRIGHT_CHROMIUM_ARGS" :
456+ "--no-sandbox --disable-setuid-sandbox" ,
457+ },
426458 "tools" : ["*" ],
427459 },
428460 }
0 commit comments