Skip to content

Releases: Rath-Team/OpenRath

OpenRath v2.0.0

Choose a tag to compare

@Tokisakix Tokisakix released this 31 Jul 05:25
8281946

OpenRath v2.0.0

OpenRath 2.0.0 将框架从进程内 Agent 工作流扩展为可部署的持久化多 Agent Runtime 与 Agent Server。本版本引入可恢复执行、受治理的副作用、人工中断、安全与租户边界,以及面向 PostgreSQL、Redis、S3 和 OpenTelemetry 的生产部署能力。

OpenRath v2 持久化运行时

核心特性

持久化 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.mddeploy/docs/operations-v2.mddeploy/docs/api-governance-v2.mddeploy/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]"

项目与资源

完整变更: 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.

OpenRath v2 durable runtime

Major Features

Durable Runtime

  • Explicit compilation@step and @router compile 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_REVIEW instead 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

Full changelog: v1.3.0...v2.0.0

OpenRath 2.0.0rc1

OpenRath 2.0.0rc1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 29 Jul 13:16

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 / @router compilation 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 /v1 HTTP 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, and deploy/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:

  1. Approved live LLM/provider lifecycle.
  2. Approved live OpenViking lifecycle.
  3. Target-like single-host and split-profile capacity results.
  4. One-to-four worker scaling efficiency validation.
  5. Eight-hour target-like soak.
  6. Target-cluster backup/restore, dependency-failure, rollout, and rollback
    drills.
  7. 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

Choose a tag to compare

@Tokisakix Tokisakix released this 08 Jul 01:25

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.jsoncompile() 为纯 opt-in。

核心特性

持久化与布局(atomic writes + manifest + GC)

  • rath.persistence.atomicatomic_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 配置段 — 新增 backend section,OpenSandbox 的 domain/flag 经 env → config → ~/.sandbox.toml 解析。
  • rath.config.env EnvSpec 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_sessionagent_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/Agenttorch.nn.Module 一样注册),构建 ResourceManifestSelector 记为 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 / openviking extras 升级到最新兼容版本。
  • 示例 — 新增 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.atomicatomic_write_text / atomic_write_json: temp file + os.replace, path-keyed lock, Windows sharing-violation retry; fixes concurrent config save PermissionError on 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.json records 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 splitconfig.json keeps routing/presets; secrets such as api_key move to a 0600 credentials.json; inline keys still load and migrate on save.
  • backend config section — new backend section; OpenSandbox domain/flag resolves env → config → ~/.sandbox.toml.
  • rath.config.env EnvSpec registry — sync/async LLM, embedding, VLM, and OpenSandbox all resolve through one central registry instead of scattered os.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 on Session.to("local") still mean sandbox backend names.
  • Loop provider fallbackrun_session_loop / run_session_compress / select_session fall back to a session-bound provider when agent_provider=None; an Agent's provider always wins; bound providers are never serialized.
  • chat_client_for cache — 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 (nested Workflow/Agent register like torch.nn.Module) building a ResourceManifest; Selector is 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.run hang — 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

  • Dependenciesopensandbox / openviking extras 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_key still 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

Choose a tag to compare

