Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-v2-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
server /data
- run: uv lock --check
- run: uv sync --frozen --extra postgres --extra server --extra s3 --extra redis --extra otel
- run: uv run ruff check src tests scripts examples
- run: uv run ruff check src tests scripts deploy/reference_app.py
- run: uv run ruff format --check src tests example
- run: uv run mypy src/rath
- name: Audit exact production dependency set
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-v2-ga.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ jobs:
uv lock --check
uv sync --frozen --all-extras --all-groups
uv run ruff format --check src tests example
uv run ruff check src tests scripts examples
uv run ruff check src tests scripts deploy/reference_app.py
uv run mypy --no-incremental src/rath
uv run pytest -q -n auto \
-m "not live_llm and not opensandbox and not openviking"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release-v2-rc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
uv lock --check
uv sync --frozen --all-extras --all-groups
uv run ruff format --check src tests example
uv run ruff check src tests scripts examples
uv run ruff check src tests scripts deploy/reference_app.py
uv run mypy --no-incremental src/rath
uv run pytest -q -n auto -m "not live_llm and not opensandbox and not openviking"
uv run python scripts/export_openapi_v2.py --output "$RUNNER_TEMP/openapi-v2.json"
Expand Down
76 changes: 59 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,40 @@ Most agent frameworks begin with an agent loop. OpenRath begins with **Session**

OpenRath is designed for this: many agents collaborating across many branchable sessions, while still tracing every role, workspace, memory write, and final output.

## v2.0.0 durable runtime (release candidate)

The `2.0.0rc1` candidate adds explicit `@step` / `@router` execution plans, durable
Runs and checkpoints, effect reconciliation, tenant-scoped Agent Server APIs,
and governed Provider/Tool/Sandbox/Memory adapters. The HTTP contract is
currently **Beta**; v1 JSONL imports are historical and cannot resume an active
Run.
## OpenRath v2.0.0: Built for Production

The defining change in OpenRath v2.0.0 is that OpenRath moves beyond a
composable Python framework and becomes a durable runtime designed for
production deployment. The existing Session-first Python API remains intact;
the release adds a production execution and operations layer around it.

| Production concern | What OpenRath provides |
| --- | --- |
| Durable execution | Explicit `@step` / `@router` boundaries compile into immutable execution plans. Runs, Events, and Checkpoints survive process and worker restarts. |
| Resilient workers | Leases, fencing, retries, cancellation, deadlines, and resumable queues prevent stale workers from silently committing new state. |
| Controlled side effects | An Effect Ledger records outcomes and idempotency keys. Ambiguous non-idempotent effects stop in `NEEDS_REVIEW` instead of being replayed blindly. |
| Human decisions | Durable Interrupts pause a Run for approval or input and resume it without rebuilding hidden loop state. |
| Security and tenancy | Agent Server tokens carry explicit action grants; tenant/project scope, policy checks, secret references, trust labels, and audit remain separate boundaries. |
| Production operations | PostgreSQL is the durable source of truth, Redis can accelerate signaling, S3-compatible storage holds artifacts, and health, migration, telemetry, container, and Kubernetes references are included. |

```text
@step / @router
|
v
ExecutionPlan -> Run -> Event -> Checkpoint
| |
| +-> Interrupt / Effect Ledger
|
+-> PostgreSQL durable state
+-> optional Redis signals
+-> S3-compatible artifacts
|
v
Agent Server HTTP + SSE
```

Embedded mode is intended for a trusted process. Agent Server mode is the
strict durable profile: tokens need explicit action grants, object access is
tenant/project scoped, and synchronous steps cannot declare a preemptive
timeout. Use an async step or isolated executor for enforceable deadlines.
Embedded mode remains useful inside a trusted process. Agent Server mode is the
strict production profile:

```python
runtime = LocalRuntime(
Expand All @@ -76,12 +98,28 @@ runtime = LocalRuntime(
server = AgentServer(store, runtime, auth=auth, audit_sink=audit)
```

Production PostgreSQL schema migration is a separate operation:
`openrath-migrate` followed by `openrath-migrate --check`. Runtime identities
do not need DDL privileges. See
[`deploy/docs/operations-v2.md`](deploy/docs/operations-v2.md),
[`deploy/docs/migration-v2.md`](deploy/docs/migration-v2.md), and the generated
[`deploy/docs/openapi-v2.json`](deploy/docs/openapi-v2.json).
Install the production profile and run schema migration as a separate
operation:

