Python Server (Remote Code Execution)#
Overview#
The isaacsim.code_editor.python_server extension provides a TCP socket server that enables remote Python code execution within a running Isaac Sim instance.
Any client — VS Code, LLM agents, custom automation scripts — can connect over TCP, send Python source code, and receive structured JSON results.
The extension is automatically loaded as a dependency of isaacsim.code_editor.vscode, but it can also be enabled independently for headless or programmatic workflows.
Enabling the Extension#
Enable the extension using the Extension Manager by searching for isaacsim.code_editor.python_server.
By default the server listens on 127.0.0.1:8226.
These values can be changed through the Carbonite settings (see Settings below).
Wire Protocol#
The wire protocol is intentionally simple so that any TCP client can use it:
Request
Send raw UTF-8 Python source code over a TCP connection to the configured host and port.
After sending all code, the client must signal end-of-input by performing a TCP half-close
(write_eof() in Python, shutdown(SHUT_WR) at the socket level, or -q 0 with netcat).
The server buffers incoming data until EOF is received, ensuring that TCP-fragmented payloads
are fully reassembled before execution.
Warning
If the client does not signal EOF, the server will wait indefinitely for more data and the connection will hang until the client disconnects or a timeout occurs.
Response
A single JSON object is returned, then the connection is closed by the server.
Field |
Description |
|---|---|
|
|
|
Captured standard output ( |
|
(present only for expression evaluation) The evaluated expression value.
JSON-native types ( |
|
(present only on error) List of traceback strings. |
|
(present only on error) Exception class name. |
|
(present only on error) Exception message string. |
Usage Examples#
Python Client#
Connect from any Python script or LLM tool to execute code in the running Isaac Sim instance:
import asyncio
import json
async def execute_in_isaac(source: str, host: str = "127.0.0.1", port: int = 8226) -> dict:
"""Send Python source to a running Isaac Sim instance and return the result."""
reader, writer = await asyncio.open_connection(host, port)
writer.write(source.encode())
writer.write_eof()
data = await reader.read()
writer.close()
return json.loads(data.decode())
# Execute a statement
result = asyncio.run(execute_in_isaac('print("Hello from Isaac Sim!")'))
print(result)
# {'status': 'ok', 'output': 'Hello from Isaac Sim!'}
# Evaluate an expression
result = asyncio.run(execute_in_isaac("1 + 1"))
print(result)
# {'status': 'ok', 'output': '', 'result': 2}
# Handle errors
result = asyncio.run(execute_in_isaac("1 / 0"))
print(result["status"]) # 'error'
print(result["ename"]) # 'ZeroDivisionError'
Command-line (netcat)#
For quick testing, use netcat or similar tools:
echo 'print("Hello")' | nc 127.0.0.1 8226
Async Code Support#
The server supports top-level await expressions.
When submitted code contains await, the server compiles it as an async coroutine,
schedules it on the Kit event loop, and awaits the result before sending the JSON response.
# Top-level await is supported
import asyncio
await asyncio.sleep(0.1)
print("this output is captured")
Standard output from print() calls inside awaited coroutines is captured and included in the
JSON response output field, just like synchronous code.
State Persistence#
The server maintains a shared Python globals dictionary across all connections within a session. Variables, imports, and function definitions from one request are available in subsequent requests. This enables incremental workflows such as building a scene step by step:
# Request 1: Create a stage
import isaacsim.core.experimental.utils.stage as stage_utils
await stage_utils.create_new_stage_async(template="empty")
# Request 2: Uses stage_utils from the previous request
stage_utils.define_prim("/World", "Xform")
Each new TCP connection reuses the same globals, so there is no need to re-import modules or re-define variables between calls.
LLM Integration#
The Python server is designed to be easy for LLM agents to use. An LLM tool implementation needs only to:
Open a TCP connection to the configured host and port.
Send the Python code as UTF-8 bytes.
Signal end-of-input by calling
write_eof()(required — the server buffers until EOF).Read the JSON response.
Parse
statusto determine success or failure,outputfor printed text, andresultfor expression values.
Because the protocol is a single request/response per connection, there is no connection-level state to manage. However, Python-level state (variables, imports) persists across connections within a session (see State Persistence above).
Settings#
The extension is configured through Carbonite settings under /exts/isaacsim.code_editor.python_server/.
Setting |
Default |
Description |
|---|---|---|
|
|
IP address the server listens on. Set to |
|
|
TCP port number. |
|
|
Enable UDP broadcasting of Carbonite log messages to connected clients. May cause the application to freeze in certain circumstances. |
Warning
Setting host to "0.0.0.0" allows any machine on the network to execute arbitrary Python code
in your Isaac Sim session. Only do this in trusted network environments.
Carbonite Log Broadcasting (UDP)#
When carb_logs is enabled, the extension opens a UDP socket on the same host and port.
Clients register by sending any datagram to that address, after which all Carbonite log messages
(Info, Warning, Error, Fatal) are broadcast to registered clients as UTF-8 strings in the format:
[Level][Source] Message
This is primarily used by the Isaac Sim VS Code Edition extension to display Isaac Sim logs in the VS Code output panel.