diff --git a/letta/services/tool_executor/sandbox_tool_executor.py b/letta/services/tool_executor/sandbox_tool_executor.py index 500b3eb2..5946a018 100644 --- a/letta/services/tool_executor/sandbox_tool_executor.py +++ b/letta/services/tool_executor/sandbox_tool_executor.py @@ -56,7 +56,7 @@ class SandboxToolExecutor(ToolExecutor): # inject some extra env such as PROJECT_ID from agent_state if agent_state and agent_state.project_id: - fetched_credentials["PROJECT_ID"] = agent_state.project_id + fetched_credentials["PROJECT_ID"] = agent_state.project_id sandbox_env_vars = {**fetched_credentials, **sandbox_env_vars} @@ -83,15 +83,16 @@ class SandboxToolExecutor(ToolExecutor): function_name, function_args, actor, + tool_id=tool.id, + agent_id=agent_state.id if agent_state else None, + project_id=agent_state.project_id if agent_state else None, tool_object=tool, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars, organization_id=actor.organization_id, ) # TODO: pass through letta api key - tool_execution_result = await sandbox.run( - agent_id=agent_state.id, agent_state=agent_state_copy, additional_env_vars=sandbox_env_vars - ) + tool_execution_result = await sandbox.run(agent_state=agent_state_copy, additional_env_vars=sandbox_env_vars) except Exception as e: # Modal execution failed, log and fall back to E2B/LOCAL logger.warning(f"Modal execution failed for tool {tool.name}: {e}. Falling back to {tool_settings.sandbox_type.value}") @@ -106,6 +107,9 @@ class SandboxToolExecutor(ToolExecutor): function_name, function_args, actor, + tool_id=tool.id, + agent_id=agent_state.id if agent_state else None, + project_id=agent_state.project_id if agent_state else None, tool_object=tool, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars, @@ -115,6 +119,9 @@ class SandboxToolExecutor(ToolExecutor): function_name, function_args, actor, + tool_id=tool.id, + agent_id=agent_state.id if agent_state else None, + project_id=agent_state.project_id if agent_state else None, tool_object=tool, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars, diff --git a/letta/services/tool_sandbox/base.py b/letta/services/tool_sandbox/base.py index c12e5fa5..ab1da864 100644 --- a/letta/services/tool_sandbox/base.py +++ b/letta/services/tool_sandbox/base.py @@ -27,6 +27,9 @@ class AsyncToolSandboxBase(ABC): tool_name: str, args: JsonDict, user, + tool_id: str, + agent_id: Optional[str] = None, + project_id: Optional[str] = None, tool_object: Optional[Tool] = None, sandbox_config: Optional[SandboxConfig] = None, sandbox_env_vars: Optional[Dict[str, Any]] = None, @@ -34,6 +37,9 @@ class AsyncToolSandboxBase(ABC): self.tool_name = tool_name self.args = args self.user = user + self.agent_id = agent_id + self.project_id = project_id + self.tool_id = tool_id self.tool = tool_object # Store provided values or create manager to fetch them later @@ -394,6 +400,13 @@ class AsyncToolSandboxBase(ABC): if additional_env_vars: env.update(additional_env_vars) + # Inject agent, project, and tool IDs as environment variables + if self.agent_id: + env["LETTA_AGENT_ID"] = self.agent_id + if self.project_id: + env["LETTA_PROJECT_ID"] = self.project_id + env["LETTA_TOOL_ID"] = self.tool_id + # Filter out None values to prevent subprocess errors env = {k: v for k, v in env.items() if v is not None} diff --git a/letta/services/tool_sandbox/e2b_sandbox.py b/letta/services/tool_sandbox/e2b_sandbox.py index 1a11b60a..7744148f 100644 --- a/letta/services/tool_sandbox/e2b_sandbox.py +++ b/letta/services/tool_sandbox/e2b_sandbox.py @@ -31,12 +31,25 @@ class AsyncToolSandboxE2B(AsyncToolSandboxBase): tool_name: str, args: JsonDict, user, + tool_id: str, + agent_id: Optional[str] = None, + project_id: Optional[str] = None, force_recreate: bool = True, tool_object: Optional[Tool] = None, sandbox_config: Optional[SandboxConfig] = None, sandbox_env_vars: Optional[Dict[str, Any]] = None, ): - super().__init__(tool_name, args, user, tool_object, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars) + super().__init__( + tool_name, + args, + user, + tool_id=tool_id, + agent_id=agent_id, + project_id=project_id, + tool_object=tool_object, + sandbox_config=sandbox_config, + sandbox_env_vars=sandbox_env_vars, + ) self.force_recreate = force_recreate @trace_method diff --git a/letta/services/tool_sandbox/local_sandbox.py b/letta/services/tool_sandbox/local_sandbox.py index d31fb60f..3e88f052 100644 --- a/letta/services/tool_sandbox/local_sandbox.py +++ b/letta/services/tool_sandbox/local_sandbox.py @@ -37,12 +37,25 @@ class AsyncToolSandboxLocal(AsyncToolSandboxBase): tool_name: str, args: JsonDict, user, + tool_id: str, + agent_id: Optional[str] = None, + project_id: Optional[str] = None, force_recreate_venv=False, tool_object: Optional[Tool] = None, sandbox_config: Optional[SandboxConfig] = None, sandbox_env_vars: Optional[Dict[str, Any]] = None, ): - super().__init__(tool_name, args, user, tool_object, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars) + super().__init__( + tool_name, + args, + user, + tool_id=tool_id, + agent_id=agent_id, + project_id=project_id, + tool_object=tool_object, + sandbox_config=sandbox_config, + sandbox_env_vars=sandbox_env_vars, + ) self.force_recreate_venv = force_recreate_venv @trace_method diff --git a/letta/services/tool_sandbox/modal_sandbox.py b/letta/services/tool_sandbox/modal_sandbox.py index eaa94a77..d7f5e52d 100644 --- a/letta/services/tool_sandbox/modal_sandbox.py +++ b/letta/services/tool_sandbox/modal_sandbox.py @@ -36,18 +36,29 @@ class AsyncToolSandboxModal(AsyncToolSandboxBase): tool_name: str, args: JsonDict, user, + tool_id: str, + agent_id: Optional[str] = None, + project_id: Optional[str] = None, force_recreate: bool = True, tool_object: Optional[Tool] = None, sandbox_config: Optional[SandboxConfig] = None, sandbox_env_vars: Optional[Dict[str, Any]] = None, organization_id: Optional[str] = None, - project_id: str = "default", ): - super().__init__(tool_name, args, user, tool_object, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars) + super().__init__( + tool_name, + args, + user, + tool_id=tool_id, + agent_id=agent_id, + project_id=project_id, + tool_object=tool_object, + sandbox_config=sandbox_config, + sandbox_env_vars=sandbox_env_vars, + ) self.force_recreate = force_recreate # Get organization_id from user if not explicitly provided self.organization_id = organization_id if organization_id is not None else user.organization_id - self.project_id = project_id # TODO: check to make sure modal app `App(tool.id)` exists @@ -86,7 +97,6 @@ class AsyncToolSandboxModal(AsyncToolSandboxBase): @trace_method async def run( self, - agent_id: Optional[str] = None, agent_state: Optional[AgentState] = None, additional_env_vars: Optional[Dict] = None, ) -> ToolExecutionResult: @@ -149,7 +159,7 @@ class AsyncToolSandboxModal(AsyncToolSandboxBase): result = await func.remote.aio( tool_name=self.tool_name, agent_state=agent_state_dict, - agent_id=agent_id, + agent_id=self.agent_id, env_vars=env_vars, letta_api_key=letta_api_key, **self.args, diff --git a/letta/services/tool_sandbox/modal_sandbox_v2.py b/letta/services/tool_sandbox/modal_sandbox_v2.py index aca3f345..488df05f 100644 --- a/letta/services/tool_sandbox/modal_sandbox_v2.py +++ b/letta/services/tool_sandbox/modal_sandbox_v2.py @@ -37,6 +37,9 @@ class AsyncToolSandboxModalV2(AsyncToolSandboxBase): tool_name: str, args: JsonDict, user, + tool_id: str, + agent_id: str | None = None, + project_id: str | None = None, tool_object: Tool | None = None, sandbox_config: SandboxConfig | None = None, sandbox_env_vars: dict[str, Any] | None = None, @@ -51,6 +54,9 @@ class AsyncToolSandboxModalV2(AsyncToolSandboxBase): tool_name: Name of the tool to execute args: Arguments to pass to the tool user: User/actor for permissions + tool_id: Tool ID for the tool being executed + agent_id: Agent ID (optional) + project_id: Project ID for the tool execution (optional) tool_object: Tool object (optional) sandbox_config: Sandbox configuration (optional) sandbox_env_vars: Environment variables (optional) @@ -58,7 +64,17 @@ class AsyncToolSandboxModalV2(AsyncToolSandboxBase): use_locking: Whether to use locking for deployment coordination (default: True) use_version_tracking: Whether to track and reuse deployments (default: True) """ - super().__init__(tool_name, args, user, tool_object, sandbox_config=sandbox_config, sandbox_env_vars=sandbox_env_vars) + super().__init__( + tool_name, + args, + user, + tool_id=tool_id, + agent_id=agent_id, + project_id=project_id, + tool_object=tool_object, + sandbox_config=sandbox_config, + sandbox_env_vars=sandbox_env_vars, + ) if not tool_settings.modal_token_id or not tool_settings.modal_token_secret: raise ValueError("MODAL_TOKEN_ID and MODAL_TOKEN_SECRET must be set.") diff --git a/tests/integration_test_async_tool_sandbox.py b/tests/integration_test_async_tool_sandbox.py index 4aeeb03a..53a42308 100644 --- a/tests/integration_test_async_tool_sandbox.py +++ b/tests/integration_test_async_tool_sandbox.py @@ -559,12 +559,12 @@ async def test_local_sandbox_default(disable_e2b_api_key, add_integers_tool, tes # Mock and assert correct pathway was invoked with patch.object(AsyncToolSandboxLocal, "run") as mock_run: - sandbox = AsyncToolSandboxLocal(add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxLocal(add_integers_tool.name, args, user=test_user, tool_id=add_integers_tool.id) await sandbox.run() mock_run.assert_called_once() # Run again to get actual response - sandbox = AsyncToolSandboxLocal(add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxLocal(add_integers_tool.name, args, user=test_user, tool_id=add_integers_tool.id) result = await sandbox.run() assert result.func_return == args["x"] + args["y"] @@ -573,7 +573,7 @@ async def test_local_sandbox_default(disable_e2b_api_key, add_integers_tool, tes @pytest.mark.local_sandbox async def test_local_sandbox_stateful_tool(disable_e2b_api_key, clear_core_memory_tool, test_user, agent_state): args = {} - sandbox = AsyncToolSandboxLocal(clear_core_memory_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxLocal(clear_core_memory_tool.name, args, user=test_user, tool_id=clear_core_memory_tool.id) result = await sandbox.run(agent_state=agent_state) assert sandbox.inject_agent_state == True assert result.agent_state.memory.get_block("human").value == "" @@ -584,7 +584,7 @@ async def test_local_sandbox_stateful_tool(disable_e2b_api_key, clear_core_memor @pytest.mark.asyncio @pytest.mark.local_sandbox async def test_local_sandbox_with_list_rv(disable_e2b_api_key, list_tool, test_user): - sandbox = AsyncToolSandboxLocal(list_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(list_tool.name, {}, user=test_user, tool_id=list_tool.id) result = await sandbox.run() assert len(result.func_return) == 5 @@ -603,7 +603,7 @@ async def test_local_sandbox_env(disable_e2b_api_key, get_env_tool, test_user): SandboxEnvironmentVariableCreate(key=key, value=long_random_string), sandbox_config_id=config.id, actor=test_user ) - sandbox = AsyncToolSandboxLocal(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run() assert long_random_string in result.func_return @@ -625,7 +625,7 @@ async def test_local_sandbox_per_agent_env(disable_e2b_api_key, get_env_tool, ag correct_val = "".join(secrets.choice(string.ascii_letters + string.digits) for _ in range(20)) agent_state.secrets = [AgentEnvironmentVariable(key=key, value=correct_val, agent_id=agent_state.id)] - sandbox = AsyncToolSandboxLocal(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run(agent_state=agent_state) assert wrong_val not in result.func_return assert correct_val in result.func_return @@ -637,7 +637,7 @@ async def test_local_sandbox_external_codebase_with_venv( disable_e2b_api_key, custom_test_sandbox_config, external_codebase_tool, test_user ): args = {"percentage": 10} - sandbox = AsyncToolSandboxLocal(external_codebase_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxLocal(external_codebase_tool.name, args, user=test_user, tool_id=external_codebase_tool.id) result = await sandbox.run() assert result.func_return == "Price Adjustments:\nBurger: $8.99 -> $9.89\nFries: $2.99 -> $3.29\nSoda: $1.99 -> $2.19" assert "Hello World" in result.stdout[0] @@ -648,7 +648,7 @@ async def test_local_sandbox_external_codebase_with_venv( async def test_local_sandbox_with_venv_and_warnings_does_not_error( disable_e2b_api_key, custom_test_sandbox_config, get_warning_tool, test_user ): - sandbox = AsyncToolSandboxLocal(get_warning_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(get_warning_tool.name, {}, user=test_user, tool_id=get_warning_tool.id) result = await sandbox.run() assert result.func_return == "Hello World" @@ -656,7 +656,7 @@ async def test_local_sandbox_with_venv_and_warnings_does_not_error( @pytest.mark.asyncio @pytest.mark.e2b_sandbox async def test_local_sandbox_with_venv_errors(disable_e2b_api_key, custom_test_sandbox_config, always_err_tool, test_user): - sandbox = AsyncToolSandboxLocal(always_err_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(always_err_tool.name, {}, user=test_user, tool_id=always_err_tool.id) result = await sandbox.run() assert len(result.stdout) != 0 assert "error" in result.stdout[0] @@ -679,7 +679,7 @@ async def test_local_sandbox_with_venv_pip_installs_basic(disable_e2b_api_key, c SandboxEnvironmentVariableCreate(key=key, value=long_random_string), sandbox_config_id=config.id, actor=test_user ) - sandbox = AsyncToolSandboxLocal(cowsay_tool.name, {}, user=test_user, force_recreate_venv=True) + sandbox = AsyncToolSandboxLocal(cowsay_tool.name, {}, user=test_user, tool_id=cowsay_tool.id, force_recreate_venv=True) result = await sandbox.run() assert long_random_string in result.stdout[0] @@ -694,7 +694,12 @@ async def test_local_sandbox_with_tool_pip_requirements(disable_e2b_api_key, too await manager.create_or_update_sandbox_config_async(config_create, test_user) sandbox = AsyncToolSandboxLocal( - tool_with_pip_requirements.name, {}, user=test_user, tool_object=tool_with_pip_requirements, force_recreate_venv=True + tool_with_pip_requirements.name, + {}, + user=test_user, + tool_id=tool_with_pip_requirements.id, + tool_object=tool_with_pip_requirements, + force_recreate_venv=True, ) result = await sandbox.run() @@ -718,7 +723,12 @@ async def test_local_sandbox_with_mixed_pip_requirements(disable_e2b_api_key, to await manager.create_or_update_sandbox_config_async(config_create, test_user) sandbox = AsyncToolSandboxLocal( - tool_with_pip_requirements.name, {}, user=test_user, tool_object=tool_with_pip_requirements, force_recreate_venv=True + tool_with_pip_requirements.name, + {}, + user=test_user, + tool_id=tool_with_pip_requirements.id, + tool_object=tool_with_pip_requirements, + force_recreate_venv=True, ) result = await sandbox.run() @@ -741,7 +751,7 @@ async def test_local_sandbox_with_venv_pip_installs_with_update(disable_e2b_api_ SandboxEnvironmentVariableCreate(key=key, value=long_random_string), sandbox_config_id=config.id, actor=test_user ) - sandbox = AsyncToolSandboxLocal(cowsay_tool.name, {}, user=test_user, force_recreate_venv=True) + sandbox = AsyncToolSandboxLocal(cowsay_tool.name, {}, user=test_user, tool_id=cowsay_tool.id, force_recreate_venv=True) result = await sandbox.run() assert len(result.stdout) == 0 assert "No module named 'cowsay'" in result.stderr[0] @@ -751,7 +761,7 @@ async def test_local_sandbox_with_venv_pip_installs_with_update(disable_e2b_api_ ) await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxLocal(cowsay_tool.name, {}, user=test_user, force_recreate_venv=False) + sandbox = AsyncToolSandboxLocal(cowsay_tool.name, {}, user=test_user, tool_id=cowsay_tool.id, force_recreate_venv=False) result = await sandbox.run() assert long_random_string in result.stdout[0] @@ -766,12 +776,12 @@ async def test_e2b_sandbox_default(check_e2b_key_is_set, add_integers_tool, test # Mock and assert correct pathway was invoked with patch.object(AsyncToolSandboxE2B, "run") as mock_run: - sandbox = AsyncToolSandboxE2B(add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxE2B(add_integers_tool.name, args, user=test_user, tool_id=add_integers_tool.id) await sandbox.run() mock_run.assert_called_once() # Run again to get actual response - sandbox = AsyncToolSandboxE2B(add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxE2B(add_integers_tool.name, args, user=test_user, tool_id=add_integers_tool.id) result = await sandbox.run() assert int(result.func_return) == args["x"] + args["y"] @@ -791,7 +801,7 @@ async def test_e2b_sandbox_pip_installs(check_e2b_key_is_set, cowsay_tool, test_ actor=test_user, ) - sandbox = AsyncToolSandboxE2B(cowsay_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(cowsay_tool.name, {}, user=test_user, tool_id=cowsay_tool.id) result = await sandbox.run() assert long_random_string in result.stdout[0] @@ -799,7 +809,7 @@ async def test_e2b_sandbox_pip_installs(check_e2b_key_is_set, cowsay_tool, test_ @pytest.mark.asyncio @pytest.mark.e2b_sandbox async def test_e2b_sandbox_stateful_tool(check_e2b_key_is_set, clear_core_memory_tool, test_user, agent_state): - sandbox = AsyncToolSandboxE2B(clear_core_memory_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(clear_core_memory_tool.name, {}, user=test_user, tool_id=clear_core_memory_tool.id) result = await sandbox.run(agent_state=agent_state) assert result.agent_state.memory.get_block("human").value == "" assert result.agent_state.memory.get_block("persona").value == "" @@ -813,7 +823,7 @@ async def test_e2b_sandbox_inject_env_var_existing_sandbox(check_e2b_key_is_set, config_create = SandboxConfigCreate(config=E2BSandboxConfig().model_dump()) config = await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxE2B(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run() assert result.func_return is None @@ -825,7 +835,7 @@ async def test_e2b_sandbox_inject_env_var_existing_sandbox(check_e2b_key_is_set, actor=test_user, ) - sandbox = AsyncToolSandboxE2B(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run() assert long_random_string in result.func_return @@ -848,7 +858,7 @@ async def test_e2b_sandbox_per_agent_env(check_e2b_key_is_set, get_env_tool, age agent_state.secrets = [AgentEnvironmentVariable(key=key, value=correct_val, agent_id=agent_state.id)] - sandbox = AsyncToolSandboxE2B(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run(agent_state=agent_state) assert wrong_val not in result.func_return assert correct_val in result.func_return @@ -857,7 +867,7 @@ async def test_e2b_sandbox_per_agent_env(check_e2b_key_is_set, get_env_tool, age @pytest.mark.asyncio @pytest.mark.e2b_sandbox async def test_e2b_sandbox_with_list_rv(check_e2b_key_is_set, list_tool, test_user): - sandbox = AsyncToolSandboxE2B(list_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(list_tool.name, {}, user=test_user, tool_id=list_tool.id) result = await sandbox.run() assert len(result.func_return) == 5 @@ -870,7 +880,9 @@ async def test_e2b_sandbox_with_tool_pip_requirements(check_e2b_key_is_set, tool config_create = SandboxConfigCreate(config=E2BSandboxConfig().model_dump()) await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxE2B(tool_with_pip_requirements.name, {}, user=test_user, tool_object=tool_with_pip_requirements) + sandbox = AsyncToolSandboxE2B( + tool_with_pip_requirements.name, {}, user=test_user, tool_id=tool_with_pip_requirements.id, tool_object=tool_with_pip_requirements + ) result = await sandbox.run() # Should succeed since tool pip requirements were installed @@ -889,7 +901,9 @@ async def test_e2b_sandbox_with_mixed_pip_requirements(check_e2b_key_is_set, too config_create = SandboxConfigCreate(config=E2BSandboxConfig(pip_requirements=["cowsay"]).model_dump()) await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxE2B(tool_with_pip_requirements.name, {}, user=test_user, tool_object=tool_with_pip_requirements) + sandbox = AsyncToolSandboxE2B( + tool_with_pip_requirements.name, {}, user=test_user, tool_id=tool_with_pip_requirements.id, tool_object=tool_with_pip_requirements + ) result = await sandbox.run() # Should succeed since both sandbox and tool pip requirements were installed @@ -908,7 +922,13 @@ async def test_e2b_sandbox_with_broken_tool_pip_requirements_error_handling( config_create = SandboxConfigCreate(config=E2BSandboxConfig().model_dump()) await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxE2B(tool_with_broken_pip_requirements.name, {}, user=test_user, tool_object=tool_with_broken_pip_requirements) + sandbox = AsyncToolSandboxE2B( + tool_with_broken_pip_requirements.name, + {}, + user=test_user, + tool_id=tool_with_broken_pip_requirements.id, + tool_object=tool_with_broken_pip_requirements, + ) # Should raise a RuntimeError with informative message with pytest.raises(RuntimeError) as exc_info: @@ -935,12 +955,14 @@ async def test_e2b_sandbox_with_broken_tool_pip_requirements_error_handling( async def test_async_function_detection(add_integers_tool, async_add_integers_tool, test_user): """Test that async function detection works correctly""" # Test sync function detection - sync_sandbox = AsyncToolSandboxE2B(add_integers_tool.name, {}, test_user, tool_object=add_integers_tool) + sync_sandbox = AsyncToolSandboxE2B(add_integers_tool.name, {}, test_user, tool_id=add_integers_tool.id, tool_object=add_integers_tool) await sync_sandbox._init_async() assert not sync_sandbox.is_async_function # Test async function detection - async_sandbox = AsyncToolSandboxE2B(async_add_integers_tool.name, {}, test_user, tool_object=async_add_integers_tool) + async_sandbox = AsyncToolSandboxE2B( + async_add_integers_tool.name, {}, test_user, tool_id=async_add_integers_tool.id, tool_object=async_add_integers_tool + ) await async_sandbox._init_async() assert async_sandbox.is_async_function @@ -949,7 +971,7 @@ async def test_async_function_detection(add_integers_tool, async_add_integers_to async def test_async_template_selection(add_integers_tool, async_add_integers_tool, test_user): """Test that correct templates are selected for sync vs async functions""" # Test sync function uses regular template - sync_sandbox = AsyncToolSandboxE2B(add_integers_tool.name, {}, test_user, tool_object=add_integers_tool) + sync_sandbox = AsyncToolSandboxE2B(add_integers_tool.name, {}, test_user, tool_id=add_integers_tool.id, tool_object=add_integers_tool) sync_script = await sync_sandbox.generate_execution_script(agent_state=None) print("=== SYNC SCRIPT ===") print(sync_script) @@ -958,7 +980,9 @@ async def test_async_template_selection(add_integers_tool, async_add_integers_to assert "asyncio.run" not in sync_script # Test async function uses async template - async_sandbox = AsyncToolSandboxE2B(async_add_integers_tool.name, {}, test_user, tool_object=async_add_integers_tool) + async_sandbox = AsyncToolSandboxE2B( + async_add_integers_tool.name, {}, test_user, tool_id=async_add_integers_tool.id, tool_object=async_add_integers_tool + ) async_script = await async_sandbox.generate_execution_script(agent_state=None) print("=== ASYNC SCRIPT ===") print(async_script) @@ -974,7 +998,7 @@ async def test_local_sandbox_async_function_execution(disable_e2b_api_key, async """Test that async functions execute correctly in local sandbox""" args = {"x": 15, "y": 25} - sandbox = AsyncToolSandboxLocal(async_add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxLocal(async_add_integers_tool.name, args, user=test_user, tool_id=async_add_integers_tool.id) result = await sandbox.run() assert result.func_return == args["x"] + args["y"] @@ -985,7 +1009,7 @@ async def test_e2b_sandbox_async_function_execution(check_e2b_key_is_set, async_ """Test that async functions execute correctly in E2B sandbox""" args = {"x": 20, "y": 30} - sandbox = AsyncToolSandboxE2B(async_add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxE2B(async_add_integers_tool.name, args, user=test_user, tool_id=async_add_integers_tool.id) result = await sandbox.run() assert int(result.func_return) == args["x"] + args["y"] @@ -996,7 +1020,7 @@ async def test_local_sandbox_async_complex_computation(disable_e2b_api_key, asyn """Test complex async computation with multiple awaits in local sandbox""" args = {"iterations": 2} - sandbox = AsyncToolSandboxLocal(async_complex_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxLocal(async_complex_tool.name, args, user=test_user, tool_id=async_complex_tool.id) result = await sandbox.run() assert isinstance(result.func_return, dict) @@ -1012,7 +1036,7 @@ async def test_e2b_sandbox_async_complex_computation(check_e2b_key_is_set, async """Test complex async computation with multiple awaits in E2B sandbox""" args = {"iterations": 2} - sandbox = AsyncToolSandboxE2B(async_complex_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxE2B(async_complex_tool.name, args, user=test_user, tool_id=async_complex_tool.id) result = await sandbox.run() func_return = result.func_return @@ -1027,7 +1051,7 @@ async def test_e2b_sandbox_async_complex_computation(check_e2b_key_is_set, async @pytest.mark.local_sandbox async def test_local_sandbox_async_list_return(disable_e2b_api_key, async_list_tool, test_user): """Test async function returning list in local sandbox""" - sandbox = AsyncToolSandboxLocal(async_list_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(async_list_tool.name, {}, user=test_user, tool_id=async_list_tool.id) result = await sandbox.run() assert result.func_return == [1, 2, 3, 4, 5] @@ -1036,7 +1060,7 @@ async def test_local_sandbox_async_list_return(disable_e2b_api_key, async_list_t @pytest.mark.e2b_sandbox async def test_e2b_sandbox_async_list_return(check_e2b_key_is_set, async_list_tool, test_user): """Test async function returning list in E2B sandbox""" - sandbox = AsyncToolSandboxE2B(async_list_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(async_list_tool.name, {}, user=test_user, tool_id=async_list_tool.id) result = await sandbox.run() assert result.func_return == [1, 2, 3, 4, 5] @@ -1059,7 +1083,7 @@ async def test_local_sandbox_async_with_env_vars(disable_e2b_api_key, async_get_ SandboxEnvironmentVariableCreate(key=key, value=test_value), sandbox_config_id=config.id, actor=test_user ) - sandbox = AsyncToolSandboxLocal(async_get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(async_get_env_tool.name, {}, user=test_user, tool_id=async_get_env_tool.id) result = await sandbox.run() assert test_value in result.func_return @@ -1080,7 +1104,7 @@ async def test_e2b_sandbox_async_with_env_vars(check_e2b_key_is_set, async_get_e SandboxEnvironmentVariableCreate(key=key, value=test_value), sandbox_config_id=config.id, actor=test_user ) - sandbox = AsyncToolSandboxE2B(async_get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(async_get_env_tool.name, {}, user=test_user, tool_id=async_get_env_tool.id) result = await sandbox.run() assert test_value in result.func_return @@ -1090,7 +1114,7 @@ async def test_e2b_sandbox_async_with_env_vars(check_e2b_key_is_set, async_get_e @pytest.mark.local_sandbox async def test_local_sandbox_async_with_agent_state(disable_e2b_api_key, async_stateful_tool, test_user, agent_state): """Test async function with agent state in local sandbox""" - sandbox = AsyncToolSandboxLocal(async_stateful_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(async_stateful_tool.name, {}, user=test_user, tool_id=async_stateful_tool.id) result = await sandbox.run(agent_state=agent_state) assert result.agent_state is not None @@ -1103,7 +1127,7 @@ async def test_local_sandbox_async_with_agent_state(disable_e2b_api_key, async_s @pytest.mark.e2b_sandbox async def test_e2b_sandbox_async_with_agent_state(check_e2b_key_is_set, async_stateful_tool, test_user, agent_state): """Test async function with agent state in E2B sandbox""" - sandbox = AsyncToolSandboxE2B(async_stateful_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(async_stateful_tool.name, {}, user=test_user, tool_id=async_stateful_tool.id) result = await sandbox.run(agent_state=agent_state) assert result.agent_state.memory.get_block("human").value == "" @@ -1115,7 +1139,7 @@ async def test_e2b_sandbox_async_with_agent_state(check_e2b_key_is_set, async_st @pytest.mark.local_sandbox async def test_local_sandbox_async_error_handling(disable_e2b_api_key, async_error_tool, test_user): """Test async function error handling in local sandbox""" - sandbox = AsyncToolSandboxLocal(async_error_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(async_error_tool.name, {}, user=test_user, tool_id=async_error_tool.id) result = await sandbox.run() # Check that error was captured @@ -1129,7 +1153,7 @@ async def test_local_sandbox_async_error_handling(disable_e2b_api_key, async_err @pytest.mark.e2b_sandbox async def test_e2b_sandbox_async_error_handling(check_e2b_key_is_set, async_error_tool, test_user): """Test async function error handling in E2B sandbox""" - sandbox = AsyncToolSandboxE2B(async_error_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(async_error_tool.name, {}, user=test_user, tool_id=async_error_tool.id) result = await sandbox.run() # Check that error was captured @@ -1157,7 +1181,7 @@ async def test_local_sandbox_async_per_agent_env(disable_e2b_api_key, async_get_ correct_val = "correct_async_local_value" agent_state.secrets = [AgentEnvironmentVariable(key=key, value=correct_val, agent_id=agent_state.id)] - sandbox = AsyncToolSandboxLocal(async_get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxLocal(async_get_env_tool.name, {}, user=test_user, tool_id=async_get_env_tool.id) result = await sandbox.run(agent_state=agent_state) assert wrong_val not in result.func_return assert correct_val in result.func_return @@ -1182,7 +1206,7 @@ async def test_e2b_sandbox_async_per_agent_env(check_e2b_key_is_set, async_get_e agent_state.secrets = [AgentEnvironmentVariable(key=key, value=correct_val, agent_id=agent_state.id)] - sandbox = AsyncToolSandboxE2B(async_get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxE2B(async_get_env_tool.name, {}, user=test_user, tool_id=async_get_env_tool.id) result = await sandbox.run(agent_state=agent_state) assert wrong_val not in result.func_return assert correct_val in result.func_return @@ -1265,6 +1289,7 @@ async def test_local_sandbox_with_client_injection(disable_e2b_api_key, list_too tool_name=list_tools_with_client_tool.name, args={}, user=test_user, + tool_id=list_tools_with_client_tool.id, tool_object=list_tools_with_client_tool, sandbox_env_vars=sandbox_env_vars, ) @@ -1323,6 +1348,7 @@ async def test_e2b_sandbox_with_client_injection(check_e2b_key_is_set, list_tool tool_name=list_tools_with_client_tool.name, args={}, user=test_user, + tool_id=list_tools_with_client_tool.id, tool_object=list_tools_with_client_tool, sandbox_env_vars=sandbox_env_vars, ) diff --git a/tests/integration_test_modal.py b/tests/integration_test_modal.py index fab27b92..304d9885 100644 --- a/tests/integration_test_modal.py +++ b/tests/integration_test_modal.py @@ -485,12 +485,12 @@ async def test_modal_sandbox_default(check_modal_key_is_set, add_integers_tool, # Mock and assert correct pathway was invoked with patch.object(AsyncToolSandboxModal, "run") as mock_run: - sandbox = AsyncToolSandboxModal(add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxModal(add_integers_tool.name, args, user=test_user, tool_id=add_integers_tool.id) await sandbox.run() mock_run.assert_called_once() # Run again to get actual response - sandbox = AsyncToolSandboxModal(add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxModal(add_integers_tool.name, args, user=test_user, tool_id=add_integers_tool.id) result = await sandbox.run() assert int(result.func_return) == args["x"] + args["y"] @@ -511,7 +511,7 @@ async def test_modal_sandbox_pip_installs(check_modal_key_is_set, cowsay_tool, t actor=test_user, ) - sandbox = AsyncToolSandboxModal(cowsay_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(cowsay_tool.name, {}, user=test_user, tool_id=cowsay_tool.id) result = await sandbox.run() assert long_random_string in result.stdout[0] @@ -519,7 +519,7 @@ async def test_modal_sandbox_pip_installs(check_modal_key_is_set, cowsay_tool, t @pytest.mark.asyncio @pytest.mark.modal_sandbox async def test_modal_sandbox_stateful_tool(check_modal_key_is_set, clear_core_memory_tool, test_user, agent_state): - sandbox = AsyncToolSandboxModal(clear_core_memory_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(clear_core_memory_tool.name, {}, user=test_user, tool_id=clear_core_memory_tool.id) result = await sandbox.run(agent_state=agent_state) assert result.agent_state.memory.get_block("human").value == "" assert result.agent_state.memory.get_block("persona").value == "" @@ -533,7 +533,7 @@ async def test_modal_sandbox_inject_env_var_existing_sandbox(check_modal_key_is_ config_create = SandboxConfigCreate(config=ModalSandboxConfig().model_dump()) config = await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxModal(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run() assert result.func_return is None @@ -545,7 +545,7 @@ async def test_modal_sandbox_inject_env_var_existing_sandbox(check_modal_key_is_ actor=test_user, ) - sandbox = AsyncToolSandboxModal(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run() assert long_random_string in result.func_return @@ -568,7 +568,7 @@ async def test_modal_sandbox_per_agent_env(check_modal_key_is_set, get_env_tool, agent_state.secrets = [AgentEnvironmentVariable(key=key, value=correct_val, agent_id=agent_state.id)] - sandbox = AsyncToolSandboxModal(get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(get_env_tool.name, {}, user=test_user, tool_id=get_env_tool.id) result = await sandbox.run(agent_state=agent_state) assert wrong_val not in result.func_return assert correct_val in result.func_return @@ -577,7 +577,7 @@ async def test_modal_sandbox_per_agent_env(check_modal_key_is_set, get_env_tool, @pytest.mark.asyncio @pytest.mark.modal_sandbox async def test_modal_sandbox_with_list_rv(check_modal_key_is_set, list_tool, test_user): - sandbox = AsyncToolSandboxModal(list_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(list_tool.name, {}, user=test_user, tool_id=list_tool.id) result = await sandbox.run() assert len(result.func_return) == 5 @@ -590,7 +590,9 @@ async def test_modal_sandbox_with_tool_pip_requirements(check_modal_key_is_set, config_create = SandboxConfigCreate(config=ModalSandboxConfig().model_dump()) await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxModal(tool_with_pip_requirements.name, {}, user=test_user, tool_object=tool_with_pip_requirements) + sandbox = AsyncToolSandboxModal( + tool_with_pip_requirements.name, {}, user=test_user, tool_id=tool_with_pip_requirements.id, tool_object=tool_with_pip_requirements + ) result = await sandbox.run() # Should succeed since tool pip requirements were installed @@ -611,7 +613,9 @@ async def test_modal_sandbox_with_mixed_pip_requirements(check_modal_key_is_set, config_create = SandboxConfigCreate(config=ModalSandboxConfig().model_dump()) await manager.create_or_update_sandbox_config_async(config_create, test_user) - sandbox = AsyncToolSandboxModal(tool_with_pip_requirements.name, {}, user=test_user, tool_object=tool_with_pip_requirements) + sandbox = AsyncToolSandboxModal( + tool_with_pip_requirements.name, {}, user=test_user, tool_id=tool_with_pip_requirements.id, tool_object=tool_with_pip_requirements + ) result = await sandbox.run() # Should succeed since tool pip requirements were installed @@ -651,12 +655,14 @@ async def test_modal_sandbox_with_broken_tool_pip_requirements_error_handling(ch async def test_async_function_detection(add_integers_tool, async_add_integers_tool, test_user): """Test that async function detection works correctly""" # Test sync function detection - sync_sandbox = AsyncToolSandboxModal(add_integers_tool.name, {}, test_user, tool_object=add_integers_tool) + sync_sandbox = AsyncToolSandboxModal(add_integers_tool.name, {}, test_user, tool_id=add_integers_tool.id, tool_object=add_integers_tool) await sync_sandbox._init_async() assert not sync_sandbox.is_async_function # Test async function detection - async_sandbox = AsyncToolSandboxModal(async_add_integers_tool.name, {}, test_user, tool_object=async_add_integers_tool) + async_sandbox = AsyncToolSandboxModal( + async_add_integers_tool.name, {}, test_user, tool_id=async_add_integers_tool.id, tool_object=async_add_integers_tool + ) await async_sandbox._init_async() assert async_sandbox.is_async_function @@ -667,7 +673,7 @@ async def test_modal_sandbox_async_function_execution(check_modal_key_is_set, as """Test that async functions execute correctly in Modal sandbox""" args = {"x": 20, "y": 30} - sandbox = AsyncToolSandboxModal(async_add_integers_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxModal(async_add_integers_tool.name, args, user=test_user, tool_id=async_add_integers_tool.id) result = await sandbox.run() assert int(result.func_return) == args["x"] + args["y"] @@ -678,7 +684,7 @@ async def test_modal_sandbox_async_complex_computation(check_modal_key_is_set, a """Test complex async computation with multiple awaits in Modal sandbox""" args = {"iterations": 2} - sandbox = AsyncToolSandboxModal(async_complex_tool.name, args, user=test_user) + sandbox = AsyncToolSandboxModal(async_complex_tool.name, args, user=test_user, tool_id=async_complex_tool.id) result = await sandbox.run() func_return = result.func_return @@ -693,7 +699,7 @@ async def test_modal_sandbox_async_complex_computation(check_modal_key_is_set, a @pytest.mark.modal_sandbox async def test_modal_sandbox_async_list_return(check_modal_key_is_set, async_list_tool, test_user): """Test async function returning list in Modal sandbox""" - sandbox = AsyncToolSandboxModal(async_list_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(async_list_tool.name, {}, user=test_user, tool_id=async_list_tool.id) result = await sandbox.run() assert result.func_return == [1, 2, 3, 4, 5] @@ -713,7 +719,7 @@ async def test_modal_sandbox_async_with_env_vars(check_modal_key_is_set, async_g SandboxEnvironmentVariableCreate(key=key, value=test_value), sandbox_config_id=config.id, actor=test_user ) - sandbox = AsyncToolSandboxModal(async_get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(async_get_env_tool.name, {}, user=test_user, tool_id=async_get_env_tool.id) result = await sandbox.run() assert test_value in result.func_return @@ -723,7 +729,7 @@ async def test_modal_sandbox_async_with_env_vars(check_modal_key_is_set, async_g @pytest.mark.modal_sandbox async def test_modal_sandbox_async_with_agent_state(check_modal_key_is_set, async_stateful_tool, test_user, agent_state): """Test async function with agent state in Modal sandbox""" - sandbox = AsyncToolSandboxModal(async_stateful_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(async_stateful_tool.name, {}, user=test_user, tool_id=async_stateful_tool.id) result = await sandbox.run(agent_state=agent_state) assert result.agent_state.memory.get_block("human").value == "" @@ -735,7 +741,7 @@ async def test_modal_sandbox_async_with_agent_state(check_modal_key_is_set, asyn @pytest.mark.modal_sandbox async def test_modal_sandbox_async_error_handling(check_modal_key_is_set, async_error_tool, test_user): """Test async function error handling in Modal sandbox""" - sandbox = AsyncToolSandboxModal(async_error_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(async_error_tool.name, {}, user=test_user, tool_id=async_error_tool.id) result = await sandbox.run() # Check that error was captured @@ -764,7 +770,7 @@ async def test_modal_sandbox_async_per_agent_env(check_modal_key_is_set, async_g agent_state.secrets = [AgentEnvironmentVariable(key=key, value=correct_val, agent_id=agent_state.id)] - sandbox = AsyncToolSandboxModal(async_get_env_tool.name, {}, user=test_user) + sandbox = AsyncToolSandboxModal(async_get_env_tool.name, {}, user=test_user, tool_id=async_get_env_tool.id) result = await sandbox.run(agent_state=agent_state) assert wrong_val not in result.func_return assert correct_val in result.func_return diff --git a/tests/integration_test_modal_sandbox_v2.py b/tests/integration_test_modal_sandbox_v2.py index a2859862..f7fdae1d 100644 --- a/tests/integration_test_modal_sandbox_v2.py +++ b/tests/integration_test_modal_sandbox_v2.py @@ -269,6 +269,7 @@ class TestModalV2BasicExecution: tool_name="calculate", args={"operation": "add", "a": 5, "b": 3}, user=test_user, + tool_id=basic_tool.id, tool_object=basic_tool, ) @@ -281,6 +282,7 @@ class TestModalV2BasicExecution: tool_name="calculate", args={"operation": "divide", "a": 10, "b": 2}, user=test_user, + tool_id=basic_tool.id, tool_object=basic_tool, ) @@ -296,6 +298,7 @@ class TestModalV2BasicExecution: tool_name="calculate", args={"operation": "divide", "a": 10, "b": 0}, user=test_user, + tool_id=basic_tool.id, tool_object=basic_tool, ) @@ -308,6 +311,7 @@ class TestModalV2BasicExecution: tool_name="calculate", args={"operation": "unknown", "a": 1, "b": 2}, user=test_user, + tool_id=basic_tool.id, tool_object=basic_tool, ) @@ -322,6 +326,7 @@ class TestModalV2BasicExecution: tool_name="fetch_data", args={"url": "https://example.com", "delay": 0.01}, user=test_user, + tool_id=async_tool.id, tool_object=async_tool, ) @@ -344,6 +349,7 @@ class TestModalV2BasicExecution: tool_name="calculate", args={"operation": "add", "a": i, "b": i + 1}, user=test_user, + tool_id=basic_tool.id, tool_object=basic_tool, ) for i in range(5) @@ -594,6 +600,7 @@ class TestModalV2Persistence: tool_name="calculate", args={"operation": "add", "a": 1, "b": 1}, user=mock_user, + tool_id=basic_tool.id, tool_object=basic_tool, sandbox_config=config1, ) @@ -602,6 +609,7 @@ class TestModalV2Persistence: tool_name="calculate", args={"operation": "add", "a": 2, "b": 2}, user=mock_user, + tool_id=basic_tool.id, tool_object=basic_tool, sandbox_config=config2, ) @@ -696,6 +704,7 @@ def calculate(operation: str, a: float, b: float) -> float: tool_name="integration_test", args={"operation": "add", "a": 5, "b": 3}, user=mock_user, + tool_id=tool.id, tool_object=tool, sandbox_config=sandbox_config, ) @@ -791,6 +800,7 @@ class TestModalV2DeploymentStats: tool_name=tool.name, args={}, user=test_user, + tool_id=tool.id, tool_object=tool, ) await sandbox.run() diff --git a/tests/integration_test_tool_execution_sandbox.py b/tests/integration_test_tool_execution_sandbox.py index fd1f989b..14ff486d 100644 --- a/tests/integration_test_tool_execution_sandbox.py +++ b/tests/integration_test_tool_execution_sandbox.py @@ -497,7 +497,9 @@ def memory_clear(label: str, agent_id: str, client: "Letta"): # Simulate tool execution with the reserved keywords # This would normally happen during agent execution, but we'll test the tool directly # Create the sandbox for the tool - sandbox = AsyncToolSandboxLocal(tool_name="memory_clear", args={"label": "test_block"}, user=test_user, tool_object=created_tool) + sandbox = AsyncToolSandboxLocal( + tool_name="memory_clear", args={"label": "test_block"}, user=test_user, tool_id=created_tool.id, tool_object=created_tool + ) # Initialize the sandbox to detect reserved keywords await sandbox._init_async() diff --git a/tests/test_modal_sandbox_v2.py b/tests/test_modal_sandbox_v2.py index 0990be8b..1e2b7ee9 100644 --- a/tests/test_modal_sandbox_v2.py +++ b/tests/test_modal_sandbox_v2.py @@ -377,6 +377,7 @@ def test_function(x: int, y: int) -> int: tool_name="test_function", args={"x": 1, "y": 2}, user=mock_user, + tool_id=mock_tool.id, tool_object=mock_tool, sandbox_config=mock_sandbox_config, ) @@ -396,6 +397,7 @@ def test_function(x: int, y: int) -> int: tool_name="test_function", args={"x": 1, "y": 2}, user=mock_user, + tool_id=mock_tool.id, tool_object=mock_tool, sandbox_config=mock_sandbox_config, ) @@ -409,6 +411,7 @@ def test_function(x: int, y: int) -> int: tool_name="test_function", args={"x": 1, "y": 2}, user=mock_user, + tool_id=mock_tool.id, tool_object=mock_tool, sandbox_config=mock_sandbox_config, ) @@ -434,6 +437,7 @@ def test_function(x: int, y: int) -> int: tool_name="test_function", args={"x": 1, "y": 2}, user=mock_user, + tool_id=mock_tool.id, tool_object=mock_tool, ) @@ -510,6 +514,7 @@ def test_function(x: int, y: int) -> int: tool_name="test_function", args={"x": 1, "y": 2}, user=mock_user, + tool_id=mock_tool.id, tool_object=mock_tool, sandbox_config=mock_sandbox_config, ) @@ -543,6 +548,7 @@ def test_function(x: int, y: int) -> int: tool_name="sync_func", args={}, user=mock_user, + tool_id=sync_tool.id, tool_object=sync_tool, ) @@ -560,6 +566,7 @@ def test_function(x: int, y: int) -> int: tool_name="async_func", args={}, user=mock_user, + tool_id=async_tool.id, tool_object=async_tool, )