Skip to content

refactor!: replace RestrictedPython code execution with Monty - #1079

Closed
vitalii-dynamiq wants to merge 1 commit into
mainfrom
refactor/remove-restricted-python
Closed

vitalii-dynamiq wants to merge 1 commit into
mainfrom
refactor/remove-restricted-python

Conversation

@vitalii-dynamiq

@vitalii-dynamiq vitalii-dynamiq commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Draft. Companion to the runtime PR that moves Python code execution into the Dynamiq runtime's OS-level sandbox. Keep this draft until that sandbox is enabled in the runtime (see that PR's rollout note), so Python workflows keep running when the runtime bumps to this version.

What

Replaces the RestrictedPython code-execution surface in the open-source package:

  • Removes dynamiq.nodes.tools.Python and dynamiq.nodes.tools.PythonCodeExecutor (the RestrictedPython nodes) and the RestrictedPython dependency (pyproject.toml + uv.lock).
  • Reimplements dynamiq.evaluations.PythonEvaluator on the Monty interpreter instead of RestrictedPython, keeping its public interface, so custom evaluation metrics keep working on a real isolation boundary.
  • Updates GraphOrchestrator conditional edges to accept a PythonMonty node in place of the removed Python node.
  • Keeps PythonInputSchema (reused by PythonMonty and the runtime sandbox node) in a slimmed nodes/tools/python.py. PythonMonty is otherwise unchanged.

Why

RestrictedPython shares the interpreter with the code it tries to restrict, so it is not a real boundary for untrusted code. Open-source dynamiq now runs Python code through PythonMonty (a separate Rust interpreter) or a remote sandbox (E2B, Daytona); on the platform, the Dynamiq runtime maps the removed node types onto its OS-level sandbox.

Tests and examples

Every test and example that used the Python node as a helper is migrated:

  • To PythonMonty where the code is a simple computation (the common case).
  • To FunctionTool where a test needs real in-process behaviour the Monty subset does not provide — blocking (the cancellation suites' sleeping tool) or exact exception text.
  • The one test of a now-removed feature (file-store injection into the code executor) is dropped.

The full suite passes; the only failures in a network-restricted run are pre-existing tiktoken-download splitter tests, unrelated to this change.

Breaking change

dynamiq.nodes.tools.Python and dynamiq.nodes.tools.PythonCodeExecutor are removed and RestrictedPython is no longer a dependency. PythonEvaluator now runs user code in the Monty interpreter, which supports a subset of Python and no third-party libraries, so a metric that relied on RestrictedPython-only behaviour must be adjusted.

@vitalii-dynamiq
vitalii-dynamiq force-pushed the refactor/remove-restricted-python branch from e9da527 to 157cd39 Compare October 29, 2026 14:24
@vitalii-dynamiq vitalii-dynamiq changed the title refactor!: remove the RestrictedPython code-execution nodes refactor!: replace RestrictedPython code execution with Monty Oct 29, 2026
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Coverage

Coverage Report •
FileStmtsMissCoverMissing
dynamiq/evaluations
   python_evaluator.py1001288%48, 114–115, 129–131, 153, 157, 215, 244–246
dynamiq/nodes/agents
   base.py175327784%161, 167, 265, 281, 289, 292, 451, 541, 561, 631, 633, 635, 676–678, 680–685, 690–692, 716–717, 726, 735, 749, 755–756, 767, 783, 785, 787, 789, 832–834, 854–855, 941–942, 944, 947, 975, 980–981, 984, 987, 1038–1039, 1043–1046, 1055–1056, 1076–1077, 1096–1098, 1109–1111, 1158, 1169–1170, 1388, 1391, 1395–1396, 1420–1436, 1460, 1464, 1507–1508, 1512–1513, 1569, 1606, 1617, 1641–1644, 1646, 1648, 1650–1652, 1654–1655, 1662, 1664–1665, 1669–1671, 1677, 1694, 1700, 1703–1705, 1733–1734, 1809–1810, 1816–1818, 1822–1824, 1843–1844, 1869–1870, 1886–1887, 1895, 1904, 1908, 2082, 2118–2120, 2170–2171, 2191, 2198–2199, 2204, 2256, 2346, 2527–2530, 2533, 2538, 2545, 2551–2552, 2554–2555, 2562, 2572–2574, 2587, 2615–2616, 2624–2625, 2629–2630, 2637, 2644, 2668, 2672–2673, 2702, 2715–2720, 2731–2734, 2736–2744, 2751, 2753, 2772, 2791–2792, 2797, 2803, 2847, 2861, 2870, 2877, 2889–2890, 2892–2893, 2897–2898, 2900, 2902, 2920, 2923, 2932–2933, 2935–2936, 2941–2942, 2947–2948, 2950–2951, 2956–2957, 2960, 3082, 3137, 3144, 3184–3185, 3287, 3321–3323, 3328–3329, 3342–3344, 3352–3353, 3357, 3370, 3374, 3380–3382, 3384, 3386, 3388–3391, 3393, 3399, 3402, 3404, 3408, 3411, 3413, 3417, 3420–3422, 3429, 3436, 3439–3440
dynamiq/nodes/agents/orchestrators
   graph.py1915571%79, 82–83, 101, 109–112, 128, 136, 141, 163–164, 166–167, 195, 219–220, 226, 246, 256, 258–263, 265–266, 270–271, 279–281, 283–284, 286–287, 307, 318, 323, 327, 333, 349, 352–353, 358, 368, 391, 393, 404, 428–431
   graph_state.py1484868%63, 79, 99–100, 115, 126, 130, 144–148, 150, 152–154, 185–188, 199, 201–206, 208–209, 212–214, 216, 224–229, 231–232, 242, 244–246, 252, 257, 259
examples/components/core/checkpoints
   loan_cooling_off.py572261%85–87, 89–92, 94–96, 98–103, 105, 109–112, 116
TOTAL529211029581% 
Tests Skipped Failures Errors Time
7738 1 💤 0 ❌ 0 🔥 5m 1s ⏱️

Remove the RestrictedPython-based Python and PythonCodeExecutor nodes and the RestrictedPython
dependency. RestrictedPython shares the interpreter with the code it tries to restrict, so it is not a
real boundary for untrusted code. Standalone open-source dynamiq now runs Python code through
PythonMonty (a separate Rust interpreter) or a remote sandbox (E2B, Daytona); the Dynamiq runtime maps
the former node types onto its own OS-level sandbox when that is enabled.

- PythonEvaluator is kept but reimplemented on the Monty interpreter instead of RestrictedPython, so
  custom evaluation metrics keep working on a real isolation boundary.
- GraphOrchestrator conditional edges now accept a PythonMonty node in place of the removed Python node.
- The shared PythonInputSchema stays; PythonMonty and the runtime sandbox reuse it.
- Tests and examples that used the Python node as a helper move to PythonMonty, or to FunctionTool
  where a test needs real in-process behaviour (blocking, exact exception text) that the Monty subset
  does not provide.

BREAKING CHANGE: dynamiq.nodes.tools.Python and dynamiq.nodes.tools.PythonCodeExecutor are removed and
RestrictedPython is no longer a dependency. dynamiq.evaluations.PythonEvaluator now runs user code in
the Monty interpreter, which supports a subset of Python and no third-party libraries, so a metric that
relied on RestrictedPython-only behaviour must be adjusted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants