Skip to content
Open
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f98c652
added isolated code executor
AlexFierro9 Oct 20, 2025
b3cdd32
Update src/google/adk/code_executors/isolated_code_executor.py
AlexFierro9 Oct 20, 2025
a77b0c2
Update src/google/adk/code_executors/isolated_code_executor.py
AlexFierro9 Oct 20, 2025
8fbd73b
added the units tests
AlexFierro9 Oct 20, 2025
9cf3ef0
Merge branch 'main' into main
AlexFierro9 Oct 21, 2025
98e5a83
Merge branch 'main' into main
AlexFierro9 Oct 22, 2025
ff06b44
Merge branch 'main' into main
hangfei Oct 23, 2025
ba5dbbd
Merge branch 'main' into main
AlexFierro9 Oct 24, 2025
b0f3f6c
run autoformat.sh
AlexFierro9 Oct 24, 2025
1e49154
Merge branch 'main' of https://github.com/AlexFierro9/adk-python
AlexFierro9 Oct 24, 2025
5d01c91
Merge branch 'main' into main
AlexFierro9 Oct 25, 2025
6424fc4
Merge remote-tracking branch 'upstream/main'
AlexFierro9 Oct 30, 2025
c1e3487
Merge branch 'main' into main
hangfei Nov 5, 2025
039b9b9
Added Isolated code executor as a config option for unsafe local code…
AlexFierro9 Nov 9, 2025
0dc3c26
Merge branch 'main' of https://github.com/AlexFierro9/adk-python
AlexFierro9 Nov 9, 2025
6a9ee6b
Added Isolated Code Executor as a separate config
AlexFierro9 Nov 9, 2025
1cc3a2e
Merge branch 'main' into main
AlexFierro9 Nov 9, 2025
7603e57
got rid of isolated code executor file, added tests cases (with assis…
AlexFierro9 Nov 9, 2025
bf19756
Merge branch 'main' of https://github.com/AlexFierro9/adk-python
AlexFierro9 Nov 9, 2025
8f12cc6
Merge branch 'main' into main
AlexFierro9 Nov 9, 2025
453e786
changed use_isolated_process to use_separate_process, ran isort for f…
AlexFierro9 Nov 11, 2025
f742aea
Merge branch 'main' into main
AlexFierro9 Nov 11, 2025
ec4d631
Merge branch 'main' into main
hangfei Nov 11, 2025
1c07fa0
Revert "Added Isolated Code Executor as a separate config"
AlexFierro9 Nov 12, 2025
f64a8ab
Merge branch 'main' of https://github.com/AlexFierro9/adk-python
AlexFierro9 Nov 12, 2025
5840c02
Merge branch 'main' into main
AlexFierro9 Nov 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/google/adk/code_executors/isolated_code_executor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from __future__ import annotations

from contextlib import redirect_stdout
import io
import re
from typing import Any

from pydantic import Field
from typing_extensions import override

from ..agents.invocation_context import InvocationContext
from .base_code_executor import BaseCodeExecutor
from .code_execution_utils import CodeExecutionInput
from .code_execution_utils import CodeExecutionResult

import sys
import subprocess

#Don't think this is needed anymore but keeping it around just in case.

# def _prepare_globals(code: str, globals_: dict[str, Any]) -> None:
# """Prepare globals for code execution, injecting __name__ if needed."""
# if re.search(r"if\s+__name__\s*==\s*['\"]__main__['\"]", code):
# globals_['__name__'] = '__main__'

class IsolatedCodeExecutor(BaseCodeExecutor):
"""A code executor that safely executes code in an isolated environment through
the current local context."""

# Overrides the BaseCodeExecutor attribute: this executor cannot be stateful.
stateful: bool = Field(default=False, frozen=True, exclude=True)

# Overrides the BaseCodeExecutor attribute: this executor cannot
# optimize_data_file.
optimize_data_file: bool = Field(default=False, frozen=True, exclude=True)

def __init__(self, **data):
"""Initializes the IsolatedCodeExecutor."""
if 'stateful' in data and data['stateful']:
raise ValueError('Cannot set `stateful=True` in IsolatedCodeExecutor.')
if 'optimize_data_file' in data and data['optimize_data_file']:
raise ValueError(
'Cannot set `optimize_data_file=True` in IsolatedCodeExecutor.'
)
super().__init__(**data)

@override
def execute_code(
self,
invocation_context: InvocationContext,
code_execution_input: CodeExecutionInput,
) -> CodeExecutionResult:
# Executes code by spawning a new python interpreter process.
code = code_execution_input.code
process_result = subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Consider adding a timeout to the subprocess.run call to prevent indefinite hanging in case the executed code enters an infinite loop or takes too long to execute. This will improve the robustness of the executor.

Also, it might be useful to capture and log the return code of the subprocess for debugging purposes.

    process_result = subprocess.run(
    [sys.executable, "-c", code],
    capture_output=True,
    text=True, # Enables decoding of stdout and stderr as text
    timeout=30 # Add a timeout to prevent indefinite hanging
    )

    if process_result.returncode != 0:
      print(f"Code execution failed with return code: {process_result.returncode}")


# Collect the final result.
return CodeExecutionResult(
stdout=process_result.stdout,
stderr=process_result.stderr,
output_files=[],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It's important to handle potential exceptions that might occur during the code execution within the subprocess. For example, the code might raise an exception that isn't properly propagated back to the main process. Consider adding a try-except block around the subprocess.run call to catch and handle such exceptions, providing more informative error messages in the CodeExecutionResult.

Suggested change
return CodeExecutionResult(
stdout=process_result.stdout,
stderr=process_result.stderr,
output_files=[],
try:
process_result = subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True
)
except subprocess.TimeoutExpired as e:
return CodeExecutionResult(
stdout="",
stderr=f"Code execution timed out: {e}",
output_files=[],
)
except Exception as e:
return CodeExecutionResult(
stdout="",
stderr=f"Code execution failed: {e}",
output_files=[],
)

)