Skip to content

WIP: Add Python runtime environments#2704

Draft
TomCC7 wants to merge 17 commits into
mainfrom
cc/feat/venv-worker
Draft

WIP: Add Python runtime environments#2704
TomCC7 wants to merge 17 commits into
mainfrom
cc/feat/venv-worker

Conversation

@TomCC7

@TomCC7 TomCC7 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

Python modules currently run in the coordinator environment, which forces module-specific dependency stacks into dimos run and makes modules with complex or conflicting dependencies difficult to deploy safely.

Closes N/A

Solution

Adds Python runtime environments for isolated module workers:

  • Runtime environment registration and class-keyed runtime placements on blueprints.
  • Runtime reconciliation before deployment slices launch workers, using locked/non-mutating Runtime Projects.
  • Python Runtime Worker launchers for venv/project-backed workers while preserving normal DimOS Python module semantics.
  • Contract/implementation split so the coordinator imports dependency-light Module Contracts and workers import Runtime Implementations.
  • Runtime project example under examples/dimos-demo-worker-module/ with a runnable script showing main venv → isolated worker venv execution.
  • OpenSpec artifacts and docs for the runtime environment model.

Key tradeoffs:

  • Runtime Implementations must subclass Module Contracts for this extraction; descriptor/structural compatibility is deferred.
  • Runtime Project reconciliation is automatic on deployment, but source-controlled project files/lockfiles are not mutated.
  • Native module runtime unification and remote deployment are out of scope.

How to Test

uv run pytest dimos/core/test_runtime_environment.py dimos/core/test_runtime_reconciliation.py dimos/core/test_venv_module_demo.py dimos/core/coordination/test_worker.py dimos/core/coordination/test_module_coordinator.py dimos/core/coordination/test_blueprints.py dimos/robot/cli/test_dimos.py -q

Result: 96 passed.

uv run python examples/dimos-demo-worker-module/demo_run_blueprint.py

Expected: prints the repo/main Python executable, a worker Python executable under examples/dimos-demo-worker-module/.venv/, runtime-only dependency output RuntimeDependency, and worker result: demo-runtime:HELLO FROM MAIN VENV.

openspec validate python-project-runtime-environments --type change --strict --no-interactive

Result: valid.

Contributor License Agreement

  • I have read and approved the CLA.

@mintlify

mintlify Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
dimensional 🟢 Ready View Preview Jul 2, 2026, 11:22 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@TomCC7 TomCC7 changed the title Add Python runtime environments WIP: Add Python runtime environments Jul 2, 2026
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
2447 1 2446 35
View the top 1 failed test(s) by shortest run time
dimos.core.test_venv_module_demo::test_demo_runtime_project_executes_with_project_worker
Stack Traces | 11.1s run time
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f0cf77a3440>

    @pytest.mark.skipif_macos_bug
    def test_demo_runtime_project_executes_with_project_worker(monkeypatch) -> None:
        monkeypatch.syspath_prepend(str(EXAMPLE_SRC))
        contract_module = importlib.import_module("dimos_demo_worker_module.contract")
        demo_contract = contract_module.DemoWorkerModule
        runtime = PythonProjectRuntimeEnvironment(
            name="demo-worker-test-runtime",
            project=EXAMPLE_ROOT,
            env={"PYTHONPATH": _example_pythonpath()},
        )
        subprocess.run(
            ("uv", "sync", "--locked"),
            cwd=EXAMPLE_ROOT,
            check=True,
            capture_output=True,
            text=True,
            timeout=180,
        )
        placement = RuntimePlacement(
            runtime=runtime.name,
            implementation="dimos_demo_worker_module.runtime.DemoWorkerRuntimeModule",
        )
        manager = WorkerManagerPython(
            g=GlobalConfig(n_workers=1, viewer="none"),
        )
        manager.register_runtime_environments(RuntimeEnvironmentRegistry().register(runtime))
        module = None
    
        try:
            manager.start()
>           module = manager.deploy(
                demo_contract,
                global_config,
                {},
                runtime_placement=placement,
            )

contract_module = <module 'dimos_demo_worker_module.contract' from '.../src/dimos_demo_worker_module/contract.py'>
demo_contract = <class 'dimos_demo_worker_module.contract.DemoWorkerModule'>
manager    = <dimos.core.coordination.worker_manager_python.WorkerManagerPython object at 0x7f0cf46886b0>
module     = None
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f0cf77a3440>
placement  = RuntimePlacement(runtime='demo-worker-test-runtime', implementation='dimos_demo_worker_module.runtime.DemoWorkerRuntimeModule')
runtime    = PythonProjectRuntimeEnvironment(name='demo-worker-test-runtime', project=PosixPath('.../dimos/dimos/exam...thon3.12/site-packages/rerun_sdk:.../dimos/dimos/.venv/lib/python3.12........./site-packages/setuptools/_vendor'})

dimos/core/test_venv_module_demo.py:92: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../core/coordination/worker_manager_python.py:94: in deploy
    workers, launcher = self._pool_for(runtime_placement)
        global_config = GlobalConfig(robot_ip=None, robot_ips=None, unitree_aes_128_key=None, xarm7_ip=None, xarm6_ip=None, can_port=None, dev...e, obstacle_avoidance=True, detection_model='moondream', listen_host='127.0.0.1', dimsim_scene='apt', dimsim_port=8090)
        kwargs     = {}
        module_class = <class 'dimos_demo_worker_module.contract.DemoWorkerModule'>
        runtime_placement = RuntimePlacement(runtime='demo-worker-test-runtime', implementation='dimos_demo_worker_module.runtime.DemoWorkerRuntimeModule')
        self       = <dimos.core.coordination.worker_manager_python.WorkerManagerPython object at 0x7f0cf46886b0>
.../core/coordination/worker_manager_python.py:412: in _pool_for
    self._add_workers_to_pool(
        launcher   = <dimos.core.coordination.worker_launcher.CommandWorkerLauncher object at 0x7f0cf7549850>
        runtime    = PythonProjectRuntimeEnvironment(name='demo-worker-test-runtime', project=PosixPath('.../dimos/dimos/exam...thon3.12/site-packages/rerun_sdk:.../dimos/dimos/.venv/lib/python3.12........./site-packages/setuptools/_vendor'})
        runtime_name = 'demo-worker-test-runtime'
        runtime_placement = RuntimePlacement(runtime='demo-worker-test-runtime', implementation='dimos_demo_worker_module.runtime.DemoWorkerRuntimeModule')
        self       = <dimos.core.coordination.worker_manager_python.WorkerManagerPython object at 0x7f0cf46886b0>
.../core/coordination/worker_manager_python.py:427: in _add_workers_to_pool
    worker.start_process()
        _          = 0
        launcher   = <dimos.core.coordination.worker_launcher.CommandWorkerLauncher object at 0x7f0cf7549850>
        n          = 1
        self       = <dimos.core.coordination.worker_manager_python.WorkerManagerPython object at 0x7f0cf46886b0>
        worker     = <dimos.core.coordination.python_worker.PythonWorker object at 0x7f0cf7541f10>
        workers    = []
.../core/coordination/python_worker.py:208: in start_process
    self._process = self._launcher.launch(self._worker_id)
        self       = <dimos.core.coordination.python_worker.PythonWorker object at 0x7f0cf7541f10>
.../core/coordination/worker_launcher.py:130: in launch
    return _launch_subprocess_worker(
        self       = <dimos.core.coordination.worker_launcher.CommandWorkerLauncher object at 0x7f0cf7549850>
        worker_id  = 82
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def _launch_subprocess_worker(
        *,
        argv: tuple[str, ...],
        env: dict[str, str],
        cwd: Path | None,
        worker_id: int,
        runtime_name: str,
        startup_timeout: float,
        terminate_process_group: bool,
    ) -> WorkerProcessHandle:
        with tempfile.TemporaryDirectory(prefix="dimos-runtime-worker-") as tmpdir:
            address = str(Path(tmpdir) / "worker.sock")
            authkey = secrets.token_bytes(32)
            listener = Listener(address, family="AF_UNIX", authkey=authkey)
            process_env = {**os.environ, **env}
            full_argv = (
                *argv,
                "--address",
                address,
                "--authkey-hex",
                authkey.hex(),
                "--worker-id",
                str(worker_id),
            )
            process: subprocess.Popen[bytes] | None = None
            try:
                process = subprocess.Popen(
                    full_argv,
                    cwd=cwd,
                    env=process_env,
                    start_new_session=terminate_process_group,
                )
                listener_socket = listener._listener._socket  # type: ignore[attr-defined]
                if not wait([listener_socket], timeout=startup_timeout):
                    process.terminate()
>                   raise WorkerLaunchError(
                        f"Runtime {runtime_name!r} worker did not connect within {startup_timeout}s"
                    )
E                   dimos.core.coordination.worker_launcher.WorkerLaunchError: Runtime 'demo-worker-test-runtime' worker did not connect within 10.0s

address    = '.../tmp/dimos-runtime-worker-lrpe0pnj/worker.sock'
argv       = ('uv', 'run', '--no-sync', 'python', '-m', 'dimos.core.coordination.venv_worker_entrypoint')
authkey    = b"\t\x149\xa3\xf8\xe0\xaf\xf83\xcb\xe2{\x0b\xbf'P}\r>\x7f\xa1\x00\x1e\xe2\xda\tb\x0b\xa3\xae0\xef"
cwd        = PosixPath('.../dimos/examples/dimos-demo-worker-module')
env        = {'PYTHONPATH': '.../dimos/examples/dimos-demo-worker-module/src:.../work/dimos/dimos:/hom...ython3.12/site-packages/rerun_sdk:.../dimos/dimos/.venv/lib/python3.12........./site-packages/setuptools/_vendor'}
full_argv  = ('uv', 'run', '--no-sync', 'python', '-m', 'dimos.core.coordination.venv_worker_entrypoint', ...)
listener   = <multiprocessing.connection.Listener object at 0x7f0cf7542210>
listener_socket = <socket.socket [closed] fd=-1, family=1, type=1, proto=0>
process    = <Popen: returncode: 1 args: ('uv', 'run', '--no-sync', 'python', '-m', 'dimo...>
process_env = {'ACCEPT_EULA': 'Y', 'ACTIONS_ID_TOKEN_REQUEST_TOKEN': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjM4ODI2YjE3LTZhMzAtNWY5Yi1iMTY5LT...-version=2.0', 'ACTIONS_ORCHESTRATION_ID': '20633935-45ea-4509-b41f-35748f348d3e.tests._3_10_ubuntu-latest_false', ...}
runtime_name = 'demo-worker-test-runtime'
startup_timeout = 10.0
terminate_process_group = True
tmpdir     = '/tmp/dimos-runtime-worker-lrpe0pnj'
worker_id  = 82

.../core/coordination/worker_launcher.py:180: WorkerLaunchError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Comment thread dimos/core/runtime_environment.py Outdated
Comment thread dimos/core/runtime_environment.py Outdated
Comment thread dimos/core/coordination/blueprints.py
Comment thread dimos/core/coordination/module_coordinator.py Outdated
Comment thread dimos/core/coordination/module_coordinator.py Outdated
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.

1 participant