# Installation OpenRath supports CPython `3.10` through `3.13`. Choose the installation path that matches your use case: | Goal | Path | | --- | --- | | Use the v2 durable Runtime and Agent Server | [Install Stable v2.0.0 from the GitHub release](#install-v200-from-the-github-release) | | Use the v1-compatible façade published on PyPI | [Install the v1-compatible package from PyPI](#install-openrath-from-pypi) | | Route chat through LiteLLM providers | [Install the LiteLLM extra](#install-the-litellm-extra) | | Modify OpenRath source, run tests, or build docs | [Install from source for development](#install-from-source-for-development) | | Use persistent memory | [Configure Memory](#configure-memory) | | Use a container sandbox backend | [Launch and connect OpenSandbox](#launch-and-connect-opensandbox) | | Use OpenViking memory | [Launch and connect OpenViking](#launch-and-connect-openviking) | (install-v200-from-the-github-release)= ## Install Stable v2.0.0 from the GitHub release Install the exact Stable `2.0.0` release wheel: ```bash python -m pip install \ "openrath @ https://github.com/Rath-Team/OpenRath/releases/download/v2.0.0/openrath-2.0.0-py3-none-any.whl" ``` For the Agent Server with PostgreSQL: ```bash python -m pip install \ "openrath[server,postgres] @ https://github.com/Rath-Team/OpenRath/releases/download/v2.0.0/openrath-2.0.0-py3-none-any.whl" ``` Continue with the [v2 quickstart](v2/quickstart.md). For service deployments, follow the [operations guide](v2/operations.md). (install-openrath-from-pypi)= ## Install the v1-compatible package from PyPI The durable v2 Runtime is distributed through the exact `2.0.0` release asset above. The PyPI path installs the retained v1-compatible façade: `Session`, `Workflow`, `FlowToolCall`, the local backend, local memory, OpenAI-compatible and Anthropic LLM clients, persistent config, and the stdio MCP adapter. LiteLLM is optional. ```bash pip install "openrath==1.3.0" ``` If you manage your project environment with `uv`: ```bash uv add "openrath==1.3.0" ``` Core dependencies include: | Dependency | Purpose | | --- | --- | | `openai` | OpenAI-compatible chat client and Azure OpenAI routing. | | `anthropic` | Anthropic Messages API adapter. | | `mcp` | Stdio MCP server integration. | | `pydantic` | Tool schemas, request/response models, and configuration types. | (install-the-litellm-extra)= ### Install the LiteLLM extra OpenRath v2.0.0 can route chat calls through LiteLLM when its optional extra is installed: ```bash python -m pip install \ "openrath[litellm] @ https://github.com/Rath-Team/OpenRath/releases/download/v2.0.0/openrath-2.0.0-py3-none-any.whl" ``` For the v1-compatible PyPI package, use `pip install "openrath[litellm]==1.3.0"`. ```python from rath.llm import Provider, chat_client_for provider = Provider( provider_kind="litellm", model="gemini/gemini-2.0-flash", ) client = chat_client_for(provider) ``` Without the extra, the LiteLLM adapter is not registered and selecting `provider_kind="litellm"` raises an unknown-provider error. ### Configure the LLM Real LLM workflows require provider configuration. The most explicit path is to build a `Provider` with the API key, optional base URL, model, and provider kind. Clients resolve credentials in this order: 1. `Provider(...)` fields. 2. Environment variables. 3. The OpenRath config store (`config.json` plus `credentials.json`). ```bash export OPENAI_API_KEY=... export OPENAI_BASE_URL=https://api.openai.com/v1 export OPENAI_DEFAULT_MODEL=gpt-5.5 export ANTHROPIC_API_KEY=... export ANTHROPIC_DEFAULT_MODEL=claude-sonnet-4-5 export LITELLM_API_KEY=... export LITELLM_API_BASE=... export LITELLM_MODEL=gemini/gemini-2.0-flash ``` | Variable | Meaning | | --- | --- | | `OPENAI_API_KEY` | OpenAI or compatible gateway API key. The default client fails if this is missing. | | `OPENAI_BASE_URL` | OpenAI-compatible endpoint. | | `OPENAI_DEFAULT_MODEL` | OpenAI-compatible fallback model. | | `AZURE_OPENAI_ENDPOINT` | Azure OpenAI endpoint fallback when `Provider.base_url` is empty. | | `AZURE_OPENAI_API_KEY` / `AZURE_API_KEY` | Azure OpenAI key fallbacks. | | `OPENAI_API_VERSION` / `AZURE_OPENAI_API_VERSION` | Legacy Azure API version; default is `2024-10-21`. | | `ANTHROPIC_API_KEY` | Anthropic API key. | | `ANTHROPIC_BASE_URL` | Optional Anthropic-compatible endpoint. | | `ANTHROPIC_DEFAULT_MODEL` | Anthropic fallback model. | | `LITELLM_API_KEY` | Generic LiteLLM key fallback; provider-specific variables may instead be resolved by LiteLLM. | | `LITELLM_API_BASE` | Optional LiteLLM API-base override. | | `LITELLM_MODEL` | Model fallback when `Provider.model` is unset. | Persistent config is JSON: ```json { "version": 1, "llm": { "default_provider": "openai-main", "providers": { "openai-main": { "provider_kind": "openai", "model": "gpt-5.5" } } }, "memory": { "default_provider": "local-main", "providers": { "local-main": { "backend_kind": "local", "path": ".openrath/memory", "embedding_provider": "openai-main", "chat_provider": "openai-main" } } } } ``` Store the key in the sibling credentials file: ```json { "version": 1, "llm": { "providers": { "openai-main": "sk-..." } } } ``` The v1-compatible config loader included in v2.0.0 still loads an inline `api_key` from legacy `config.json`; the next `ConfigStore.save()` migrates it to `credentials.json` (mode `0600` on POSIX). When a save rewrites a non-empty credentials payload, keys set to `None` are omitted. If the resulting payload is empty, however, the loader leaves an existing sidecar untouched; remove that file or entry explicitly when revoking the last stored credential. Use it from Python: ```python from rath.llm import Provider provider = Provider.from_config("openai-main", temperature=0.2) ``` OpenRath does not auto-load `.env` files. Source them in the shell or let your deployment platform inject secrets before starting Python. For a named LiteLLM provider, use the normal JSON config schema and construct the provider explicitly through `Provider.from_config(...)`: ```json { "version": 1, "llm": { "default_provider": "gemini", "providers": { "gemini": { "provider_kind": "litellm", "model": "gemini/gemini-2.0-flash" } } } } ``` ```python provider = Provider.from_config("gemini") ``` The LiteLLM client does not scan OpenRath config on its own. If you also cloned the OpenRath repository, you can first run examples that do not depend on OpenSandbox or a live model: ```bash python example/02_session_lineage.py python example/06_mcp_tool.py python example/09_memory.py ``` When using OpenRath from PyPI in your own project, import it directly: ```python import os from rath import flow from rath.llm import Provider from rath.session import Session provider = Provider( api_key=os.environ["OPENAI_API_KEY"], base_url=os.environ.get("OPENAI_BASE_URL") or None, model=os.environ.get("OPENAI_DEFAULT_MODEL") or "gpt-5.5", ) agent = flow.Agent("Use tools when helpful.", provider=provider) user = Session.from_user_message("List files.").to("local", spec=".") out = agent(user) ``` (configure-memory)= ## Configure Memory The v1-compatible memory API included in OpenRath v2.0.0 provides local memory in the base install. The local backend is registered as `local`, uses public `memory://` URIs, stores data under `.openrath/memory/` by default, and can run lexical BM25 recall without any LLM key. The shortest path is: ```python from rath import flow with flow.Agent("Remember useful facts.", model="demo", memory="local") as agent: agent.remember_memory("The user writes Python.") hits = agent.recall_memory("preferred programming language") ``` Configure named local memory stores in `~/.openrath/config.json`: ```json { "version": 1, "memory": { "default_provider": "local-main", "providers": { "local-main": { "backend_kind": "local", "path": ".openrath/memory", "embedding_provider": "embed-main", "chat_provider": "chat-main" } } } } ``` | Field | Meaning | | --- | --- | | `backend_kind` | Currently `local` in config. OpenViking stores are opened explicitly or through adapter/environment settings. | | `path` | Local memory root. Relative paths are resolved from the current project. | | `embedding_provider` | Optional `llm.providers` entry used for embedding-ranked search. | | `chat_provider` | Optional `llm.providers` entry used by commit-time memory extraction. | Run the key-free memory example from a source checkout: ```bash python example/09_memory.py ``` (install-from-source-for-development)= ## Install from source for development This is the developer installation path. Use it to modify OpenRath source, run tests, build docs, or debug examples. ```bash git clone https://github.com/Rath-Team/OpenRath.git cd OpenRath uv sync --group dev --group docs ``` Without `uv`, use an editable install. This also works in an existing mamba/conda environment: ```bash pip install -e . pip install pytest ruff mypy sphinx myst-parser pydata-sphinx-theme ``` Development dependencies include: | Dependency group | Contents | | --- | --- | | runtime | `openai`, `anthropic`, `mcp`, `pydantic`. | | optional `litellm` | LiteLLM chat adapter and provider integrations. | | dev | `pytest`, `ruff`, `mypy`. | | docs | `sphinx`, `myst-parser`, `pydata-sphinx-theme`. | Configure credentials in your shell, CI secret store, or deployment environment. OpenRath does not load repository-local secret files. Run tests: ```bash bash scripts/run_openrath_test.sh ``` Build the docs: ```bash bash scripts/build_docs.sh ``` Or call Sphinx directly: ```bash uv run sphinx-build -M html docs/source docs/_build ``` In a mamba environment that already has the docs dependencies installed, the equivalent direct build is: ```bash mamba run -n rath-dev python -m sphinx -M html docs/source docs/_build ``` The generated output is under `docs/_build/html/`. (launch-and-connect-opensandbox)= ## Launch and connect OpenSandbox OpenSandbox is an optional backend. It is useful for workflows that need a container execution environment. OpenRath connects to it with `Session.to("opensandbox", spec=...)`; the default local backend does not require this step. The v1-compatible OpenSandbox backend included in v2.0.0 defaults to `opensandbox/code-interpreter:v1.1.0` with entrypoint `/opt/code-interpreter/code-interpreter.sh`. Override both through `BackendSandboxSpec` only when your deployment supplies another compatible image. ### Install the OpenSandbox extra When using PyPI: ```bash pip install "openrath[opensandbox]" ``` When using a source development environment: ```bash uv sync --extra opensandbox ``` This extra installs: | Package | Purpose | | --- | --- | | `opensandbox` | OpenSandbox Python SDK. | | `opensandbox-code-interpreter` | Code interpreter client. | | `opensandbox-server` | Starts the OpenSandbox API server locally. | ### Start the service Local development usually starts OpenSandbox with the repository script. The script checks Docker, syncs the optional dependency, generates `.sandbox.toml`, adds the current OpenRath project directory to the host bind allowlist, and starts `opensandbox-server`. On macOS with Colima, if `DOCKER_HOST` is unset and the Colima socket exists, the script exports `DOCKER_HOST=unix://${HOME}/.colima/default/docker.sock` automatically. macOS / Linux: ```bash bash scripts/launch_opensandbox.sh ``` Windows: ```bat scripts\launch_opensandbox.bat ``` The script uses the OpenSandbox Docker configuration example by default. Switch the packaged example with an environment variable: ```bash SANDBOX_INIT_EXAMPLE=docker bash scripts/launch_opensandbox.sh ``` Allowed values include `docker`, `docker-zh`, `k8s`, and `k8s-zh`. ### Check service status After the OpenSandbox server starts, first check that the control plane responds. `/health` is the unauthenticated health-check path for the OpenSandbox server. ```bash curl -fsS http://127.0.0.1:8080/health ``` If `curl` is not installed, use Python for the same check: ```bash python - <<'PY' import urllib.request with urllib.request.urlopen("http://127.0.0.1:8080/health", timeout=3) as resp: print(resp.status) print(resp.read().decode("utf-8", errors="replace")) PY ``` The health check only confirms that the OpenSandbox API server responds locally. The container runtime, workspace bind, and OpenRath client configuration still need to be verified with the later example. ### Connect OpenRath to OpenSandbox Set client variables in the environment where OpenRath runs: ```bash export OPEN_SANDBOX_DOMAIN=127.0.0.1:8080 export OPEN_SANDBOX_API_KEY= ``` If the server sets an API key, the server and client values must match: ```bash export OPENSANDBOX_SERVER_API_KEY=... export OPEN_SANDBOX_API_KEY=... ``` | Variable | Meaning | | --- | --- | | `OPEN_SANDBOX_DOMAIN` | OpenSandbox API server address. The local default is `127.0.0.1:8080`. | | `OPEN_SANDBOX_API_KEY` | API key used by the OpenRath client when requesting the server. | | `OPENSANDBOX_SERVER_API_KEY` | API key on the OpenSandbox server side. | | `RATH_OPENSANDBOX_STRICT_WORKSPACE_BIND` | When set to `1`, a failed host bind does not fall back to an empty workspace. | In the v1-compatible configuration surface included in v2.0.0, the backend `domain` is used for availability resolution and is not injected into the SDK connection; backend `api_key` also has no runtime consumer. Keep the environment variables above or configure the SDK through `~/.sandbox.toml` for an actual connection. ### Verify the backend After confirming that the server is listening locally, run the sandbox backend example: ```bash python example/03_sandbox_backend.py opensandbox ``` You can also bind directly in Python: ```python from rath.session import Session user = Session.from_user_message("List the workspace.") user = user.to("opensandbox", spec=".") ``` `spec="."` requests a bind from the current directory to `/workspace` inside the container. This host path must be visible to the machine running the OpenSandbox server and allowed by the storage allowlist in `.sandbox.toml`. The repository script automatically allowlists the current project directory. To bind other directories, manually add the matching prefix to `allowed_host_paths`. If the host bind is rejected, OpenRath retries with an empty workspace by default. Set `RATH_OPENSANDBOX_STRICT_WORKSPACE_BIND=1` to disable this fallback. ## Local sandbox path notes `Session.to("local", spec="...")` treats the string `spec` as `BackendSandboxSpec(working_dir=...)`. `LocalBackend.close(...)` only deletes temporary working directories that OpenRath created itself. User-supplied working directories are left on disk when the sandbox closes. (launch-and-connect-openviking)= ## Launch and connect OpenViking OpenViking is an optional memory backend. The base `local` memory backend does not require it. Install the extra: ```bash pip install "openrath[openviking]" ``` When developing from source, use the repository scripts: ```bash bash scripts/launch_openviking.sh bash scripts/check_openviking.sh ``` OpenViking exposes a richer external memory service. OpenRath keeps the public memory API on `memory://` URIs; the adapter translates to OpenViking's internal `viking://` boundary.