Releases: Rath-Team/OpenRath
Release list
OpenRath v2.0.0
OpenRath v2.0.0
OpenRath 2.0.0 将框架从进程内 Agent 工作流扩展为可部署的持久化多 Agent Runtime 与 Agent Server。本版本引入可恢复执行、受治理的副作用、人工中断、安全与租户边界,以及面向 PostgreSQL、Redis、S3 和 OpenTelemetry 的生产部署能力。
核心特性
持久化 Runtime
- 显式编译模型 —
@step、@router编译为规范化执行计划与不可变 revision。 - 可恢复 Run — Events、Checkpoints、Interrupts、取消、截止时间、重试、租约 fencing 与队列恢复形成完整生命周期。
- 受控副作用 — Effect Ledger 保存结果和幂等键;无法安全判定的非幂等操作进入
NEEDS_REVIEW,避免盲目重放。 - 人工决策 — durable Interrupt 可暂停 Run 等待审批或输入,并从持久化状态继续。
Agent Server 与安全边界
- HTTP + SSE API — 提供租户/项目作用域下的 Run、Event、Artifact、Revision 与 Evaluation 资源。
- 显式授权 — Token、Action Grant、Tenant/Project Scope、Policy、Secret Reference、Trust Label 与 Audit 各自保持独立边界。
- 受治理适配器 — Provider、Tool/MCP、Sandbox 与 Memory 通过统一上下文和策略执行。
- 防护默认值 — 有界请求、资源限制、安全响应头、结构化审计与敏感信息脱敏。
生产存储与运维
- PostgreSQL 作为持久化事实来源,支持 additive migrations、租约与恢复。
- Redis 可选用于低延迟信号传递,不替代持久化状态。
- S3 兼容 Artifact Store 保存输入、输出与运行制品。
- 可观测性与部署 — OpenTelemetry、健康检查、API/worker 拆分、Docker Compose 与 Kubernetes 参考配置。
- 评测能力 — Evaluation 资源、运行结果和 Artifact 可纳入同一审计链路。
兼容性与迁移
- Python v1 facade 在文档约定的维护窗口内继续支持。
- v1 JSONL Sessions 可导入为不可恢复的历史 Runs。
- Agent Server HTTP 接口当前标记为 Beta。
- 切换生产流量前,请备份 PostgreSQL 与 Artifact,执行迁移 dry-run,并完成恢复验证。
- 支持 Python 3.10–3.13。
迁移与运维说明见 deploy/docs/migration-v2.md、deploy/docs/operations-v2.md、deploy/docs/api-governance-v2.md 和 deploy/docs/known-limitations-v2.md。
安装
pip install --upgrade openrath
# Agent Server
pip install --upgrade "openrath[server]"
# 生产存储与可观测性
pip install --upgrade "openrath[postgres,redis,s3,otel]"
# 可选适配器
pip install --upgrade "openrath[litellm,opensandbox,openviking]"项目与资源
- OpenRath 主项目: https://github.com/Rath-Team/OpenRath
- OpenRath Docs: https://github.com/Rath-Team/OpenRath-Docs
- OpenRath Example: https://github.com/Rath-Team/OpenRath-Example
- PyPI: https://pypi.org/project/openrath/2.0.0/
- 项目主页: https://openrath.com/
- 文档主页: https://docs.openrath.com/stable/
- Colab Example: https://colab.research.google.com/github/Rath-Team/OpenRath-Example/blob/main
- GHCR 镜像:
ghcr.io/rath-team/openrath:2.0.0 - GHCR 包页面: https://github.com/orgs/Rath-Team/packages/container/package/openrath
完整变更: v1.3.0...v2.0.0
OpenRath v2.0.0
OpenRath 2.0.0 expands the framework from in-process agent workflows into a deployable durable multi-agent Runtime and Agent Server. It adds resumable execution, governed side effects, human interrupts, security and tenancy boundaries, and production-oriented PostgreSQL, Redis, S3, and OpenTelemetry integration.
Major Features
Durable Runtime
- Explicit compilation —
@stepand@routercompile into canonical execution plans and immutable revisions. - Resumable Runs — Events, Checkpoints, Interrupts, cancellation, deadlines, retries, lease fencing, and queue recovery form a complete lifecycle.
- Governed side effects — the Effect Ledger records outcomes and idempotency keys; ambiguous non-idempotent operations enter
NEEDS_REVIEWinstead of being replayed blindly. - Human decisions — durable Interrupts pause a Run for approval or input and resume from persisted state.
Agent Server and security boundaries
- HTTP + SSE APIs — tenant/project-scoped Run, Event, Artifact, Revision, and Evaluation resources.
- Explicit authorization — tokens, action grants, tenant/project scope, policy, secret references, trust labels, and audit remain separate boundaries.
- Governed adapters — Provider, Tool/MCP, Sandbox, and Memory execute through shared context and policy controls.
- Defensive defaults — bounded requests, resource limits, security headers, structured auditing, and secret redaction.
Production storage and operations
- PostgreSQL is the durable source of truth, with additive migrations, leases, and recovery.
- Redis optionally accelerates signaling without replacing durable state.
- S3-compatible Artifact Store persists inputs, outputs, and run artifacts.
- Observability and deployment — OpenTelemetry, health checks, split API/worker operation, Docker Compose, and Kubernetes references.
- Evaluation resources — evaluation runs, results, and artifacts join the same auditable lifecycle.
Compatibility and migration
- The Python v1 facade remains supported for the documented maintenance window.
- v1 JSONL Sessions can be imported as non-resumable historical Runs.
- The Agent Server HTTP surface is currently marked Beta.
- Before switching production traffic, back up PostgreSQL and artifacts, run the migration dry-run, and verify restoration.
- Python 3.10–3.13 is supported.
See deploy/docs/migration-v2.md, deploy/docs/operations-v2.md, deploy/docs/api-governance-v2.md, and deploy/docs/known-limitations-v2.md.
Install
pip install --upgrade openrath
# Agent Server
pip install --upgrade "openrath[server]"
# production storage and observability
pip install --upgrade "openrath[postgres,redis,s3,otel]"
# optional adapters
pip install --upgrade "openrath[litellm,opensandbox,openviking]"Project resources
- OpenRath repository: https://github.com/Rath-Team/OpenRath
- OpenRath Docs: https://github.com/Rath-Team/OpenRath-Docs
- OpenRath Example: https://github.com/Rath-Team/OpenRath-Example
- PyPI: https://pypi.org/project/openrath/2.0.0/
- Project homepage: https://openrath.com/
- Documentation: https://docs.openrath.com/stable/
- Colab examples: https://colab.research.google.com/github/Rath-Team/OpenRath-Example/blob/main
- GHCR image:
ghcr.io/rath-team/openrath:2.0.0 - GHCR package: https://github.com/orgs/Rath-Team/packages/container/package/openrath
Full changelog: v1.3.0...v2.0.0
OpenRath 2.0.0rc1
OpenRath v2.0.0rc1
v2.0.0rc1 is the first installable release candidate for OpenRath's durable
Runtime and Agent Server. It is published for integration, compatibility, and
operator validation. It is not GA approval and is not deployed by this
release.
Highlights
- Explicit
@step/@routercompilation with canonical plans and revision
identity. - Durable Run, Event, Checkpoint, Interrupt, lease/fencing, cancellation,
deadline, retry, and effect-reconciliation semantics. - PostgreSQL production storage, optional Redis signaling, and
S3-compatible artifact storage. - Tenant/project-scoped Agent Server HTTP/SSE APIs with explicit action grants,
bounded queues/pages/bodies, security headers, and redacted structured audit. - Governed Provider, Tool/MCP, Sandbox, and Memory adapter boundaries.
- OpenTelemetry integration, datasets/experiments/feedback, migration tooling,
Compose/Kubernetes references, SBOM, and security gates.
Stability
- The v1 Python façade remains supported during the RC.
- The Agent Server
/v1HTTP surface remains Beta. - v1 JSONL imports are historical and cannot resume active Runs.
- See
deploy/docs/known-limitations-v2.md,
deploy/docs/threat-model-v2.md, anddeploy/docs/migration-v2.md.
RC evidence boundary
This prerelease includes source/package/container CI and local/available
backend evidence. The following remain blocking before final v2.0.0 GA:
- Approved live LLM/provider lifecycle.
- Approved live OpenViking lifecycle.
- Target-like single-host and split-profile capacity results.
- One-to-four worker scaling efficiency validation.
- Eight-hour target-like soak.
- Target-cluster backup/restore, dependency-failure, rollout, and rollback
drills. - Final API stability, v1 maintenance-window, and GA owner approval.
Do not represent this RC as production certification.
Distribution
- Wheel and source distribution are attached to this GitHub prerelease.
- The OCI image is published to GHCR and identified by the digest in the
attached evidence manifest. - This RC does not publish to PyPI and does not deploy to a shared environment.
v1.3.0
OpenRath v1.3.0
在 v1.2.2 的 LiteLLM 接入与运行时健壮性之上,v1.3.0 把重心放在基础层加固与 Workflow 静态编译上。持久化写入、配置/凭据分离、环境变量解析、Provider 重绑定与 Workflow.compile() 构成一条连贯的「先 inspect、再 validate、再运行」路径;OpenSandbox 适配层与 CI 也去掉了对 --reruns 的依赖,用更长超时与有针对性的重试消除 flaky。没有 intentional 破坏性改动:内联 api_key 仍可加载并在下次保存时迁移到 credentials.json,compile() 为纯 opt-in。
核心特性
持久化与布局(atomic writes + manifest + GC)
rath.persistence.atomic—atomic_write_text/atomic_write_json:临时文件 +os.replace、路径级锁、Windows sharing-violation 重试;修复 Windows 并发保存 config 时的PermissionError。- Registry 原子化 — backend 远程沙箱 registry 与 local memory adapter 的 JSON 写入改为 atomic(此前为裸
write_text)。 rath.persistence.manifest— 根目录.openrath/manifest.json记录 layout 与各 plane 的 schema version;加载时拒绝比当前代码更新的 layout。rath.persistence.gc(older_than=..., dry_run=True)— 跨 sessions、sandboxes、memory stores 与 memory commits archive 的统一 retention/GC(此前 commits archive 无界增长)。
配置与环境(credentials 分离 + EnvSpec registry)
- Secrets 分离 —
config.json保留路由/presets;api_key等 secret 外置到 0600 的credentials.json;内联 key 仍可加载,保存时自动迁移。 backend配置段 — 新增backendsection,OpenSandbox 的 domain/flag 经 env → config →~/.sandbox.toml解析。rath.config.envEnvSpec registry — sync/async LLM、embedding、VLM、OpenSandbox 统一经 central registry 解析,替代散落的os.environ.get;embedding/VLM 补齐 config fallback。env_reference_markdown()— 从 registry 生成 env 变量参考表(API + 测试覆盖)。
Provider 作为可 .to() 切换的组件
AgentParam.to()/Session.to()/Workflow.to()— type-dispatched 重绑定 Provider;Session.to("local")等 bare string 仍表示 sandbox backend 名。- Loop provider 回退 —
run_session_loop/run_session_compress/select_session在agent_provider=None时回退到 session-bound provider;Agent 上的 provider 优先;bound provider 永不序列化。 chat_client_for缓存 — 按 provider HTTP identity 缓存已构造的 chat client(explicit-key only)。
Workflow.compile()(静态 manifest + 离线 validate + 生命周期)
Workflow.compile()→CompiledWorkflow— 静态遍历 module tree(嵌套Workflow/Agent像torch.nn.Module一样注册),构建ResourceManifest;Selector记为 dynamic 节点。CompiledWorkflow.validate()— 离线 pre-flight,不发起模型请求。with wf.compile() as cw:— 按 manifest acquire bound memory stores,exit 时逆序 release。example/12_compile.py— 无需 API key 的可运行示例;example ladder README 与 smoke tests 已同步。
修复
- OpenSandbox 冷启动 create 超时 — 120s API 预算 + 最多 3 次 transient 重试;默认 code-interpreter 镜像升至 v1.1.0(v1.0.2 已退役)。
- OpenSandbox stdout/exit_code 竞态 — 仅对含
print(的探针命令在空 stdout 时重跑一次,避免 mutating 命令被重复执行。 code.run挂死 — 默认 90s 超时 + 超时重试一次。- OpenSandbox CI flaky — 去掉
--reruns 2;动态预拉_DEFAULT_IMAGE+ warm-up script;42 passed / 4 skipped,无 RRF。
其他改进
- 依赖 —
opensandbox/openvikingextras 升级到最新兼容版本。 - 示例 — 新增
12_compile.py;offline smoke tests 覆盖 examples 02/06/12。 - CI — Lint、Test Fast、Build、OpenSandbox、OpenViking 全部通过。
安装
pip install --upgrade openrath
# 可选:多供应商接入
pip install --upgrade "openrath[litellm]"
# 可选 memory backend
pip install --upgrade "openrath[openviking]"
# 可选 sandbox backend
pip install --upgrade "openrath[opensandbox]"兼容性
- 向后兼容:内联
api_key仍可加载;compile()、credentials.json、manifest/GC 均为增量能力;Session.to("backend")语义不变。 - OpenSandbox 默认镜像 v1.0.2 → v1.1.0:若本地/CI 仍 pin 旧镜像需手动更新。
- 支持 Python 3.10 – 3.13。
完整变更: v1.2.2...v1.3.0
OpenRath v1.3.0
Building on v1.2.2's LiteLLM reach and runtime hardening, v1.3.0 focuses on foundation-layer hardening and Workflow static compilation. Atomic persistence, config/credential split, centralized env resolution, Provider rebinding via .to(), and Workflow.compile() form a coherent inspect → validate → run path; the OpenSandbox adapter and CI no longer rely on --reruns, using longer timeouts and targeted retries instead. No intentional breaking changes: inline api_key values still load and migrate to credentials.json on the next save; compile() is purely opt-in.
Major Features
Persistence & layout (atomic writes + manifest + GC)
rath.persistence.atomic—atomic_write_text/atomic_write_json: temp file +os.replace, path-keyed lock, Windows sharing-violation retry; fixes concurrent config savePermissionErroron Windows.- Atomic registries — backend remote-sandbox registry and local memory adapter JSON writes now go through atomic helpers (previously bare
write_text). rath.persistence.manifest— root.openrath/manifest.jsonrecords layout and per-plane schema versions; refuses a layout newer than the running code on load.rath.persistence.gc(older_than=..., dry_run=True)— unified retention/GC across sessions, sandboxes, memory stores, and the previously unbounded memory commits archive.
Config & environment (credential split + EnvSpec registry)
- Secret split —
config.jsonkeeps routing/presets; secrets such asapi_keymove to a 0600credentials.json; inline keys still load and migrate on save. backendconfig section — newbackendsection; OpenSandbox domain/flag resolves env → config →~/.sandbox.toml.rath.config.envEnvSpec registry — sync/async LLM, embedding, VLM, and OpenSandbox all resolve through one central registry instead of scatteredos.environ.get; embedding/VLM gain config fallback.env_reference_markdown()— generates an env-var reference table from the registry (API + test coverage).
Provider as a .to()-switchable component
AgentParam.to()/Session.to()/Workflow.to()— type-dispatched Provider rebinding; bare strings onSession.to("local")still mean sandbox backend names.- Loop provider fallback —
run_session_loop/run_session_compress/select_sessionfall back to a session-bound provider whenagent_provider=None; an Agent's provider always wins; bound providers are never serialized. chat_client_forcache — caches constructed chat clients by provider HTTP identity (explicit-key only).
Workflow.compile() (static manifest + offline validate + lifecycle)
Workflow.compile()→CompiledWorkflow— static pass over the module tree (nestedWorkflow/Agentregister liketorch.nn.Module) building aResourceManifest;Selectoris recorded as a dynamic node.CompiledWorkflow.validate()— offline pre-flight with no model calls.with wf.compile() as cw:— acquires bound memory stores from the manifest and releases in reverse order on exit.example/12_compile.py— runnable demo with no API key; example ladder README and smoke tests updated.
Fixes
- OpenSandbox cold-start create timeout — 120s API budget + up to 3 transient retries; default code-interpreter image bumped to v1.1.0 (v1.0.2 retired).
- OpenSandbox stdout/exit_code race — retries empty stdout only for
print(probe commands, avoiding double execution of mutating commands. code.runhang — default 90s timeout + one retry on timeout.- OpenSandbox CI flakiness — removed
--reruns 2; dynamic pre-pull of_DEFAULT_IMAGE+ warm-up script; 42 passed / 4 skipped, no RRF.
Other Improvements
- Dependencies —
opensandbox/openvikingextras upgraded to latest compatible releases. - Examples — new
12_compile.py; offline smoke tests for examples 02/06/12. - CI — Lint, Test Fast, Build, OpenSandbox, and OpenViking all pass.
Install
pip install --upgrade openrath
# optional: multi-provider reach
pip install --upgrade "openrath[litellm]"
# optional memory backend
pip install --upgrade "openrath[openviking]"
# optional sandbox backend
pip install --upgrade "openrath[opensandbox]"Compatibility
- Backward compatible: inline
api_keystill loads;compile(),credentials.json, manifest/GC are all additive;Session.to("backend")semantics unchanged. - OpenSandbox default image v1.0.2 → v1.1.0: update local/CI pins if you still target the old image.
- Python 3.10 – 3.13 supported.
Full changelog: v1.2.2...v1.3.0
v1.2.2
OpenRath v1.2.2
延续 v1.2.1 的动态工作流之后,v1.2.2 把重心放在接入面与运行时健壮性上。核心新特性是 litellm provider:通过一个薄适配器把 OpenRath 接到 100+ 模型供应商(Gemini、Bedrock、Azure、Ollama、Groq……),不必再在内置 Provider / chat_client_for 之外手工接线。围绕它,本版补齐了 Session 的常用取值与序列协议,并集中修复了一批并发竞态、内存增长与持久化 round-trip 的问题。没有破坏性改动,可从 v1.2.1 直接升级。
核心特性
LiteLLM provider(一个适配器接入 100+ 模型)
新增 provider_kind="litellm",经 LiteLLM 路由到上百家供应商。RathLiteLLMChatClient 复用 OpenRath 既有的 OpenAI 归一化与 kwargs 构造逻辑(LiteLLM 返回 OpenAI 兼容响应),因此适配层很薄,并且不改动既有 provider 分派,也不引入新的运行时依赖:
RathLiteLLMChatClient— 实现complete()与complete_stream(),经register_chat_client("litellm", ...)自动注册,chat_client_for()在provider_kind="litellm"时分派。- 可选依赖,零侵入 —
pip install "openrath[litellm]";未安装时懒加载回退,对现有安装毫无影响,provider_kind未设置时仍默认openai。 - 凭据解析顺序 — 先
Provider.api_key/Provider.base_url,再LITELLM_API_KEY/LITELLM_API_BASE环境变量,最后交给 LiteLLM 自身的按供应商解析。 drop_params=True(默认) — 供应商不支持的 kwargs 被静默丢弃,避免因参数差异报错。- 重试 — 复用 OpenRath 的
retry_with_backoff,对RateLimitError/Timeout/APIConnectionError/ServiceUnavailableError/InternalServerError退避重试。
快速上手:
from rath.llm import Provider, chat_client_for
provider = Provider(
provider_kind="litellm",
model="gemini/gemini-2.0-flash", # 或 anthropic/…、bedrock/…、ollama/… 等
api_key="sk-...", # 也可留空,交由 LiteLLM 从环境变量解析
)
client = chat_client_for(provider)
resp = client.complete(req)或经配置:
llm:
provider_kind: litellm
model: anthropic/claude-sonnet-4-20250514
# api_key 由 LiteLLM 从供应商专属环境变量解析Session 易用性
Session.text()— 一行取回本次运行的最终回答:从末尾回溯,返回最近一条带文本的 assistant 消息,跳过纯 tool-call 轮次,无文本时返回None。此前调用方需手动遍历 transcript;example/11_dynamic_selector.py也因调用了这个不存在的方法而崩溃,现已修复。ChunkTable序列协议 — 新增__len__/__getitem__(含切片)/__iter__,ChunkTable现可直接len()、索引、切片与迭代;Session.__repr__也带上了短 session id,便于日志区分。
修复
- 文件系统同路径竞态 — 内置文件工具统一到单一
("fs", path)资源键;同一路径的读/写/list 现按 transcript 顺序串行,不同路径仍并行,消除读到写一半中间态的问题。 - 压缩截断静默丢历史 —
run_session_compress在finish_reason="length"(摘要被输出上限截断)时明确报错并提示加大输出预算,而非把残缺摘要当作权威替换。 - 懒开沙箱重复打开 —
_ensure_sandbox改用双检锁,避免两个首用调用各开一个沙箱、第二个赋值挤掉第一个而留下永不释放的孤儿句柄。 - Session 注册表内存增长 —
SessionRegistry改用WeakValueDictionary,无外部引用的 session 可被回收,长跑进程不再无界增长。 - 持久化空集合 round-trip —
spec_from_jsonable用is not None(而非真值判断)重建entrypoint/env,空()/{}现能在 persist/reload 后存活,与序列化端对齐。
其他改进
- 文档 — README_zh 全面对齐英文版结构(logo、arXiv badge、示意图、PyTorch 对照表、示例阶梯表);英文 README 补充 arXiv badge。
- CI / 打包 — 找回 v1.2.0 准备阶段误删的 opensandbox
--reruns,抵御 server 偶发的 stdout/exit_code 捕获竞态;延长 opensandbox code-run 测试超时以适配冷启动;sdist 收敛到源码必需文件。 - CI — Lint、Test Fast、Build、OpenSandbox 全部通过。
安装
pip install --upgrade openrath
# 可选:多供应商接入(Gemini/Bedrock/Azure/Ollama/Groq…)
pip install --upgrade "openrath[litellm]"
# 可选 memory backend
pip install --upgrade "openrath[openviking]"
# 可选 sandbox backend
pip install --upgrade "openrath[opensandbox]"兼容性
- 完全向后兼容:
provider_kind未设置时仍默认openai,litellm为纯新增;所有新符号(Session.text()、ChunkTable序列方法)均为增量,不影响既有调用点。 litellm为可选依赖,未安装时懒加载静默回退,对现有环境无影响。- 支持 Python 3.10 – 3.13。
完整变更: v1.2.1...v1.2.2
OpenRath v1.2.2
Following v1.2.1's dynamic workflows, v1.2.2 focuses on provider reach and runtime robustness. The headline feature is the litellm provider: a thin adapter that connects OpenRath to 100+ model providers (Gemini, Bedrock, Azure, Ollama, Groq, …) without hand-wiring a client outside the built-in Provider / chat_client_for dispatch. Around it, this release rounds out Session's common accessors and sequence protocol, and lands a batch of fixes for concurrency races, unbounded memory growth, and a lossy persistence round-trip. No breaking changes; upgrade straight from v1.2.1.
Major Features
LiteLLM provider (one adapter, 100+ models)
A new provider_kind="litellm" routes through LiteLLM to hundreds of providers. RathLiteLLMChatClient reuses OpenRath's existing OpenAI normalization and kwargs-building helpers (LiteLLM returns OpenAI-compatible responses), so the adapter stays thin and introduces no change to existing provider dispatch and no new runtime dependency:
RathLiteLLMChatClient— implementscomplete()andcomplete_stream(), auto-registered viaregister_chat_client("litellm", ...)and dispatched bychat_client_for()whenprovider_kind="litellm".- Optional dep, zero impact —
pip install "openrath[litellm]"; a lazy import falls back cleanly when it isn't installed, andprovider_kindstill defaults toopenaiwhen unset. - Credential resolution order —
Provider.api_key/Provider.base_urlfirst, then theLITELLM_API_KEY/LITELLM_API_BASEenv vars, then LiteLLM's own provider-specific resolution. drop_params=True(default) — provider-unsupported kwargs are silently dropped instead of raising on parameter mismatches.- Retries — reuses OpenRath's
retry_with_backoffforRateLimitError/Timeout/APIConnectionError/ServiceUnavailableError/InternalServerError.
Quick start:
from rath.llm import Provider, chat_client_for
provider = Provider(
provider_kind="litellm",
model="gemini/gemini-2.0-flash", # or anthropic/…, bedrock/…, ollama/…, etc.
api_key="sk-...", # or leave unset and let LiteLLM read the env var
)
client = chat_client_for(provider)
resp = client.complete(req)Or via config:
llm:
provider_kind: litellm
model: anthropic/claude-sonnet-4-20250514
# api_key resolved by LiteLLM from the provider-specific env varSession ergonomics
Session.text()— a one-call accessor for the run's final answer: walks the transcript from the end and returns the most recent assistant message carrying text, skipping pure tool-call turns, orNonewhen there is none yet. Callers previously had to walk the transcript by hand;example/11_dynamic_selector.pyalso crashed because it called this then-missing method, and now runs.ChunkTablesequence protocol — new__len__/__getitem__(with slicing) /__iter__, so aChunkTablesupportslen(), indexing, slicing, and iteration directly;Session.__repr__now carries a short session id for easier log disambiguation.
Fixes
- Same-path filesystem race — the built-in file tools collapse onto a single
("fs", path)resource key; reads/writes/lists on the same path now run in transcript order while distinct paths still fan out in parallel, removing the read-during-write intermediate-state bug. - Truncated compression summaries —
run_session_compressraises a clear error onfinish_reason="length"(a summary cut off by the output limit) telling the caller to retry with a larger output budget, instead of promoting a truncated summary as the canonical replacement. - Lazy sandbox double-open —
_ensure_sandboxnow uses double-checked locking, preventing two first-use calls from each opening a sandbox and orphaning the first acquired handle. - Session registry memory growth —
SessionRegistryis backed by aWeakValueDictionary, so an unreferenced session is collected and a long-running process no longer grows without bound. - Empty-collection persistence round-trip —
spec_from_jsonablerebuildsentrypoint/envwithis not None(not truthiness), so empty()/{}survive a persist/reload cycle, mirroring the serializer.
Other Improvements
- Docs — README_zh is fully aligned with the English structure (logo, arXiv badge, diagrams, PyTorch mapping table, example ladder); the English README gains an arXiv badge.
- CI / packaging — restored the opensandbox
--rerunsaccidentally dropped during v1.2.0 prep, riding out the server's occasional stdout/exit_code capture race; extended the opensandbox code-run test timeout for cold starts; trimmed the sdist to source essentials. - CI — Lint, Test Fast, Build, and OpenSandbox all pass.
Install
pip install --upgrade openrath
# optional: multi-provider reach (Gemini/Bedrock/Azure/Ollama/Groq…)
pip install --upgrade "openrath[litellm]"
# optional memory backend
pip install --upgrade "openrath[openviking]"
# optional sandbox backend
pip install --upgrade "openrath[opensandbox]"Compatibility
- Fully backward compatible:
provider_kindstill defaults toopenaiwhen unset,litellmis purely additive, and all new symbols (Session.text(), theChunkTablesequence methods) are additive and leave existing call sites unaffected. litellmis an optional dependency; when it isn't installed, a lazy import falls back silently with no impact on existing environments.- Python 3.10 – 3.13 supported.
Full changelog: v1.2.1...v1.2.2
v1.2.1
OpenRath v1.2.1
在 v1.2.0 的 Memory 平面与内部 Async 运行时之上,v1.2.1 把控制流带进了 Workflow。此前 Workflow 里下一步跑哪个 Agent 必须在写代码时就定好;现在新增的动态工作流让这个选择交由 LLM 在运行时做出,而 if / while 这类分支与循环仍用普通 Python 表达。Selector 负责判断该走哪条路,你的代码负责分派——没有图引擎,也没有 DSL。OpenRath 由此从「可组合的多 Agent 框架」进一步走向运行时可动态路由的多 Agent 编排。
核心特性
动态工作流(LLM 路由)
围绕 Selector 新增了一套动态控制流原语。它们都沿用既有模式——Selector 仿照 Compressor,select_session 仿照 run_session_compress——并且不引入 system tool、registry,也不改动 session graph:
flow.Selector— 与Agent/Compressor同级的内置 Workflow,本质是一个由 LLM 驱动的路由器。调用Selector.forward(session, *workflows)时,它把路由说明、当前 session、以及各候选 Workflow 的description组成的带编号菜单合并为一次 LLM 调用,再返回被选中的下一个 Workflow。动态多 Agent 控制流由此可以用普通 Python 写出来。flow.EmptyWorkflow— 一个空操作 Workflow,forward会原样返回输入的 session。当没有合适候选、下标越界或根本没有候选时,Selector会返回它而非None。这样调用方既能无条件分派(session = result(session)是安全的空操作),也能通过isinstance(result, flow.EmptyWorkflow)判断任务是否结束。Workflow.description— 新增字段(默认""),让每个 Workflow 都能附带一句自我描述;Agent与Compressor均支持。这正是Selector路由时所依据的文本。session.select_session—Selector底层的路由原语,用一次 LLM 调用完成选择。如果想自己拼装控制流,可以直接使用它。
快速上手:python example/11_dynamic_selector.py,演示 if 分支与 while 循环两种用法。
from rath import flow
selector = flow.Selector(provider)
triage = flow.Agent("处理账单问题。", provider, description="账单、发票、退款、支付方式")
tech = flow.Agent("解决技术问题。", provider, description="安装、报错、配置、故障排查")
wrapup = flow.Agent("收尾并总结。", provider, description="收尾并给出最终总结")
# 持续路由,直到 Selector 返回 EmptyWorkflow(表示任务结束)
while not isinstance(
nxt := selector.forward(session, triage, tech, wrapup), flow.EmptyWorkflow
):
session = nxt(session)其他改进
- 示例 — 新增
example/11_dynamic_selector.py,演示动态多 Agent 场景下的if与while控制。 - 文档 — 新增用户指南
docs/source/user_guide/dynamic_workflow.md,并在workflow_agent.md/main_components.md中交叉引用;README 与 README_zh 补充了「动态控制流」章节,PyTorch 对照表中也新增了Selector一行。 - CI — Lint、Test Fast、Build、OpenViking、OpenSandbox 全部通过。
安装
pip install --upgrade openrath
# 可选 memory backend
pip install --upgrade "openrath[openviking]"
# 可选 sandbox backend
pip install --upgrade "openrath[opensandbox]"兼容性
- 完全向后兼容:
Workflow.description默认为"",所有新增符号都是增量的,现有Agent/Compressor/Workflow调用点不受影响。 Selector.forward(session, *workflows)返回的是Workflow而非Session,刻意偏离了基类forward(session) -> Session的约定——因为它是一个路由决策组件,而非 session 变换器;任务结束以返回EmptyWorkflow表示。- 支持 Python 3.10 – 3.13。
完整变更: v1.2.0...v1.2.1
OpenRath v1.2.1
Building on v1.2.0's memory plane and internal async runtime, v1.2.1 brings control flow into the Workflow layer. Until now, which agent runs next had to be decided when you wrote the code; the new dynamic workflow lets an LLM make that choice at runtime, while branching and loops stay plain Python if / while. Selector decides which path to take and your code does the dispatch—no graph engine, no DSL. With it, OpenRath moves from a composable multi-agent framework toward one with runtime dynamic routing.
Major Features
Dynamic Workflows (LLM-routed control flow)
A set of dynamic-control-flow primitives built around Selector. They follow existing patterns—Selector mirrors Compressor, select_session mirrors run_session_compress—and introduce no system tool, no registry, and no change to the session graph:
flow.Selector— a built-in Workflow, sibling toAgent/Compressor, that acts as an LLM-backed router. CallingSelector.forward(session, *workflows)merges the routing instructions, the current session, and a numbered menu of each candidate'sdescriptioninto a single LLM call, then returns the next workflow to run. Dynamic multi-agent control flow becomes expressible in ordinary Python.flow.EmptyWorkflow— a no-op Workflow whoseforwardreturns the input session unchanged. When no candidate fits, the index is out of range, or there are no candidates at all,Selectorreturns this instead ofNone. Callers can then dispatch unconditionally (session = result(session)is a safe no-op) and checkisinstance(result, flow.EmptyWorkflow)to tell when the task is done.Workflow.description— a new field (default"") that lets every Workflow carry a one-line self-description; supported on bothAgentandCompressor. This is the textSelectorroutes on.session.select_session— the routing primitive beneathSelector, making the choice in a single LLM call. Use it directly if you want to assemble your own control flow.
Quick start: python example/11_dynamic_selector.py, which demonstrates both the if and while patterns.
from rath import flow
selector = flow.Selector(provider)
triage = flow.Agent("Answer billing questions.", provider,
description="Billing, invoices, refunds, payment methods")
tech = flow.Agent("Solve technical problems.", provider,
description="Installation, errors, configuration, troubleshooting")
wrapup = flow.Agent("Wrap up and summarize.", provider,
description="Wrap up and produce a final summary")
# keep routing until Selector returns an EmptyWorkflow (the task is done)
while not isinstance(
nxt := selector.forward(session, triage, tech, wrapup), flow.EmptyWorkflow
):
session = nxt(session)Other Improvements
- Example — new
example/11_dynamic_selector.pyshowingifandwhilecontrol flow in a dynamic multi-agent setting. - Docs — new user guide
docs/source/user_guide/dynamic_workflow.md, cross-referenced fromworkflow_agent.md/main_components.md; README and README_zh gain a "dynamic control flow" section, and the PyTorch mapping table gains aSelectorrow. - CI — Lint, Test Fast, Build, OpenViking, and OpenSandbox all pass.
Install
pip install --upgrade openrath
# optional memory backend
pip install --upgrade "openrath[openviking]"
# optional sandbox backend
pip install --upgrade "openrath[opensandbox]"Compatibility
- Fully backward compatible:
Workflow.descriptiondefaults to"", all new symbols are additive, and existingAgent/Compressor/Workflowcall sites are unaffected. Selector.forward(session, *workflows)returns aWorkflowrather than aSession, deliberately departing from the baseforward(session) -> Sessioncontract—it is a routing-decision component, not a session transformer, and signals completion by returning anEmptyWorkflow.- Python 3.10 – 3.13 supported.
Full changelog: v1.2.0...v1.2.1
v1.2.0
OpenRath v1.2.0
在 v1.1.0 的 Session 运行时、沙箱后端与持久化基础上,v1.2.0 引入完整的 Memory 平面 与 内部 Async 运行时,并统一 Session / Sandbox 生命周期。OpenRath 从「多 Session 编排框架」进一步走向 Multi-Agent × Multi-Session × 可持久记忆 的运行时。
核心特性
Memory 平面
新增与 rath.backend 对称的 rath.memory 模块,Agent 记忆成为一等公民:
- 默认 Local Memory Backend —
pip install openrath即可使用,零额外依赖;支持memory://URI、BM25 词法检索、可选 embedding 排序、Resource ingest,以及 Commit 时的 LLM 记忆提取。 - OpenViking Backend(可选) —
pip install "openrath[openviking]"接入 OpenViking;公开 API 统一为memory://,adapter 边界自动与viking://互转。 - Agent 记忆 API —
flow.Agent(memory="local")绑定 store,提供remember_memory()/recall_memory()/commit_memory();forward时可自动 recall 注入,并可选commit_on_forward。 - 配置驱动 —
~/.openrath/config.json新增memorysection,可命名多个 local store preset。
快速上手:python example/09_memory.py(remember / recall 无需 API key)。
内部 Async 运行时
引入 PyTorch 风格的私有 rath._async 运行时。对外 API 保持完全同步,async 能力在内部透明生效:
- Lazy Session —
run_session_loop()立即返回 Session;读取chunk_table/cumulative_usage时隐式同步,lineage 属性仍 eager 可读。 - 并行工具调度 — 按
resource_key分组并行执行(如不同文件的 fs:write),同 key 内串行(如 shell exec),兼顾吞吐与安全。 - WAL 持久化 — Session JSONL 写入
.__partial__,crash 可检测;异步 writer 不阻塞 runtime loop。 - Benchmark / Stress — 新增
tests/bench/与scripts/stress.py用于并发压测。
重要优化
Session 与 Sandbox 生命周期统一
BackendSandboxacquire/release 加锁保护;refcount 归零时在锁外 close,消除竞态。backend.get(name)返回进程级单例,refcount 与 per-backend 缓存在跨 Session 间保持一致。Session.create()合并 leaf-user / leaf-system / empty 构造路径,lineage stamping 统一。Session.merge语义明确 — 始终保留self.sandbox;跨 sandbox merge 不再 raise。- Loop 性能 — 每轮 assistant+tools 只 sync 一次
chunk_table,修复 O(n²) 增长。 - OpenSandbox resume —
PersistedSession.to_resumable_pair走 reattach 而非新开容器。
其他改进
- Anthropic 流式 —
RathAnthropicChatClient.complete_stream()与run_session_loop(on_event=...)打通。 - Embedding / VLM Provider — 新增
EmbeddingProvider、VLMProvider及对应 OpenAI-compatible client;config 新增llm.embedding_provider/llm.vlm_provider。 - 稳定性 — 流式 TOCTOU 修复、OpenSandbox double-close 竞态修复、ConfigStore 按
(mtime_ns, size)缓存、session loop incremental tail rendering、类型安全收紧(社区 PR #10–#14)。 - 示例重构 —
example/重建为 01–10 编号学习阶梯;新增 memory local / openviking demo。 - README — 重写为 Multi-Agent Multi-Session 定位,补充 PyTorch 概念对照表。
- CI / 测试 — pytest-xdist 并行、pytest-timeout / pytest-rerunfailures;PR 与 main 分支 Python 矩阵拆分;OpenViking 独立 workflow。
安装
pip install --upgrade openrath
# 可选 memory backend
pip install --upgrade "openrath[openviking]"
# 可选 sandbox backend
pip install --upgrade "openrath[opensandbox]"兼容性
Session.merge沙箱语义变更:始终保留self.sandbox。- Lazy Session:读取 transcript / usage 时会阻塞同步。
- Memory 公开 URI 为
memory://;OpenViking 内部viking://由 adapter 转换。 - Python 3.10 – 3.13 支持。
完整变更: v1.1.0...v1.2.0
OpenRath v1.2.0
Building on v1.1.0's session runtime, sandbox backends, and durability layer, v1.2.0 introduces a full Memory plane, an internal async runtime, and a unified Session / Sandbox lifecycle. OpenRath moves from a multi-session orchestration framework toward a multi-agent × multi-session × durable memory runtime.
Major Features
Memory Plane
A new rath.memory module mirrors rath.backend — agent memory is now a first-class concept:
- Local Memory Backend (default) — ships with
pip install openrath, zero extra dependencies; supportsmemory://URIs, BM25 lexical search, optional embedding ranking, resource ingest, and LLM memo extraction on commit. - OpenViking Backend (optional) —
pip install "openrath[openviking]"for OpenViking integration; public API usesmemory://, with automaticviking://translation at the adapter boundary. - Agent Memory API —
flow.Agent(memory="local")binds a store and exposesremember_memory()/recall_memory()/commit_memory(); forward can auto-inject recalled context and optionally commit withcommit_on_forward. - Config-driven —
~/.openrath/config.jsongains amemorysection with named local store presets.
Quick start: python example/09_memory.py (remember / recall work without an API key).
Internal Async Runtime
A PyTorch-style private rath._async runtime. The public API stays fully synchronous — async behavior is transparent internally:
- Lazy Session —
run_session_loop()returns a Session immediately; readingchunk_table/cumulative_usageimplicitly synchronizes; lineage attributes remain eager. - Parallel tool scheduling — tool calls grouped by
resource_keyrun in parallel across keys (e.g. distinctfs:writepaths) and serially within a key (e.g. shellexec). - WAL persistence — session JSONL writes to
.__partial__for crash detection; async writer keeps the runtime loop unblocked. - Benchmark / stress — new
tests/bench/suite andscripts/stress.pyfor concurrency soak testing.
Major Optimization
Unified Session & Sandbox Lifecycle
- Lock-guarded
BackendSandboxacquire/release; close-on-zero runs outside the lock to eliminate races. backend.get(name)returns a per-process singleton so refcounts and per-backend caches stay coherent across sessions.Session.create()consolidates leaf-user / leaf-system / empty constructors with consistent lineage stamping.Session.mergesemantics clarified — always keepsself.sandbox; cross-sandbox merge no longer raises.- Loop performance — one
chunk_tablesync per assistant+tools turn instead of per row (fixes O(n²) growth). - OpenSandbox resume —
PersistedSession.to_resumable_pairreattaches existing handles instead of opening fresh containers.
Other Improvements
- Anthropic streaming —
RathAnthropicChatClient.complete_stream()wired intorun_session_loop(on_event=...). - Embedding / VLM providers — new
EmbeddingProvider,VLMProvider, and OpenAI-compatible clients; config addsllm.embedding_provider/llm.vlm_provider. - Stability — streaming TOCTOU fixes, OpenSandbox double-close race fix, ConfigStore cached by
(mtime_ns, size), incremental session-loop tail rendering, type-safety tightening (community PRs #10–#14). - Examples —
example/rebuilt as a numbered 01–10 learning ladder; new local / OpenViking memory demos. - README — rewritten around multi-agent multi-session positioning with a PyTorch concept mapping table.
- CI / testing — pytest-xdist parallelism, pytest-timeout / pytest-rerunfailures; split Python matrix for PR vs main; dedicated OpenViking workflow.
Install
pip install --upgrade openrath
# optional memory backend
pip install --upgrade "openrath[openviking]"
# optional sandbox backend
pip install --upgrade "openrath[opensandbox]"Compatibility
Session.mergesandbox semantics changed: always keepsself.sandbox.- Lazy Session: reading transcript / usage blocks until synchronized.
- Public memory URIs use
memory://; OpenViking's internalviking://is translated by the adapter. - Python 3.10 – 3.13 supported.
Full changelog: v1.1.0...v1.2.0
v1.1.0
v1.1.0
This release builds on v1.0.0 (session-first loops, sandbox-as-backend, session graph) with four user-visible feature surfaces, two architecture improvements, and a project-wide CI/lint overhaul.
Most of what's below shipped thanks to community contributions — thank you 🙏
Highlights
Community contributions
Thanks to @Enderfga for a sustained run of feature work:
- Multi-provider LLM support — Anthropic via
provider_kind="anthropic", Azure OpenAI env-var fallbacks, registry-based chat-client dispatch so adding another vendor is aregister_chat_client(kind, factory)call. - Streaming completions — opt in via
run_session_loop(..., on_event=...); per-delta callbacks for UI consumers. - Session persistence — append-only JSONL under
~/.openrath/sessions/<uuid>.jsonl. Every chunk is flushed as it lands, sokill -9mid-loop loses at most one partial line. Opt in viarun_session_loop(..., persist=True). - Sandbox identity persistence — stable working dirs for
local, remote-id pinning foropensandbox, both under~/.openrath/sandboxes/. Groundwork for cross-process reattach. - LLM API fault-tolerance — transient-error retries, cumulative token-usage aggregation, per-session budget guard (
provider.budget_total_tokens+on_budget_exceededcallback, latched to the first cap-crossing). - MCP stdio adapter — wire an MCP server in as a
FlowToolCall.
Thanks to @xy3xy3 for Chinese README and language-switch links.
Thanks to @NorthSecond for the infrastructure pass:
- GitHub Actions CI — full matrix (lint / mypy / pytest 3.10–3.13 / opensandbox / docs / build / shellcheck) with pre-commit hooks.
- flake8 → ruff migration with auto-fix and format-check enforcement.
From the OpenRath team @Tokisakix
- Refcount-shared sandboxes — a sandbox can now be held by multiple sessions; close happens when the last reference drops, not when the first session ends. Improves reuse across fork/merge workflows.
- Session
mergeprimitive — first-class atomic merge on the session graph, complementingfork.
Supporting refactors and fixes
- Unified streaming loop;
BackendSandbox.refcountpublic read-only property; shared helpers extracted (parse_tool_arguments,tool_failure_from,resolve_executor,spec_json). - Streaming + Anthropic now fails fast at setup instead of deep inside dispatch.
- Compress works when
user_sessionhas no sandbox. max_tool_roundstruncation now warns and stamps lineage.- OpenSandbox
_code_runreliably surfaces Python tracebacks (the v1.0.2 code-interpreter image doesn't always populateExecution.error). - Local backend normalizes
OSErrorin_files_write/_files_exists.
Docs
- Docs site translated to English; new research_transformer example; reference table for LLM integration points.
Install
pip install --upgrade openrath
# optional sandbox backend
pip install --upgrade "openrath[opensandbox]"Compatibility
- No public-API breaking changes vs. v1.0.0.
- Python 3.10 – 3.13 supported.
Full changelog: v1.0.0...v1.1.0
OpenRath v1.0.0
First stable PyPI release. See CHANGELOG or commit message on tag.
