@@ -12,6 +12,7 @@ import (
1212 "github.com/yaoapp/yao/agent/i18n"
1313 "github.com/yaoapp/yao/agent/llm"
1414 "github.com/yaoapp/yao/agent/output/message"
15+ agentsandbox "github.com/yaoapp/yao/agent/sandbox"
1516)
1617
1718// Stream stream the agent
@@ -150,6 +151,33 @@ func (ast *Assistant) Stream(ctx *context.Context, inputMessages []context.Messa
150151 }
151152 ctx .Logger .PhaseComplete ("History" )
152153
154+ // ================================================
155+ // Initialize Sandbox (if configured)
156+ // ================================================
157+ // Sandbox must be created BEFORE hooks so that hooks can access ctx.sandbox
158+ var sandboxExecutor agentsandbox.Executor
159+ var sandboxCleanup func ()
160+ if ast .HasSandbox () {
161+ ctx .Logger .Phase ("Sandbox" )
162+ var err error
163+ sandboxExecutor , sandboxCleanup , err = ast .initSandbox (ctx , opts )
164+ if err != nil {
165+ ast .traceAgentFail (agentNode , err )
166+ ast .sendStreamEndOnError (ctx , streamHandler , streamStartTime , err )
167+ return nil , err
168+ }
169+ // Set sandbox executor in context so hooks can access ctx.sandbox
170+ // The executor implements both agentsandbox.Executor and context.SandboxExecutor
171+ ctx .SetSandboxExecutor (sandboxExecutor )
172+ ctx .Logger .PhaseComplete ("Sandbox" )
173+ }
174+ // Ensure sandbox cleanup on exit
175+ defer func () {
176+ if sandboxCleanup != nil {
177+ sandboxCleanup ()
178+ }
179+ }()
180+
153181 // ================================================
154182 // Execute Create Hook
155183 // ================================================
@@ -254,7 +282,14 @@ func (ast *Assistant) Stream(ctx *context.Context, inputMessages []context.Messa
254282 })
255283
256284 // Execute the LLM streaming call
257- completionResponse , err = ast .executeLLMStream (ctx , completionMessages , completionOptions , agentNode , streamHandler , opts )
285+ // Choose between sandbox execution or direct LLM execution
286+ if ast .HasSandbox () {
287+ // Sandbox execution path (Claude CLI, Cursor CLI, etc.)
288+ completionResponse , err = ast .executeSandboxStream (ctx , completionMessages , agentNode , streamHandler , sandboxExecutor )
289+ } else {
290+ // Direct LLM execution path
291+ completionResponse , err = ast .executeLLMStream (ctx , completionMessages , completionOptions , agentNode , streamHandler , opts )
292+ }
258293 if err != nil {
259294 finalStatus = context .ResumeStatusFailed
260295 finalError = err
@@ -282,8 +317,9 @@ func (ast *Assistant) Stream(ctx *context.Context, inputMessages []context.Messa
282317 // ================================================
283318 // Execute tool calls with retry
284319 // ================================================
320+ // Note: Skip MCP tool calls execution for sandbox mode - Claude CLI handles them internally
285321 var toolCallResponses []context.ToolCallResponse = nil
286- if completionResponse != nil && completionResponse .ToolCalls != nil {
322+ if completionResponse != nil && completionResponse .ToolCalls != nil && ! ast . HasSandbox () {
287323
288324 maxToolRetries := 3
289325 currentMessages := completionMessages
0 commit comments