mitos-run 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. mitos_run-0.1.0/.gitignore +12 -0
  2. mitos_run-0.1.0/PKG-INFO +465 -0
  3. mitos_run-0.1.0/README.md +433 -0
  4. mitos_run-0.1.0/examples/direct.py +44 -0
  5. mitos_run-0.1.0/mitos/__init__.py +52 -0
  6. mitos_run-0.1.0/mitos/_envelope.py +118 -0
  7. mitos_run-0.1.0/mitos/_k8s.py +69 -0
  8. mitos_run-0.1.0/mitos/aio.py +741 -0
  9. mitos_run-0.1.0/mitos/client.py +382 -0
  10. mitos_run-0.1.0/mitos/direct.py +639 -0
  11. mitos_run-0.1.0/mitos/e2b.py +361 -0
  12. mitos_run-0.1.0/mitos/errors.py +127 -0
  13. mitos_run-0.1.0/mitos/guest.py +189 -0
  14. mitos_run-0.1.0/mitos/integrations/__init__.py +43 -0
  15. mitos_run-0.1.0/mitos/integrations/_mapping.py +178 -0
  16. mitos_run-0.1.0/mitos/integrations/claude_agent.py +329 -0
  17. mitos_run-0.1.0/mitos/integrations/langchain.py +226 -0
  18. mitos_run-0.1.0/mitos/integrations/openai_agents.py +308 -0
  19. mitos_run-0.1.0/mitos/integrations/vibekit.py +222 -0
  20. mitos_run-0.1.0/mitos/integrations/zenml.py +244 -0
  21. mitos_run-0.1.0/mitos/pty.py +173 -0
  22. mitos_run-0.1.0/mitos/sandbox.py +839 -0
  23. mitos_run-0.1.0/mitos/template.py +130 -0
  24. mitos_run-0.1.0/mitos/types.py +225 -0
  25. mitos_run-0.1.0/mitos/workspace.py +149 -0
  26. mitos_run-0.1.0/pyproject.toml +65 -0
  27. mitos_run-0.1.0/tests/__init__.py +0 -0
  28. mitos_run-0.1.0/tests/test_async.py +114 -0
  29. mitos_run-0.1.0/tests/test_auth_resolution.py +75 -0
  30. mitos_run-0.1.0/tests/test_claude_agent_integration.py +243 -0
  31. mitos_run-0.1.0/tests/test_conformance.py +142 -0
  32. mitos_run-0.1.0/tests/test_default_pool.py +135 -0
  33. mitos_run-0.1.0/tests/test_direct.py +158 -0
  34. mitos_run-0.1.0/tests/test_e2b_compat.py +306 -0
  35. mitos_run-0.1.0/tests/test_errors.py +63 -0
  36. mitos_run-0.1.0/tests/test_flat_create.py +633 -0
  37. mitos_run-0.1.0/tests/test_from_name.py +31 -0
  38. mitos_run-0.1.0/tests/test_guest.py +145 -0
  39. mitos_run-0.1.0/tests/test_langchain_integration.py +308 -0
  40. mitos_run-0.1.0/tests/test_openai_agents_integration.py +254 -0
  41. mitos_run-0.1.0/tests/test_preview.py +100 -0
  42. mitos_run-0.1.0/tests/test_pty.py +119 -0
  43. mitos_run-0.1.0/tests/test_quickstart_snippet.py +91 -0
  44. mitos_run-0.1.0/tests/test_run_code.py +143 -0
  45. mitos_run-0.1.0/tests/test_sandbox.py +354 -0
  46. mitos_run-0.1.0/tests/test_stream.py +225 -0
  47. mitos_run-0.1.0/tests/test_template_builder.py +73 -0
  48. mitos_run-0.1.0/tests/test_typed_errors.py +105 -0
  49. mitos_run-0.1.0/tests/test_types.py +52 -0
  50. mitos_run-0.1.0/tests/test_vibekit_integration.py +188 -0
  51. mitos_run-0.1.0/tests/test_wait_ready.py +45 -0
  52. mitos_run-0.1.0/tests/test_workspace.py +77 -0
  53. mitos_run-0.1.0/tests/test_zenml_integration.py +165 -0