```bash
pip install "openrath[server,postgres]"
openrath-migrate
openrath-migrate --check
```

Runtime identities do not need DDL privileges. Tokens need explicit action
grants, object access is tenant/project scoped, and synchronous steps cannot
declare a preemptive timeout; use an async step or isolated executor when a
deadline must be enforced.

OpenRath v2.0.0 is designed for production deployment while keeping interface
maturity explicit: the Agent Server HTTP surface remains **Beta**, and v1 JSONL
imports are historical records rather than resumable active Runs. Deployment,
migration, security, and operations guidance lives in
[`deploy/`](deploy/), including
[`operations-v2.md`](deploy/docs/operations-v2.md),
[`migration-v2.md`](deploy/docs/migration-v2.md), and the generated
[`openapi-v2.json`](deploy/docs/openapi-v2.json).

<p align="center">
<img src="assets/readme/diagrams/paradigm-map.png" alt="Multi-Agent Multi-Session Map" width="860" />
Expand Down Expand Up @@ -344,6 +382,10 @@ python example/01_hello_agent.py

Read [`example/README.md`](example/README.md) for setup details and shared helpers.

For complete, production-shaped scenarios with fixed inputs, durable state, QA,
and committed deliverables, see
[`Rath-Team/OpenRath-Example`](https://github.com/Rath-Team/OpenRath-Example).

---

## Docs and Links
Expand Down
70 changes: 62 additions & 8 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,67 @@

OpenRath 为此而设计:多个 Agent 在多个可分支 Session 上协作,同时仍能追踪每个 role、workspace、memory 写入和最终输出。

## v2.0.0 durable runtime(候选版本)
## OpenRath v2.0.0:面向生产环境

OpenRath v2.0.0 最重要的变化,是 OpenRath 从一个可组合的 Python 框架,
进入可部署、可恢复、可运维的生产环境。原有以 Session 为核心的 Python API
保持不变;这个版本在其外层增加了一套生产级执行与运维体系。

| 生产环境关注点 | OpenRath 提供的能力 |
| --- | --- |
| 持久化执行 | 显式的 `@step` / `@router` 边界会编译成不可变执行计划;Run、Event 与 Checkpoint 能跨进程和 Worker 重启保留。 |
| Worker 故障恢复 | Lease、Fencing、Retry、Cancellation、Deadline 与可恢复队列,防止过期 Worker 静默提交新状态。 |
| 受控副作用 | Effect Ledger 记录执行结果与幂等键;无法确认的非幂等副作用会停在 `NEEDS_REVIEW`,而不是被盲目重放。 |
| 人工决策 | 持久化 Interrupt 可以暂停 Run 等待审批或输入,并在不重建隐藏循环状态的情况下恢复。 |
| 安全与租户隔离 | Agent Server Token 使用显式 Action Grant;Tenant/Project Scope、Policy、Secret Reference、Trust Label 与 Audit 保持为独立边界。 |
| 生产运维 | PostgreSQL 是持久化事实来源,Redis 可加速信号传递,S3 兼容存储保存 Artifact,并提供健康检查、迁移、遥测、容器与 Kubernetes 参考。 |

```text
@step / @router
|
v
ExecutionPlan -> Run -> Event -> Checkpoint
| |
| +-> Interrupt / Effect Ledger
|
+-> PostgreSQL 持久化状态
+-> 可选 Redis 信号
+-> S3 兼容 Artifact
|
v
Agent Server HTTP + SSE
```

Embedded mode 仍适合可信进程内部使用。Agent Server mode 是严格的生产
Profile:

`2.0.0rc1` 新增显式 `@step` / `@router` 执行计划、durable Run 与
Checkpoint、effect reconciliation、tenant-scoped Agent Server API,以及受
治理的 Provider/Tool/Sandbox/Memory adapter。HTTP contract 在 RC 阶段仍为
**Beta**;v1 JSONL 导入仅作为历史记录,不能恢复 active Run。
```python
runtime = LocalRuntime(
store,
effect_ledger=ledger,
production_mode=True,
)
server = AgentServer(store, runtime, auth=auth, audit_sink=audit)
```

Embedded mode 面向可信本地进程。Agent Server mode 是严格的 durable
profile:token 必须具有显式 action grants,对象访问按 tenant/project
隔离;需要强制 deadline 时应使用 async step 或 isolated executor。
安装生产 Profile,并将数据库 Schema 迁移作为独立操作执行:

```bash
pip install "openrath[server,postgres]"
openrath-migrate
openrath-migrate --check
```

运行时身份不需要 DDL 权限。Token 必须拥有显式 Action Grant,对象访问按
Tenant/Project 隔离;同步 Step 不能声明抢占式超时,需要强制 Deadline 时应使用
Async Step 或隔离执行器。

OpenRath v2.0.0 面向生产部署,同时明确标注接口成熟度:Agent Server HTTP
接口仍为 **Beta**;v1 JSONL 导入属于历史记录,不能恢复 Active Run。部署、
迁移、安全和运维指南位于 [`deploy/`](deploy/),包括
[`operations-v2.md`](deploy/docs/operations-v2.md)、
[`migration-v2.md`](deploy/docs/migration-v2.md) 和生成的
[`openapi-v2.json`](deploy/docs/openapi-v2.json)。

<p align="center">
<img src="assets/readme/diagrams/paradigm-map.png" alt="多智能体多会话映射" width="860" />
Expand Down Expand Up @@ -326,6 +377,9 @@ python example/01_hello_agent.py

阅读 [`example/README.md`](example/README.md) 获取设置细节和共享 helpers。

如需查看包含固定输入、持久化状态、质量检查和已提交交付物的完整生产化场景,
请访问 [`Rath-Team/OpenRath-Example`](https://github.com/Rath-Team/OpenRath-Example)。

---

## 文档与链接
Expand Down
4 changes: 2 additions & 2 deletions deploy/compose/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ services:
dockerfile: docker/Dockerfile
image: openrath:2.0.0rc1
environment:
OPENRATH_APP: examples.v2_server_app:app
OPENRATH_APP: reference_app:app
OPENRATH_POSTGRES_DSN: postgresql://openrath:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/openrath
OPENRATH_TOKEN: ${OPENRATH_TOKEN:?set OPENRATH_TOKEN}
OPENRATH_TENANT_ID: ${OPENRATH_TENANT_ID:-default}
Expand Down Expand Up @@ -61,7 +61,7 @@ services:
dockerfile: docker/Dockerfile
image: openrath:2.0.0rc1
entrypoint: ["openrath-worker"]
command: ["--app", "examples.v2_server_app:server"]
command: ["--app", "reference_app:server"]
environment:
OPENRATH_POSTGRES_DSN: postgresql://openrath:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/openrath
OPENRATH_TOKEN: ${OPENRATH_TOKEN:?set OPENRATH_TOKEN}
Expand Down
4 changes: 2 additions & 2 deletions deploy/kubernetes/openrath.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ kind: ConfigMap
metadata:
name: openrath
data:
OPENRATH_APP: examples.v2_server_app:app
OPENRATH_APP: reference_app:app
OPENRATH_EMBEDDED_WORKER: "false"
OPENRATH_DB_SCHEMA: openrath
OPENRATH_TENANT_ID: default
Expand Down Expand Up @@ -163,7 +163,7 @@ spec:
image: ghcr.io/rath-team/openrath:2.0.0rc1
# Release automation must replace the review tag with image@sha256.
imagePullPolicy: Always
command: ["openrath-worker", "--app", "examples.v2_server_app:server"]
command: ["openrath-worker", "--app", "reference_app:server"]
envFrom:
- configMapRef:
name: openrath
Expand Down
2 changes: 1 addition & 1 deletion examples/v2_server_app.py → deploy/reference_app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Minimal standalone OpenRath v2 reference application."""
"""Minimal deployable OpenRath v2 reference application."""

from __future__ import annotations

Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ RUN groupadd --system --gid 10001 openrath \
&& useradd --system --uid 10001 --gid openrath --home /app openrath
WORKDIR /app
COPY --from=builder /opt/venv /opt/venv
COPY examples ./examples
COPY deploy/reference_app.py ./reference_app.py
USER 10001:10001
EXPOSE 8000
ENTRYPOINT ["openrath-server"]
2 changes: 1 addition & 1 deletion tests/deployment/test_reference_manifests.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_kubernetes_template_covers_workloads_and_dns() -> None:


def test_reference_server_enables_audit_and_explicit_grants() -> None:
app = Path("examples/v2_server_app.py").read_text(encoding="utf-8")
app = Path("deploy/reference_app.py").read_text(encoding="utf-8")
compose = Path("deploy/compose/compose.yaml").read_text(encoding="utf-8")
assert "StructuredAuditSink()" in app
assert 'os.environ["OPENRATH_GRANTS"]' in app
Expand Down
Loading