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

Use the v1-compatible façade published on PyPI

Install the v1-compatible package from PyPI

Route chat through LiteLLM providers

Install the LiteLLM extra

Modify OpenRath source, run tests, or build docs

Install from source for development

Use persistent memory

Configure Memory

Use a container sandbox backend

Launch and connect OpenSandbox

Use OpenViking memory

Launch and connect OpenViking

Install Stable v2.0.0 from the GitHub release#

Install the exact Stable 2.0.0 release wheel:

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:

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. For service deployments, follow the operations guide.

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.

pip install "openrath==1.3.0"

If you manage your project environment with uv:

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#

OpenRath v2.0.0 can route chat calls through LiteLLM when its optional extra is installed:

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".

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).

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:

{
  "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:

{
  "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:

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(...):

{
  "version": 1,
  "llm": {
    "default_provider": "gemini",
    "providers": {
      "gemini": {
        "provider_kind": "litellm",
        "model": "gemini/gemini-2.0-flash"
      }
    }
  }
}
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:

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:

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#

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:

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:

{
  "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:

python example/09_memory.py

Install from source for development#

This is the developer installation path. Use it to modify OpenRath source, run tests, build docs, or debug examples.

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:

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 scripts/run_openrath_test.sh

Build the docs:

bash scripts/build_docs.sh

Or call Sphinx directly:

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:

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#

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:

pip install "openrath[opensandbox]"

When using a source development environment:

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 scripts/launch_opensandbox.sh

Windows:

scripts\launch_opensandbox.bat

The script uses the OpenSandbox Docker configuration example by default. Switch the packaged example with an environment variable:

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.

curl -fsS http://127.0.0.1:8080/health

If curl is not installed, use Python for the same check:

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:

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:

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:

python example/03_sandbox_backend.py opensandbox

You can also bind directly in 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#

OpenViking is an optional memory backend. The base local memory backend does not require it.

Install the extra:

pip install "openrath[openviking]"

When developing from source, use the repository scripts:

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.