{"id":50992838,"url":"https://github.com/parcadei/ouros","last_synced_at":"2026-06-20T05:04:20.867Z","repository":{"id":339453253,"uuid":"1160310289","full_name":"parcadei/ouros","owner":"parcadei","description":"A sandboxed Python runtime for AI agents, written in Rust.","archived":false,"fork":false,"pushed_at":"2026-04-21T23:48:38.000Z","size":6193,"stargazers_count":142,"open_issues_count":4,"forks_count":12,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T12:09:19.403Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/parcadei.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-17T19:41:20.000Z","updated_at":"2026-05-27T14:38:59.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/parcadei/ouros","commit_stats":null,"previous_names":["parcadei/ouros"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/parcadei/ouros","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parcadei%2Fouros","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parcadei%2Fouros/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parcadei%2Fouros/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parcadei%2Fouros/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/parcadei","download_url":"https://codeload.github.com/parcadei/ouros/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parcadei%2Fouros/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34557553,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-20T02:00:06.407Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-20T05:04:17.471Z","updated_at":"2026-06-20T05:04:20.861Z","avatar_url":"https://github.com/parcadei.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.jpeg\" alt=\"Ouros\" width=\"600\"\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003eA sandboxed Python runtime for AI agents, written in Rust.\u003c/h3\u003e\n\u003c/div\u003e\n\n---\n\nOuros is more than an interpreter and more than a REPL. It's a **stateful, sandboxed Python runtime** designed for AI agents that need to execute code across multiple turns, fork execution paths, rewind mistakes, and call out to external services — all without any access to the host system.\n\nRun LLM-generated code safely with startup times under 1 microsecond. No containers, no VMs, no network access, no filesystem — just fast, isolated Python execution with full control over what the code can do.\n\n## Key Features\n\n**Sandboxed execution** — No filesystem, network, subprocess, or environment access. The only way sandbox code communicates with the outside world is through external functions you explicitly provide.\n\n**Persistent REPL sessions** — `SessionManager` keeps variables alive across multiple `execute()` calls. Fork sessions, rewind history, transfer variables between sessions, save/restore to disk.\n\n**Snapshot \u0026 resume** — Execution pauses at external function calls and produces a serializable `Snapshot`. Store it in a database, send it over the network, resume in a different process.\n\n**Type checking included** — Full Python type checking via [ty](https://docs.astral.sh/ty/) (from Astral/Ruff), bundled in a single binary. Catch errors before execution.\n\n**72 stdlib modules** — `json`, `re`, `datetime`, `collections`, `dataclasses`, `math`, `itertools`, `decimal`, `pathlib`, `statistics`, `csv`, `hashlib`, `uuid`, `asyncio`, and many more.\n\n**Resource limits** — Cap memory, allocations, stack depth, and execution time. Kill runaway code before it causes problems.\n\n**Multi-language bindings** — Call from Python, JavaScript/TypeScript, or Rust.\n\n## Usage\n\n### Python\n\n```bash\nuv add ouros\n```\n\n```python\nimport ouros\n\n# Basic execution\nm = ouros.Sandbox('x + y', inputs=['x', 'y'])\nresult = m.run(inputs={'x': 10, 'y': 20})  # returns 30\n```\n\n#### External Functions\n\nSandbox code can call functions on the host — but only the ones you allow:\n\n```python\nimport ouros\n\ncode = \"\"\"\ndata = fetch(url)\nlen(data)\n\"\"\"\n\nm = ouros.Sandbox(code, inputs=['url'], external_functions=['fetch'])\n\n# start() pauses when fetch() is called\nresult = m.start(inputs={'url': 'https://example.com'})\n\nprint(type(result))  # \u003cclass 'ouros.Snapshot'\u003e\n#\u003e \u003cclass 'ouros.Snapshot'\u003e\nprint(result.function_name)  # 'fetch'\n#\u003e fetch\nprint(result.args)  # ('https://example.com',)\n#\u003e ('https://example.com',)\n\n# Perform the real fetch, then resume\nresult = result.resume(return_value='hello world')\nprint(result.output)  # 11\n#\u003e 11\n```\n\n#### Async External Functions\n\n```python {test=\"skip - requires async runtime\"}\nimport ouros\n\ncode = \"\"\"\nasync def agent(prompt, messages):\n    while True:\n        output = await call_llm(prompt, messages)\n        if isinstance(output, str):\n            return output\n        messages.extend(output)\n\nawait agent(prompt, [])\n\"\"\"\n\nm = ouros.Sandbox(\n    code,\n    inputs=['prompt'],\n    external_functions=['call_llm'],\n    type_check=True,\n)\n\n\nasync def call_llm(prompt, messages):\n    # Your LLM call here\n    return f'Done after {len(messages)} messages'\n\n\noutput = await ouros.run_async(  # noqa: F704\n    m,\n    inputs={'prompt': 'testing'},\n    external_functions={'call_llm': call_llm},\n)\n```\n\n#### Persistent Sessions (REPL)\n\nVariables survive across calls. Fork sessions. Rewind history. Transfer variables between sessions.\n\n```python\nfrom ouros import SessionManager\n\nmgr = SessionManager()\nsession = mgr.create_session('analysis', external_functions=['llm_query'])\n\n# Execute code — variables persist\nsession.execute('data = [1, 2, 3, 4, 5]')\nsession.execute('total = sum(data)')\n\n# Inspect state\nsession.get_variable('total')  # {'json_value': 15, 'repr': '15'}\nsession.list_variables()  # [{'name': 'data', ...}, {'name': 'total', ...}]\n\n# Fork a session for exploration\nbranch = session.fork('experiment')\nbranch.execute('data.append(100)')\nbranch.get_variable('data')  # [1, 2, 3, 4, 5, 100]\nsession.get_variable('data')  # [1, 2, 3, 4, 5] — original unchanged\n\n# Rewind mistakes\nsession.execute('data = \"oops\"')\nsession.rewind(steps=1)\nsession.get_variable('data')  # [1, 2, 3, 4, 5] — restored\n\n# Save and restore\nmgr.set_storage_dir('/tmp/ouros-sessions')\nsession.save(name='checkpoint-1')\n# Later, or in another process:\nmgr.load_session('checkpoint-1')\n```\n\n#### Serialization\n\nBoth `Sandbox` and `Snapshot` can be serialized to bytes, stored, and restored later:\n\n```python\nimport ouros\n\n# Cache parsed code\nm = ouros.Sandbox('x + 1', inputs=['x'])\ndata = m.dump()\nm2 = ouros.Sandbox.load(data)\nprint(m2.run(inputs={'x': 41}))  # 42\n#\u003e 42\n\n# Suspend execution mid-flight\nm = ouros.Sandbox('fetch(url)', inputs=['url'], external_functions=['fetch'])\nsnapshot = m.start(inputs={'url': 'https://example.com'})\nstate = snapshot.dump()\n\n# Resume later, even in a different process\nsnapshot2 = ouros.Snapshot.load(state)\nresult = snapshot2.resume(return_value='response data')\n```\n\n### JavaScript / TypeScript\n\n```bash\nnpm install ouros\n```\n\n```ts\nimport { Sandbox, Snapshot, runSandboxAsync } from 'ouros'\n\n// Basic\nconst m = new Sandbox('x + y', { inputs: ['x', 'y'] })\nconst result = m.run({ inputs: { x: 10, y: 20 } }) // 30\n\n// Iterative execution with external functions\nconst m2 = new Sandbox('a() + b()', { externalFunctions: ['a', 'b'] })\nlet progress = m2.start()\nwhile (progress instanceof Snapshot) {\n  progress = progress.resume({ returnValue: 10 })\n}\nconsole.log(progress.output) // 20\n```\n\n### Rust\n\n```rust\nuse ouros::{Runner, Object, NoLimitTracker, StdPrint};\n\nlet code = r#\"\ndef fib(n):\n    if n \u003c= 1:\n        return n\n    return fib(n - 1) + fib(n - 2)\n\nfib(x)\n\"#;\n\nlet runner = Runner::new(code.to_owned(), \"fib.py\", vec![\"x\".to_owned()], vec![]).unwrap();\nlet result = runner.run(vec![Object::Int(10)], NoLimitTracker, \u0026mut StdPrint).unwrap();\nassert_eq!(result, Object::Int(55));\n```\n\n### MCP Server\n\nOuros ships an MCP (Model Context Protocol) server that exposes the full `SessionManager` API as tools. Any coding agent or IDE that supports MCP can use Ouros as a sandboxed Python runtime.\n\n```bash\ncargo install ouros-mcp\n```\n\nThe server speaks JSON-RPC over stdin/stdout with Content-Length framing (standard MCP transport).\n\n#### Available Tools\n\n| Category | Tools |\n|----------|-------|\n| **Execution** | `execute`, `resume`, `resume_as_pending`, `resume_futures` |\n| **Variables** | `list_variables`, `get_variable`, `set_variable`, `delete_variable`, `eval_variable`, `transfer_variable`, `call_session` |\n| **Sessions** | `create_session`, `destroy_session`, `list_sessions`, `fork_session`, `reset` |\n| **Persistence** | `save_session`, `load_session`, `list_saved_sessions` |\n| **History** | `rewind`, `history`, `set_history_depth` |\n| **Heap introspection** | `heap_stats`, `snapshot_heap`, `diff_heap` |\n\nAll tools accept an optional `session_id` parameter. When omitted, the `\"default\"` session is used.\n\n#### Adding to Claude Code\n\nAdd to your project's `.claude/settings.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ouros\": {\n      \"command\": \"ouros-mcp\",\n      \"args\": [\"--storage-dir\", \"/tmp/ouros-sessions\"]\n    }\n  }\n}\n```\n\n#### Adding to Cursor\n\nAdd to `.cursor/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"ouros\": {\n      \"command\": \"ouros-mcp\",\n      \"args\": [\"--storage-dir\", \"/tmp/ouros-sessions\"]\n    }\n  }\n}\n```\n\n#### Adding to any MCP client\n\n```json\n{\n  \"command\": \"ouros-mcp\",\n  \"args\": [\"--storage-dir\", \"/tmp/ouros-sessions\"]\n}\n```\n\nThe `--storage-dir` flag is optional. It defaults to `$OUROS_STORAGE_DIR` if set, otherwise `~/.ouros/sessions/`. When configured, `save_session` and `load_session` tools persist session state to disk.\n\n#### Example: Agent workflow over MCP\n\n```text\nAgent → execute(code: \"data = [1, 2, 3]\\nsum(data)\")\n     ← {status: \"ok\", result: 6, variables: [{name: \"data\", type: \"list\"}]}\n\nAgent → execute(code: \"fetch(url)\", session_id: \"default\")\n     ← {status: \"external_call\", call_id: 1, function: \"fetch\", args: [\"https://...\"]}\n\nAgent → resume(call_id: 1, result: \"response body\")\n     ← {status: \"ok\", result: \"response body\"}\n\nAgent → fork_session(session_id: \"default\", new_session_id: \"experiment\")\n     ← {status: \"ok\"}\n\nAgent → execute(code: \"data.append(100)\", session_id: \"experiment\")\n     ← {status: \"ok\"}\n\nAgent → get_variable(name: \"data\", session_id: \"default\")\n     ← {name: \"data\", value: [1, 2, 3]}  // original unchanged\n```\n\n## Use Cases\n\n### AI Agent Code Execution\n\nThe primary use case. LLMs generate Python code, Ouros runs it safely:\n\n- **Tool calling via code** — Instead of JSON tool schemas, let the model write Python that calls your functions\n- **Data processing** — Let agents write analysis code that runs on your data without exposing your filesystem\n- **Multi-step reasoning** — Persistent sessions let agents build up state across multiple code generations\n\n### RLM (Recursive Language Model) Runtime\n\nOuros's `SessionManager` is a natural fit for the [RLM pattern](https://arxiv.org/abs/2512.24601) — a root LLM generates code that runs in a persistent REPL, calling `llm_query()` for sub-tasks. Variables persist in Ouros's heap (not in the LLM's context window), enabling processing of arbitrarily large inputs with a bounded model context.\n\nSee [`examples/rlm_orchestrator/`](examples/rlm_orchestrator/) for a working implementation.\n\n### Sandboxed Computation\n\nAny scenario where you need to run untrusted Python safely: user-submitted code, plugin systems, educational platforms, competitive programming judges.\n\n## Examples\n\nSee [`examples/`](examples/) for complete, runnable examples:\n\n| Example | Language | Description |\n|---------|----------|-------------|\n| [`basic_js/`](examples/basic_js/) | TypeScript | Basic execution, external functions, async, serialization |\n| [`basic_rust/`](examples/basic_rust/) | Rust | Basic execution, fibonacci, external functions |\n| [`expense_analysis/`](examples/expense_analysis/) | Python | Async external functions for team expense analysis |\n| [`rlm_orchestrator/`](examples/rlm_orchestrator/) | Python | Recursive Language Model pattern with persistent REPL sessions |\n| [`sql_playground/`](examples/sql_playground/) | Python | Cross-format data joining with SQL, JSON, and sentiment analysis |\n\n## Stdlib Modules\n\n72 modules implemented natively in Rust:\n\n`abc`, `argparse`, `array`, `asyncio`, `atexit`, `base64`, `binascii`, `bisect`, `builtins`, `cmath`, `codecs`, `collections`, `collections.abc`, `concurrent`, `concurrent.futures`, `contextlib`, `copy`, `csv`, `dataclasses`, `datetime`, `decimal`, `difflib`, `enum`, `errno`, `fnmatch`, `fractions`, `functools`, `gc`, `hashlib`, `heapq`, `html`, `inspect`, `io`, `ipaddress`, `itertools`, `json`, `linecache`, `logging`, `math`, `numbers`, `operator`, `os`, `os.path`, `pathlib`, `pickle`, `pprint`, `queue`, `random`, `re`, `secrets`, `shelve`, `shlex`, `statistics`, `string`, `struct`, `sys`, `textwrap`, `threading`, `time`, `token`, `tokenize`, `tomllib`, `traceback`, `types`, `typing`, `typing_extensions`, `urllib`, `urllib.parse`, `uuid`, `warnings`, `weakref`, `zlib`\n\n## What Ouros Cannot Do\n\n- **Full CPython compatibility** — Ouros implements a substantial subset of Python, not all of it\n- **Third-party libraries** — No pip, no numpy, no pandas. This is by design\n- **Direct I/O** — No filesystem, network, or subprocess access from sandbox code. All external communication goes through external functions you control\n\n## Performance\n\nBenchmarks comparing Ouros vs CPython 3.14 (`make bench`):\n\n| Benchmark | Ouros | CPython | Ratio |\n|-----------|------|---------|-------|\n| End-to-end (parse + run) | 1.2 µs | 8.2 µs | **6.9x faster** |\n| Loop + modulo (1k iter) | 38 µs | 27 µs | 1.4x slower |\n| Kitchen sink (mixed ops) | 5.0 µs | 1.5 µs | 3.4x slower |\n| List append (100k ints) | 3.9 ms | 2.7 ms | 1.4x slower |\n| List append (100k strings) | 13.3 ms | 6.0 ms | 2.2x slower |\n| Fibonacci (recursive, n=25) | 20.5 ms | 9.7 ms | 2.1x slower |\n\nEnd-to-end startup is where Ouros shines — no interpreter boot, no module imports, just parse and go. Runtime is typically 1.4–3.4x slower than CPython, which is fast enough for agent-generated code where the bottleneck is the LLM call, not the computation.\n\n## Concepts\n\n| Term | What it is |\n|------|-----------|\n| **Sandbox** | A compiled Python program. Parse once, run many times with different inputs. No access to the host. |\n| **External function** | A host function that sandbox code can call by name. Execution pauses until the host provides a return value. This is how sandbox code talks to the outside world. |\n| **Snapshot** | A frozen execution state, captured when an external function is called. Serializable to bytes — store in a database, send over the wire, resume in another process. |\n| **SessionManager** | A persistent multi-session runtime. Variables survive across `execute()` calls. Think Jupyter kernel, but sandboxed. |\n| **Session** | A single named environment within a SessionManager. Has its own variables, history, and heap. |\n| **Fork** | Copy a session into an independent branch. The original is unchanged. Use for speculative execution or tree-of-thought. |\n| **Rewind** | Undo the last N `execute()` calls in a session. Variables revert to their previous state. |\n| **Heap introspection** | `heap_stats()`, `snapshot_heap()`, `diff_heap()` — inspect and compare memory state across executions. |\n| **Resource limits** | Cap allocations, memory, stack depth, and wall-clock time. Execution terminates with `ResourceError` if exceeded. |\n| **Type checking** | Static analysis via [ty](https://docs.astral.sh/ty/) before execution. Optional, zero runtime cost. |\n\n## Acknowledgments\n\nOuros is forked from [Monty](https://github.com/pydantic/monty) by [Pydantic](https://pydantic.dev), originally created by [Samuel Colvin](https://github.com/samuelcolvin).\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparcadei%2Fouros","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparcadei%2Fouros","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparcadei%2Fouros/lists"}