@Tokisakix Tokisakix released this 04 Jul 20:09

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_compressfinish_reason="length"(摘要被输出上限截断)时明确报错并提示加大输出预算,而非把残缺摘要当作权威替换。
  • 懒开沙箱重复打开_ensure_sandbox 改用双检锁,避免两个首用调用各开一个沙箱、第二个赋值挤掉第一个而留下永不释放的孤儿句柄。
  • Session 注册表内存增长SessionRegistry 改用 WeakValueDictionary,无外部引用的 session 可被回收,长跑进程不再无界增长。
  • 持久化空集合 round-tripspec_from_jsonableis 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 未设置时仍默认 openailitellm 为纯新增;所有新符号(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 — implements complete() and complete_stream(), auto-registered via register_chat_client("litellm", ...) and dispatched by chat_client_for() when provider_kind="litellm".
  • Optional dep, zero impactpip install "openrath[litellm]"; a lazy import falls back cleanly when it isn't installed, and provider_kind still defaults to openai when unset.
  • Credential resolution orderProvider.api_key / Provider.base_url first, then the LITELLM_API_KEY / LITELLM_API_BASE env 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_backoff for RateLimitError / 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 var

Session 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, or None when there is none yet. Callers previously had to walk the transcript by hand; example/11_dynamic_selector.py also crashed because it called this then-missing method, and now runs.
  • ChunkTable sequence protocol — new __len__ / __getitem__ (with slicing) / __iter__, so a ChunkTable supports len(), 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 summariesrun_session_compress raises a clear error on finish_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_sandbox now uses double-checked locking, preventing two first-use calls from each opening a sandbox and orphaning the first acquired handle.
  • Session registry memory growthSessionRegistry is backed by a WeakValueDictionary, so an unreferenced session is collected and a long-running process no longer grows without bound.
  • Empty-collection persistence round-tripspec_from_jsonable rebuilds entrypoint / env with is 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 --reruns accidentally 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_kind still defaults to openai when unset, litellm is purely additive, and all new symbols (Session.text(), the ChunkTable sequence methods) are additive and leave existing call sites unaffected.
  • litellm is 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

Choose a tag to compare

@Tokisakix Tokisakix released this 30 May 04:13

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 仿照 Compressorselect_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 都能附带一句自我描述;AgentCompressor 均支持。这正是 Selector 路由时所依据的文本。
  • session.select_sessionSelector 底层的路由原语,用一次 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 场景下的 ifwhile 控制。
  • 文档 — 新增用户指南 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 to Agent / Compressor, that acts as an LLM-backed router. Calling Selector.forward(session, *workflows) merges the routing instructions, the current session, and a numbered menu of each candidate's description into 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 whose forward returns the input session unchanged. When no candidate fits, the index is out of range, or there are no candidates at all, Selector returns this instead of None. Callers can then dispatch unconditionally (session = result(session) is a safe no-op) and check isinstance(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 both Agent and Compressor. This is the text Selector routes on.
  • session.select_session — the routing primitive beneath Selector, 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.py showing if and while control flow in a dynamic multi-agent setting.
  • Docs — new user guide docs/source/user_guide/dynamic_workflow.md, cross-referenced from workflow_agent.md / main_components.md; README and README_zh gain a "dynamic control flow" section, and the PyTorch mapping table gains a Selector row.
  • 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.description defaults to "", all new symbols are additive, and existing Agent / Compressor / Workflow call sites are unaffected.
  • Selector.forward(session, *workflows) returns a Workflow rather than a Session, deliberately departing from the base forward(session) -> Session contract—it is a routing-decision component, not a session transformer, and signals completion by returning an EmptyWorkflow.
  • Python 3.10 – 3.13 supported.

Full changelog: v1.2.0...v1.2.1

v1.2.0

Choose a tag to compare

@Tokisakix Tokisakix released this 25 May 08:28

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 Backendpip install openrath 即可使用,零额外依赖;支持 memory:// URI、BM25 词法检索、可选 embedding 排序、Resource ingest,以及 Commit 时的 LLM 记忆提取。
  • OpenViking Backend(可选)pip install "openrath[openviking]" 接入 OpenViking;公开 API 统一为 memory://,adapter 边界自动与 viking:// 互转。
  • Agent 记忆 APIflow.Agent(memory="local") 绑定 store,提供 remember_memory() / recall_memory() / commit_memory()forward 时可自动 recall 注入,并可选 commit_on_forward
  • 配置驱动~/.openrath/config.json 新增 memory section,可命名多个 local store preset。

快速上手:python example/09_memory.py(remember / recall 无需 API key)。

内部 Async 运行时

引入 PyTorch 风格的私有 rath._async 运行时。对外 API 保持完全同步,async 能力在内部透明生效:

  • Lazy Sessionrun_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 生命周期统一

  • BackendSandbox acquire/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 — 新增 EmbeddingProviderVLMProvider 及对应 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; supports memory:// 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 uses memory://, with automatic viking:// translation at the adapter boundary.
  • Agent Memory APIflow.Agent(memory="local") binds a store and exposes remember_memory() / recall_memory() / commit_memory(); forward can auto-inject recalled context and optionally commit with commit_on_forward.
  • Config-driven~/.openrath/config.json gains a memory section 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 Sessionrun_session_loop() returns a Session immediately; reading chunk_table / cumulative_usage implicitly synchronizes; lineage attributes remain eager.
  • Parallel tool scheduling — tool calls grouped by resource_key run in parallel across keys (e.g. distinct fs:write paths) and serially within a key (e.g. shell exec).
  • WAL persistence — session JSONL writes to .__partial__ for crash detection; async writer keeps the runtime loop unblocked.
  • Benchmark / stress — new tests/bench/ suite and scripts/stress.py for concurrency soak testing.

Major Optimization

Unified Session & Sandbox Lifecycle

  • Lock-guarded BackendSandbox acquire/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.merge semantics clarified — always keeps self.sandbox; cross-sandbox merge no longer raises.
  • Loop performance — one chunk_table sync per assistant+tools turn instead of per row (fixes O(n²) growth).
  • OpenSandbox resume — PersistedSession.to_resumable_pair reattaches existing handles instead of opening fresh containers.

Other Improvements

  • Anthropic streamingRathAnthropicChatClient.complete_stream() wired into run_session_loop(on_event=...).
  • Embedding / VLM providers — new EmbeddingProvider, VLMProvider, and OpenAI-compatible clients; config adds llm.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).
  • Examplesexample/ 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.merge sandbox semantics changed: always keeps self.sandbox.
  • Lazy Session: reading transcript / usage blocks until synchronized.
  • Public memory URIs use memory://; OpenViking's internal viking:// is translated by the adapter.
  • Python 3.10 – 3.13 supported.

Full changelog: v1.1.0...v1.2.0

v1.1.0

Choose a tag to compare

@Tokisakix Tokisakix released this 16 May 10:40

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 a register_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, so kill -9 mid-loop loses at most one partial line. Opt in via run_session_loop(..., persist=True).
  • Sandbox identity persistence — stable working dirs for local, remote-id pinning for opensandbox, 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_exceeded callback, 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 merge primitive — first-class atomic merge on the session graph, complementing fork.

Supporting refactors and fixes

  • Unified streaming loop; BackendSandbox.refcount public 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_session has no sandbox.
  • max_tool_rounds truncation now warns and stamps lineage.
  • OpenSandbox _code_run reliably surfaces Python tracebacks (the v1.0.2 code-interpreter image doesn't always populate Execution.error).
  • Local backend normalizes OSError in _files_write / _files_exists.

Docs

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

Choose a tag to compare

@Tokisakix Tokisakix released this 12 May 10:56

First stable PyPI release. See CHANGELOG or commit message on tag.