Skip to content

Commit faebe81

Browse files
Update docs: explain Runtime.start() blocking behavior across environments
Co-authored-by: nivedit <nivedit@aikin.club>
1 parent b6f1db8 commit faebe81

3 files changed

Lines changed: 72 additions & 0 deletions

File tree

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ This allows developers to deploy production agents that can scale beautifully to
7171
).start()
7272
```
7373

74+
Note: `Runtime.start()` will block the main thread in normal scripts (no running event loop). In interactive environments with an active loop (e.g., Jupyter), it returns an `asyncio.Task` and does not block. For non-blocking usage from a sync script, you can run it in a background thread:
75+
76+
```python
77+
from threading import Thread
78+
79+
runtime = Runtime(name="my-first-runtime", namespace="hello-world", nodes=[MyFirstNode])
80+
Thread(target=runtime.start, daemon=True).start()
81+
```
82+
7483
- ### Define your first graph
7584

7685
Graphs are then described connecting nodes with relationships in json objects. Exosphere runs graph as per defined trigger conditions. See [Graph definitions](https://docs.exosphere.host/exosphere/create-graph/) to see more examples.

docs/docs/getting-started.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,39 @@ Runtime(
8686
).start()
8787
```
8888

89+
### Note on blocking behavior of `Runtime.start()`
90+
91+
By design, `Runtime.start()` runs the runtime loop indefinitely and will block the main thread when no asyncio event loop is running (e.g., normal Python scripts). In interactive environments that already have an event loop (like Jupyter notebooks), `Runtime.start()` returns an `asyncio.Task` and does not block.
92+
93+
- If you're in an async/interactive environment (e.g., Jupyter/REPL with a running loop):
94+
95+
```python
96+
# Jupyter/async environment
97+
runtime = Runtime(namespace="MyProject", name="DataProcessor", nodes=[SampleNode])
98+
task = runtime.start() # task is an asyncio.Task running in the background
99+
# You can continue interacting, and optionally await/cancel the task later
100+
# await task # if you want to wait on it
101+
```
102+
103+
- If you need a non-blocking start from a regular sync script, run it in a background thread:
104+
105+
```python
106+
from threading import Thread
107+
108+
runtime = Runtime(namespace="MyProject", name="DataProcessor", nodes=[SampleNode])
109+
Thread(target=runtime.start, daemon=True).start()
110+
# continue with other work in the main thread
111+
```
112+
113+
- Alternatively, from an async context you can offload to a thread:
114+
115+
```python
116+
import asyncio
117+
118+
runtime = Runtime(namespace="MyProject", name="DataProcessor", nodes=[SampleNode])
119+
await asyncio.to_thread(runtime.start)
120+
```
121+
89122
## Next Steps
90123

91124
Now that you have the basics, explore:

python-sdk/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,36 @@ Runtime(
5959
).start()
6060
```
6161

62+
### Note on blocking behavior of `Runtime.start()`
63+
64+
`Runtime.start()` blocks the main thread when no asyncio event loop is running (typical Python scripts). In environments with an active event loop (e.g., Jupyter), it returns an `asyncio.Task` and does not block.
65+
66+
- Jupyter/interactive (non-blocking):
67+
68+
```python
69+
runtime = Runtime(namespace="MyProject", name="DataProcessor", nodes=[SampleNode])
70+
task = runtime.start() # background asyncio.Task
71+
# await task # optionally wait on it later
72+
```
73+
74+
- Regular sync script (non-blocking via thread):
75+
76+
```python
77+
from threading import Thread
78+
79+
runtime = Runtime(namespace="MyProject", name="DataProcessor", nodes=[SampleNode])
80+
Thread(target=runtime.start, daemon=True).start()
81+
```
82+
83+
- From async code (offload to a thread):
84+
85+
```python
86+
import asyncio
87+
88+
runtime = Runtime(namespace="MyProject", name="DataProcessor", nodes=[SampleNode])
89+
await asyncio.to_thread(runtime.start)
90+
```
91+
6292
## Environment Configuration
6393

6494
The SDK requires the following environment variables for authentication with ExosphereHost:

0 commit comments

Comments
 (0)