Repository navigation
Conversation
Run every plain callable served through the OpenCode MCP tool bridge in a spawned child process via invoke_tool_callable, while emitting tool_call tracking in the parent from the tracked wrapper metadata. Add Sandbox and SandboxError to launchdarkly_ai_server for opt-in sandboxing on other handlers; wrap_tool_handlers keeps tracking in-process for Sandbox(fn). NativeTool entries are unchanged and never pass through the bridge. Co-authored-by: alexis <alexis@launchdarkly.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b77e721. Configure here.
| track() | ||
| result = await invoke_tool_callable(_sandbox_target(target), arguments) | ||
| else: | ||
| result = await invoke_tool_callable(fn, arguments) |
There was a problem hiding this comment.
Sandbox pickles trajectory wrapper closures
High Severity
_invoke sandboxes _ld_tool_target from the tracking wrapper. execute_and_track and execute_and_stream apply TrajectoryRecorder.wrap first, so that target is a nested closure and pickling fails. OpenCode Python tools then error with a picklable-callable message even when the author defined the function at module scope.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit b77e721. Configure here.
| except Exception as exc: | ||
| if isinstance(exc, SandboxError): | ||
| raise | ||
| raise SandboxError(str(exc)) from exc |
There was a problem hiding this comment.
Sandbox timeout leaves child running
Medium Severity
After future.result times out, the ProcessPoolExecutor context still shuts down with wait=True, so a hung child is never killed and the worker thread blocks. The outer asyncio.wait_for then raises TimeoutError while that process keeps running and occupies the default executor.
Reviewed by Cursor Bugbot for commit b77e721. Configure here.


Summary
Sandbox,SandboxError, andinvoke_tool_callabletolaunchdarkly_ai_serverfor spawned-process tool execution (picklable, module-scope callables only).tool_bridge._invoke) always runs plain Python tool callables in that sandbox.$ld:ai:tool_calltracking still fires in the parent via_ld_tool_track/_ld_tool_targetmetadata on tracked wrappers.wrap_tool_handlerstreatsSandbox(fn)as opt-in sandboxing on other handlers (track in parent, runfnin a child).Sandboxed
tool_handlers, notNativeTool).Explicitly not sandboxed
NativeToolentries (OpenCode built-ins and observability MCP tools wired asNativeTool("observability_*")) — OpenCode runs those insideopencode serve; this PR does not touch them.Sandbox(fn).Tests
packages/client/tests/test_tool_sandbox.py— spawn isolation + pickling errorspackages/opencode-agents/tests/test_tool_bridge.py— bridge MCPtools/callpathtest_tool_contract.py