@@ -0,0 +1,12 @@
1
+ bin/
2
+ /controller
3
+ /agent
4
+ /facade
5
+ *.exe
6
+ *.test
7
+ *.out
8
+ .env
9
+ __pycache__/
10
+ *.pyc
11
+ .pytest_cache/
12
+ *.egg-info/
@@ -0,0 +1,465 @@
1
+ Metadata-Version: 2.4
2
+ Name: mitos-run
3
+ Version: 0.1.0
4
+ Summary: Python SDK for mitos: sub-millisecond sandbox forking on Kubernetes
5
+ Project-URL: Homepage, https://mitos.run
6
+ Project-URL: Documentation, https://mitos.run/docs
7
+ Project-URL: Repository, https://github.com/mitos-run/mitos
8
+ Project-URL: Issues, https://github.com/mitos-run/mitos/issues
9
+ License: Apache-2.0
10
+ Keywords: ai-agents,code-interpreter,firecracker,kubernetes,microvm,mitos,sandbox
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: httpx>=0.27.0
13
+ Requires-Dist: websocket-client>=1.7.0
14
+ Provides-Extra: claude-agent
15
+ Requires-Dist: claude-agent-sdk>=0.1; extra == 'claude-agent'
16
+ Provides-Extra: dev
17
+ Requires-Dist: kubernetes>=31.0.0; extra == 'dev'
18
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
19
+ Requires-Dist: pytest>=8.0; extra == 'dev'
20
+ Requires-Dist: websockets>=12.0; extra == 'dev'
21
+ Provides-Extra: k8s
22
+ Requires-Dist: kubernetes>=31.0.0; extra == 'k8s'
23
+ Provides-Extra: langchain
24
+ Requires-Dist: langchain>=0.3; extra == 'langchain'
25
+ Provides-Extra: openai-agents
26
+ Requires-Dist: openai-agents>=0.1; extra == 'openai-agents'
27
+ Provides-Extra: vibekit
28
+ Requires-Dist: vibekit>=0.1; extra == 'vibekit'
29
+ Provides-Extra: zenml
30
+ Requires-Dist: zenml>=0.60; extra == 'zenml'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # mitos Python SDK
34
+
35
+ Python client for [mitos-run/mitos](https://github.com/mitos-run/mitos):
36
+ snapshot-fork sandboxes for AI agents on Kubernetes.
37
+
38
+ ```bash
39
+ pip install mitos-run
40
+ ```
41
+
42
+ The PyPI distribution is named `mitos-run` (the bare `mitos` name is taken by an
43
+ unrelated project), but the import package stays `mitos`: you `pip install
44
+ mitos-run` and `import mitos`. Optional extras keep the same import name, for
45
+ example `pip install "mitos-run[k8s]"` for cluster mode.
46
+
47
+ Two modes:
48
+
49
+ - `mitos.create` (flat one-liner): API key plus base URL, returns a Ready
50
+ sandbox handle against the hosted control plane or a standalone
51
+ `sandbox-server`. No Kubernetes required. The canonical entry point.
52
+ - `mitos.AgentRun` / `Sandbox`: drives the Kubernetes CRDs
53
+ (`SandboxClaim`, `SandboxFork`, `SandboxPool`, `SandboxTemplate`) and execs
54
+ through the forkd sandbox API. For operators who run the mitos cluster.
55
+
56
+ ## The flat one-liner
57
+
58
+ ```python
59
+ import mitos
60
+
61
+ # MITOS_API_KEY and MITOS_BASE_URL from the environment (explicit args override).
62
+ sb = mitos.create("python")
63
+ print(sb.exec("echo hello").stdout) # hello
64
+ sb.terminate()
65
+ ```
66
+
67
+ `mitos.create(image, api_key=..., base_url=...)` resolves the API key (argument,
68
+ else `MITOS_API_KEY`, else the CLI login credential file written by
69
+ `mitos auth login`, so one login authenticates the SDK too) and base URL
70
+ (argument, else `MITOS_BASE_URL`) and returns a `DirectSandbox` exposing `exec`,
71
+ `run_code`, `files`, `pty`, `fork`, and `terminate`. `Sandbox.create(...)` is an
72
+ alias for the same call.
73
+
74
+ ```python
75
+ import mitos
76
+
77
+ sb = mitos.create("python", api_key="sk-...", base_url="http://localhost:8080")
78
+
79
+ sb.files.write("/workspace/plan.txt", "draft")
80
+ print(sb.files.read("/workspace/plan.txt")) # draft
81
+
82
+ ex = sb.run_code("import math; math.sqrt(144)")
83
+ print(ex.text) # 12.0
84
+
85
+ fork_a, fork_b = sb.fork(2) # independent sibling sandboxes
86
+ fork_a.exec("echo a > /workspace/a.txt")
87
+ fork_b.exec("echo b > /workspace/b.txt")
88
+
89
+ sb.terminate()
90
+ ```
91
+
92
+ Auth: the API key rides on `Authorization: Bearer <key>` on every request. The
93
+ standalone `sandbox-server` runs tokenless and ignores it; the hosted control
94
+ plane verifies the same header server-side ([#210], not yet built) without an SDK
95
+ change. The key value is never logged and never placed in an error message. A
96
+ missing base URL raises a typed `AgentRunError(code="missing_base_url")` whose
97
+ remediation names the argument and the env var but no key value.
98
+
99
+ [#210]: https://github.com/mitos-run/mitos/issues/210
100
+
101
+ ### Async flat path
102
+
103
+ ```python
104
+ import asyncio
105
+ import mitos.aio
106
+
107
+ async def main():
108
+ sb = await mitos.aio.create("python") # AsyncDirectSandbox
109
+ print((await sb.exec("echo hi")).stdout)
110
+ await sb.files.write("/workspace/a.txt", "x")
111
+ print(await sb.files.read("/workspace/a.txt"))
112
+ ex = await sb.run_code("1 + 1")
113
+ print(ex.text)
114
+ children = await sb.fork(2)
115
+ for c in children:
116
+ await c.terminate()
117
+ await sb.terminate()
118
+
119
+ asyncio.run(main())
120
+ ```
121
+
122
+ ## Cluster mode: the one-liner
123
+
124
+ ```python
125
+ from mitos import AgentRun
126
+
127
+ c = AgentRun() # kubeconfig or in-cluster; autodetected
128
+
129
+ sb = c.sandbox("python", ready=True) # lazy default pool, waits Ready
130
+ print(sb.exec("python -c 'print(2 + 2)'").stdout) # 4
131
+ sb.files.write("/workspace/notes.md", "# findings")
132
+ print(sb.files.read("/workspace/notes.md")) # "# findings"
133
+ sb.terminate()
134
+ ```
135
+
136
+ `c.sandbox("python")` ensures a deterministic default pool
137
+ `mitos-default-python` (a `SandboxTemplate` carrying the image plus a
138
+ `SandboxPool` that references it), creating both if absent. It is
139
+ admin-disableable with `AgentRun(allow_default_pool=False)`, which makes the
140
+ image path raise instead of creating anything.
141
+
142
+ ### Explicit pool (never creates anything)
143
+
144
+ ```python
145
+ sb = c.sandbox(pool="python-agent-pool")
146
+ ```
147
+
148
+ ### Fork a running sandbox
149
+
150
+ ```python
151
+ forks = sb.fork(3) # 3 copies of the warmed state
152
+ for f in forks:
153
+ print(f.exec("echo from-fork").stdout)
154
+ ```
155
+
156
+ ### Reconnect by name (durable handle across processes)
157
+
158
+ ```python
159
+ sb = c.sandbox("python", name="agent-session-1", ready=True)
160
+ # ... later, in a different process:
161
+ sb = c.from_name("agent-session-1")
162
+ print(sb.exec("cat /workspace/notes.md").stdout)
163
+ ```
164
+
165
+ ### Readiness
166
+
167
+ ```python
168
+ sb = c.sandbox("python").wait_until_ready() # chainable; raises on Failed/timeout
169
+ ```
170
+
171
+ ### Streaming exec
172
+
173
+ ```python
174
+ # Callbacks fire per chunk (bytes) as output arrives; the returned ExecResult
175
+ # still carries the full aggregate.
176
+ sb.exec("pytest -x", on_stdout=lambda b: print(b.decode(), end=""))
177
+
178
+ # A long-running background command with a handle.
179
+ bg = sb.exec_background("npm run dev")
180
+ # ... do other work ...
181
+ bg.kill()
182
+ ```
183
+
184
+ ### Structured errors
185
+
186
+ ```python
187
+ from mitos import AgentRunError
188
+
189
+ try:
190
+ sb.exec("false")
191
+ sb.files.read("/does/not/exist")
192
+ except AgentRunError as e:
193
+ print(e.code) # e.g. file_failed, not_found
194
+ print(e.remediation) # an actionable next step
195
+ ```
196
+
197
+ `AgentRunError` is parsed from the server envelope
198
+ `{error:{code, message, cause, remediation}}`. Any bearer token a misconfigured
199
+ server reflects into a body is redacted before it becomes the error cause.
200
+
201
+ ### Async client (hot paths)
202
+
203
+ ```python
204
+ import asyncio
205
+ from mitos import AsyncAgentRun
206
+
207
+ async def main():
208
+ c = AsyncAgentRun()
209
+ sb = await c.sandbox("python", ready=True)
210
+ print((await sb.exec("echo async-hello")).stdout)
211
+ await sb.files.write("/workspace/a.txt", "x")
212
+ print(await sb.files.read("/workspace/a.txt"))
213
+ forks = await sb.fork(2)
214
+ for f in forks:
215
+ await f.terminate()
216
+ await sb.terminate()
217
+
218
+ asyncio.run(main())
219
+ ```
220
+
221
+ `AsyncAgentRun` / `AsyncSandbox` cover the hot paths (exec blocking and
222
+ streaming, files, fork, terminate, wait_until_ready, from_name,
223
+ sandbox(image)). Pool and workspace administration are sync-only. If your build
224
+ includes the code interpreter (#102), `sb.run_code(...)` returns an `Execution`;
225
+ the async client does not yet wrap `run_code`.
226
+
227
+ ## Direct mode (no Kubernetes)
228
+
229
+ ```python
230
+ from mitos.direct import SandboxServer
231
+
232
+ server = SandboxServer("http://localhost:8080")
233
+ server.create_template("python")
234
+ sandbox = server.fork("python")
235
+ print(sandbox.exec("print(1 + 1)").stdout)
236
+ sandbox.terminate()
237
+ ```
238
+
239
+ ## Templates as code
240
+
241
+ Author a custom environment from code with the fluent `Template` builder, in the
242
+ shape E2B and Daytona use. It emits a `SandboxTemplate` spec; no server or KVM is
243
+ needed to build the spec.
244
+
245
+ ```python
246
+ from mitos import Template
247
+
248
+ spec = (
249
+ Template()
250
+ .from_image("python:3.12")
251
+ .copy("app/", "/app")
252
+ .run("pip install -r requirements.txt")
253
+ .set_start("python app.py")
254
+ .to_spec()
255
+ )
256
+
257
+ # Or wrap it as a full object to apply to a cluster:
258
+ obj = Template().from_image("node:24").run("npm ci").to_template("web")
259
+ ```
260
+
261
+ The ordered steps (copy / run / env / workdir) map onto the CRD
262
+ `spec.buildSteps` and feed a content-addressed, chained build cache so unchanged
263
+ steps are reused. See docs/templates.md for the CLI (`mitos template build` /
264
+ `push`) and the cache semantics.
265
+
266
+ ## Integrations
267
+
268
+ Framework adapters live under `mitos.integrations`. Each maps a framework's
269
+ sandbox-backend interface onto the native SDK ops (exec, files, run_code, fork),
270
+ so you change the backend and keep your agent code. The framework is an OPTIONAL
271
+ dependency: the adapter modules import mitos always and the framework lazily, so
272
+ the base SDK installs and tests without it.
273
+
274
+ ### LangChain / deepagents quickstart
275
+
276
+ LangChain and deepagents let you pick a pluggable sandbox backend (they ship
277
+ `E2BSandbox` and `DaytonaSandbox`). `MitosSandbox` is the mitos backend: change
278
+ the backend, keep your agent code.
279
+
280
+ ```python
281
+ from mitos.integrations.langchain import MitosSandbox
282
+
283
+ # Standalone sandbox-server / hosted control plane, no Kubernetes:
284
+ sb = MitosSandbox.create("python", base_url="http://localhost:8080")
285
+
286
+ # Shell command -> normalized result dict (stdout, stderr, exit_code).
287
+ out = sb.execute("echo hi") # alias: sb.run("echo hi")
288
+
289
+ # Filesystem ops.
290
+ sb.write_file("/workspace/a.txt", "hello")
291
+ print(sb.read_file("/workspace/a.txt"))
292
+ print(sb.list_files("/workspace"))
293
+
294
+ # Code execution with rich MIME results (image/png, text/html, ...).
295
+ ex = sb.run_code("import math; math.sqrt(144)")
296
+ print(ex.text, ex.results)
297
+
298
+ sb.close() # alias: sb.stop(); lifecycle close
299
+ ```
300
+
301
+ Install the optional extra only if you use the integration:
302
+ `pip install "mitos-run[langchain]"`. `MitosSandbox` does not subclass any langchain
303
+ type and is fully usable without langchain installed.
304
+
305
+ Fork is a mitos superpower the LangChain sandbox-backend interface does not
306
+ expose, so it is NOT forced onto that interface. Reach branching / parallel runs
307
+ through the adapter's native `fork`, which returns sibling `MitosSandbox`
308
+ backends:
309
+
310
+ ```python
311
+ children = sb.fork(2) # two independent forked sandboxes
312
+ for c in children:
313
+ print(c.execute("echo from-fork")["stdout"])
314
+ c.close()
315
+ ```
316
+
317
+ The wire-op mapping is factored into `mitos.integrations._mapping` so the other
318
+ adapters (OpenAI / Claude, the E2B-compat shim) reuse one translation layer.
319
+
320
+ ### OpenAI Agents SDK quickstart
321
+
322
+ The OpenAI Agents SDK exposes tools as function tools. `MitosSandboxTools` binds
323
+ `run_command` / `read_file` / `write_file` / `run_code` to a mitos sandbox: give
324
+ the tools to your agent and its tool calls run inside the sandbox.
325
+
326
+ ```python
327
+ from mitos.integrations.openai_agents import MitosSandboxTools
328
+
329
+ # Standalone sandbox-server / hosted control plane, no Kubernetes:
330
+ tools = MitosSandboxTools.create("python", base_url="http://localhost:8080")
331
+
332
+ # Use the thin wrappers directly:
333
+ print(tools.run_command("echo hi")["stdout"])
334
+ tools.write_file("/workspace/a.txt", "hello")
335
+ print(tools.read_file("/workspace/a.txt"))
336
+ print(tools.run_code("import math; math.sqrt(144)")["text"])
337
+
338
+ # Or hand real function tools to an Agent (needs the SDK installed):
339
+ from agents import Agent
340
+ agent = Agent(name="coder", tools=tools.as_function_tools())
341
+
342
+ tools.close()
343
+ ```
344
+
345
+ Install the optional extra only if you use the integration:
346
+ `pip install "mitos-run[openai-agents]"`. The adapter is fully usable and testable
347
+ without `openai-agents`; only `as_function_tools()` needs it and it raises a
348
+ clear error naming the extra when absent.
349
+
350
+ ### Claude Agent SDK quickstart
351
+
352
+ The Claude Agent SDK takes custom tools as an in-process MCP server.
353
+ `MitosSandboxTools` binds the same four tools to a mitos sandbox and wraps them
354
+ as an MCP server you pass to the agent.
355
+
356
+ ```python
357
+ from mitos.integrations.claude_agent import MitosSandboxTools
358
+
359
+ # Standalone sandbox-server / hosted control plane, no Kubernetes:
360
+ tools = MitosSandboxTools.create("python", base_url="http://localhost:8080")
361
+
362
+ # The handlers return MCP tool results (a content list of text blocks):
363
+ res = tools.run_command({"command": "echo hi"})
364
+ print(res["content"][0]["text"])
365
+ tools.write_file({"path": "/workspace/a.txt", "content": "hello"})
366
+ print(tools.read_file({"path": "/workspace/a.txt"})["content"][0]["text"])
367
+
368
+ # Or build a real in-process MCP server (needs the SDK installed):
369
+ server = tools.as_mcp_server(name="mitos-sandbox") # pass via mcp_servers
370
+
371
+ tools.close()
372
+ ```
373
+
374
+ Install the optional extra only if you use the integration:
375
+ `pip install "mitos-run[claude-agent]"`. The adapter is fully usable and testable
376
+ without `claude-agent-sdk`; only `as_mcp_server()` needs it and it raises a clear
377
+ error naming the extra when absent.
378
+
379
+ ### Use mitos via VibeKit
380
+
381
+ VibeKit is a provider aggregator over sandbox backends ("E2B today; Daytona,
382
+ Modal, Fly.io coming soon"). `MitosVibeKitProvider` is the mitos provider against
383
+ VibeKit's provider shape: a named provider that creates sandboxes exposing
384
+ command execution, a filesystem, and a lifecycle.
385
+
386
+ ```python
387
+ from mitos.integrations.vibekit import MitosVibeKitProvider
388
+
389
+ provider = MitosVibeKitProvider(base_url="http://localhost:8080") # name == "mitos"
390
+ sandbox = provider.create("python")
391
+
392
+ out = sandbox.run_command("echo hi") # {stdout, stderr, exit_code, exec_time_ms}
393
+ sandbox.write_file("/workspace/a.txt", "hello")
394
+ print(sandbox.read_file("/workspace/a.txt"))
395
+ ex = sandbox.run_code("1 + 1") # rich Execution with MIME results
396
+ sandbox.kill() # alias: sandbox.close()
397
+ ```
398
+
399
+ Install the optional extra only if you use the integration:
400
+ `pip install "mitos-run[vibekit]"`. The provider does not subclass any VibeKit type
401
+ and is fully usable and testable without VibeKit installed. Fork stays reachable
402
+ as a mitos-native op via `sandbox.fork(n)`, which VibeKit's provider interface
403
+ does not expose.
404
+
405
+ ### Use mitos via ZenML
406
+
407
+ ZenML treats a sandbox as a pluggable stack component selected by a flavor.
408
+ `MitosSandboxComponent` is the framework-neutral mitos backend (config, flavor
409
+ name, and the provision / run_command / files / run_code / deprovision logic the
410
+ flavor wraps).
411
+
412
+ ```python
413
+ from mitos.integrations.zenml import MitosSandboxComponent, MitosSandboxConfig
414
+
415
+ comp = MitosSandboxComponent(
416
+ MitosSandboxConfig(template="python", base_url="http://localhost:8080")
417
+ ) # FLAVOR == "mitos"
418
+ comp.provision()
419
+ out = comp.run_command("echo hi") # {stdout, stderr, exit_code, exec_time_ms}
420
+ comp.write_file("/workspace/a.txt", "hello")
421
+ ex = comp.run_code("1 + 1") # rich Execution; comp.run_code_dict(...) for JSON
422
+ comp.deprovision()
423
+ ```
424
+
425
+ Install the optional extra only if you use the integration:
426
+ `pip install "mitos-run[zenml]"`. The component backend is fully usable and testable
427
+ without ZenML; only `MitosSandboxComponent.flavor()` needs it and raises a clear
428
+ error naming the extra when absent.
429
+
430
+ ### Registering mitos with VibeKit / ZenML (maintainer step)
431
+
432
+ The adapters above implement the mitos backend each aggregator expects, but
433
+ LISTING mitos as a selectable option inside VibeKit or ZenML is a contribution to
434
+ THOSE projects' own repositories and is NOT done by installing this SDK. It is a
435
+ maintainer step:
436
+
437
+ - **VibeKit:** open a PR to VibeKit adding a provider entry that constructs
438
+ `MitosVibeKitProvider` and wires its create / command / filesystem methods to
439
+ VibeKit's provider interface, following VibeKit's contribution process.
440
+ - **ZenML:** open a PR (or ship a plugin) that subclasses ZenML's sandbox
441
+ stack-component base with `MitosSandboxConfig` and `FLAVOR = "mitos"`, delegates
442
+ its hooks to `MitosSandboxComponent`, and registers the flavor through ZenML's
443
+ flavor API, following ZenML's integration contribution process.
444
+
445
+ Until those external PRs merge, mitos is usable through the adapters directly (as
446
+ shown above); it is not yet selectable by name inside VibeKit's or ZenML's own
447
+ provider lists. See the module docstrings in `mitos/integrations/vibekit.py` and
448
+ `mitos/integrations/zenml.py` for the targeted contract each PR conforms to.
449
+
450
+ ## What is proven where
451
+
452
+ The cluster examples (lazy default-pool creation, fork, from_name reconnect,
453
+ readiness, async hot paths) run against the real Firecracker engine in the KVM
454
+ CI job. The structured-error parsing and the wire shapes are unit-tested with
455
+ no cluster. No latency or throughput number is claimed in this README.
456
+
457
+ ## Development
458
+
459
+ ```bash
460
+ pip install -e ".[dev]"
461
+ pytest tests/ -v
462
+ ```
463
+
464
+ See the [repository README](https://github.com/mitos-run/mitos#readme)
465
+ for project status; this SDK is pre-alpha and its API may change.