[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-76154":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":9,"rankLanguage":9,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":22,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":15,"starSnapshotCount":15,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},76154,"OpenRath","Rath-Team\u002FOpenRath","Rath-Team","A opensource, torch-like api framework for dynamic multi-agent workflow.",null,"Python",378,9,120,5,0,106,165,258,318,3,"BSD 3-Clause \"New\" or \"Revised\" License",false,"main",[],"2026-06-12 02:03:40","# OpenRath\n\n![OpenRath logo](https:\u002F\u002Fraw.githubusercontent.com\u002FRath-Team\u002FOpenRath\u002Fmain\u002Fdocs\u002Fsource\u002F_static\u002Flogo.png)\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fpypi.org\u002Fproject\u002Fopenrath\u002F\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fv\u002Fopenrath.svg\" alt=\"PyPI\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fpypi.org\u002Fproject\u002Fopenrath\u002F\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fpyversions\u002Fopenrath.svg\" alt=\"Python\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FRath-Team\u002FOpenRath\u002Fblob\u002Fmain\u002FLICENSE\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-BSD--3--Clause-blue.svg\" alt=\"License\">\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Flinux.do\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLINUX-DO-FFB003.svg?logo=data:image\u002Fsvg%2bxml;base64,DQo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCIgaGVpZ2h0PSIxMDAiPjxwYXRoIGQ9Ik00Ni44Mi0uMDU1aDYuMjVxMjMuOTY5IDIuMDYyIDM4IDIxLjQyNmM1LjI1OCA3LjY3NiA4LjIxNSAxNi4xNTYgOC44NzUgMjUuNDV2Ni4yNXEtMi4wNjQgMjMuOTY4LTIxLjQzIDM4LTExLjUxMiA3Ljg4NS0yNS40NDUgOC44NzRoLTYuMjVxLTIzLjk3LTIuMDY0LTM4LjAwNC0yMS40M1EuOTcxIDY3LjA1Ni0uMDU0IDUzLjE4di02LjQ3M0MxLjM2MiAzMC43ODEgOC41MDMgMTguMTQ4IDIxLjM3IDguODE3IDI5LjA0NyAzLjU2MiAzNy41MjcuNjA0IDQ2LjgyLS4wNTYiIHN0eWxlPSJzdHJva2U6bm9uZTtmaWxsLXJ1bGU6ZXZlbm9kZDtmaWxsOiNlY2VjZWM7ZmlsbC1vcGFjaXR5OjEiLz48cGF0aCBkPSJNNDcuMjY2IDIuOTU3cTIyLjUzLS42NSAzNy43NzcgMTUuNzM4YTQ5LjcgNDkuNyAwIDAgMSA2Ljg2NyAxMC4xNTdxLTQxLjk2NC4yMjItODMuOTMgMCA5Ljc1LTE4LjYxNiAzMC4wMjQtMjQuMzg3YTYxIDYxIDAgMCAxIDkuMjYyLTEuNTA4IiBzdHlsZT0ic3Ryb2tlOm5vbmU7ZmlsbC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMTkxOTE5O2ZpbGwtb3BhY2l0eToxIi8+PHBhdGggZD0iTTcuOTggNzAuOTI2YzI3Ljk3Ny0uMDM1IDU1Ljk1NCAwIDgzLjkzLjExM1E4My40MjYgODcuNDczIDY2LjEzIDk0LjA4NnEtMTguODEgNi41NDQtMzYuODMyLTEuODk4LTE0LjIwMy03LjA5LTIxLjMxNy0yMS4yNjIiIHN0eWxlPSJzdHJva2U6bm9uZTtmaWxsLXJ1bGU6ZXZlbm9kZDtmaWxsOiNmOWFmMDA7ZmlsbC1vcGFjaXR5OjEiLz48L3N2Zz4=\" alt=\"LINUX DO\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n\u003Cdiv align=\"center\">\n\nEnglish · [简体中文](README_zh.md)\n\n\u003C\u002Fdiv>\n\n---\n\n**OpenRath** is an open-source multi-agent framework. You can compose APIs in a PyTorch-like style: session lifecycle, workflow orchestration, tool dispatch, and sandbox backends evolve together on a session graph woven from agents and sessions.\n\n## Recent updates\n\n- 2026-05-12: Released `v1.0.0` and opened the codebase and docs to the community.\n\n> For more info on OpenRath, head over to our docs [https:\u002F\u002Fdocs.openrath.com](https:\u002F\u002Fdocs.openrath.com).\n\n---\n\n## Core highlights\n\nMany stacks keep conversation state, orchestration logic, and execution environments separate: each agent holds its own message list or inner while-loop, the outer layer uses graphs or hand-written steps, and sandboxes or shells are bolted on later. That works for demos, but whole histories get copied across agent boundaries, the execution environment drifts from the workspace the session points at, and at cluster scale it is hard to say which branch and context a round belongs to. OpenRath treats the session as the primary carrier through a run (analogous to a tensor advancing through computation, without replacing PyTorch itself). The split differs in five ways below.\n\n### Sandbox as the execution backend of a session\n\nSeparate ledgers for messages and where commands actually run stay in sync only by hand. After machine or directory changes, or tighter isolation, tool landing points and the workspace implied by the conversation often diverge, which hurts reproducibility and audit. Here backend choice chain-loads off the same object, much like putting data on a device. After a dialogue-and-tool round, ownership of the active sandbox is written back into the returned session so later dispatch still targets the same workflow outcome.\n\n![Sandbox as session backend](https:\u002F\u002Fraw.githubusercontent.com\u002FRath-Team\u002FOpenRath\u002Fmain\u002Fdocs\u002Fsource\u002F_static\u002Fbackend.png)\n\n### Context through chunk tables for better reuse in multi-agent collaboration\n\nFlat message lists encourage whole-history copies and repeated stitching of system prompts and tool results, so it is hard to grab semantic slices while context length and traffic grow. This project keeps an ordered chunk table for system, user, assistant, tool feedback, and related rows; agent-side instructions are prepended before user chunks in the loop for structured sharing and composition. Session fork and merge primitives are described in the Session chapter of the user guide.\n\n### Session-first loops instead of agent-first loops for a sparse agent cluster\n\nA common pattern is a small inner loop per agent (read, model, tools) wrapped by outer orchestration, which yields nested loops and unnecessary completions at a fixed cadence when many roles exist. The default path is session-centric: completions and tool rounds interleave on one evolving session; agents attach to the workflow mainly as prompts and sampling configuration, not each with its own closed executor, which fits sparse clusters better when only part of the roles should activate.\n\n![Session-first loop](https:\u002F\u002Fraw.githubusercontent.com\u002FRath-Team\u002FOpenRath\u002Fmain\u002Fdocs\u002Fsource\u002F_static\u002Fsession.png)\n\n### Dynamic multi-agent fleets: automatic session-graph tracking\n\nWhen topology is wired by hand or an external DAG, lineage often depends on ad-hoc IDs and log excerpts. At scale it becomes hard to say which fork or merge produced a given output. With session-graph tracking enabled, new sessions carry lineage metadata and register centrally into a queryable session graph for dialogue and tool traces; this has nothing to do with autograd and only records execution and conversation.\n\n### Modular workflows: compose and orchestrate cleanly\n\nIf one agent type owns prompts, network I\u002FO, tools, and the loop, inheritance and callbacks stack up and even changing a system prompt or sampling field pulls the whole class. Workflows expose a forward step that takes a session and returns an updated session; agent-side settings sit in parameter-like objects; networking and sandbox dispatch live with the loop executor so module boundaries stay clearer for nesting and reuse.\n\n![Workflow composition](https:\u002F\u002Fraw.githubusercontent.com\u002FRath-Team\u002FOpenRath\u002Fmain\u002Fdocs\u002Fsource\u002F_static\u002Fworkflow.png)\n\n---\n\n## Quickstart\n\n### Install from PyPI\n\n```bash\npip install openrath\n```\n\nOptional OpenSandbox dependencies:\n\n```bash\npip install \"openrath[opensandbox]\"\n```\n\n### Install from source\n\nInstalling from a Git clone is for **developers**; it does **not** guarantee the same stability as installing a **release** from PyPI.\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002FRath-Team\u002FOpenRath.git\ncd OpenRath\npip install .\n```\n\n### Configure the OpenSandbox backend (optional)\n\n```bash\npip install \"openrath[opensandbox]\"\n# or: pip install \".[opensandbox]\"\n```\n\nYou need a running OpenSandbox server (typically Docker). At the repo root, use `scripts\u002Flaunch_opensandbox.sh` or `launch_opensandbox.bat` to sync the optional dependency, generate `.sandbox.toml`, and start `opensandbox-server`; see the script comments for details.\n\nExport `OPEN_SANDBOX_DOMAIN` (default if unset in check scripts: `127.0.0.1:8080`) and any API keys your deployment requires. Run `scripts\u002Fcheck_opensandbox.sh` or `check_opensandbox.bat` to verify imports and `GET \u002Fhealth`.\n\nSet the backend to `opensandbox` in-session with a spec; see `example\u002Fsandbox_backend_opensandbox.py` and the user guide chapter on sandbox backends.\n\n---\n\n## Documentation\n\nBuild Sphinx locally:\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002FRath-Team\u002FOpenRath.git\nuv sync --group dev --group docs\nuv run sphinx-build -M html docs\u002Fsource docs\u002F_build\n```\n\nThe HTML output is under `docs\u002F_build\u002Fhtml\u002F`.\n\n---\n\n## Examples\n\nSample OpenRath entry points:\n\n1. [`session_usage.py`](example\u002Fsession_usage.py): fork and detach, session loop with a local workspace binding, plus session compression at the main entry.\n2. [`sandbox_backend_local.py`](example\u002Fsandbox_backend_local.py): session loop on the local subprocess sandbox; compares unbound workspace vs binding the repository root as the workspace.\n3. [`sandbox_backend_opensandbox.py`](example\u002Fsandbox_backend_opensandbox.py): same shape on the OpenSandbox backend; requires an OpenSandbox stack.\n4. [`custom_tool_usage.py`](example\u002Fcustom_tool_usage.py): FlowToolCall subclass and tool mode wiring on the model side.\n5. [`trading_agents\u002F`](example\u002Ftrading_agents\u002F): an OpenRath reimplementation of [TradingAgents](https:\u002F\u002Fgithub.com\u002FTauricResearch\u002FTradingAgents) (Tauric Research, multi-agent LLM finance stack). Roles stay in a workflow; sessions and tools follow this framework; CLI entry is `main.py`.\n6. [`engineering_agents\u002F`](example\u002Fengineering_agents\u002F): an OpenRath reimplementation of one scenario from [ClawTeam](https:\u002F\u002Fgithub.com\u002FHKUDS\u002FClawTeam) (HKUDS, multi-agent software-engineering automation). Nested workflows (e.g. Lead, FeatureSquad, backend pairs, QA) live in the subfolder.\n7. [`research_transformer\u002F`](example\u002Fresearch_transformer\u002F): a **Transformer-metaphor** academic pipeline (literature vs reproduction branches over N layers, optional figure tool, final polish) demonstrating story-first composition on `Session`\u002F`Workflow`; default sandbox root is `example\u002Fresearch_transformer\u002F.workspace\u002F`.\n\n\u003Cdiv align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002FRath-Team\u002FOpenRath\u002Fmain\u002Fdocs\u002Fsource\u002F_static\u002Fresearch_transformer.png\" alt=\"Research Transformer\" style=\"width: 360px; height: auto;\" \u002F>\n\u003C\u002Fdiv>\n\nThe folders above that reimplement or storyboard upstream scenarios (`trading_agents`, `engineering_agents`, and similar) are for demonstrating complex orchestration only; they are not guarantees about upstream behavior. Using upstream names still means following those repositories’ licenses and terms.\n\n---\n\n## How OpenRath maps onto PyTorch\n\n| Layer | PyTorch | OpenRath | Brief parallel |\n| ----- | ------- | -------- | -------------- |\n| Flowing carrier | Tensor | Session | Advances along compute or dialogue; state can be read again and appended. |\n| Execution structure | Compute graph | Session Graph | Graphs encode dependencies; sessions carry multi-agent dialogue and tool traces. |\n| Execution backend | GPU \u002F CPU | Sandbox | Where compute lands maps to the isolation environment where commands and tools actually run. |\n| Invoke surface | Kernel \u002F op | Tool | Smallest callable surface the backend actually executes. |\n| State \u002F hyperparameters | `nn.Parameter` | `flow.AgentParam` | Agents are not classic executors; the object is closer to typed configuration or parameters. |\n| Modularity | `nn.Module` | `flow.Workflow` | Recursive composition of child modules. |\n\n1. **Session \u002F tensor**\n\nIn OpenRath a session carries ordered semantic chunks, not a numeric array. Like a tensor in PyTorch at the center of data flow and execution, fork and detach names follow PyTorch habits.\n\nIn OpenRath\n\n```python\nfrom rath.session import Session\n\na = Session.from_user_message(\n    \"Please impl a full-stack todo app with auth, DB, React frontend.\"\n)\nb = a.fork()  # like clone()\nc = a.detach()\n```\n\nIn PyTorch\n\n```python\nimport torch\n\na = torch.ones(3, requires_grad=True)\nb = a.clone()\nc = a.detach()\n```\n\n2. **Session graph \u002F compute graph**\n\nIn PyTorch a multiply attaches the new tensor to the graph and `grad_fn` points at the backward node; after `detach` on a leaf, `grad_fn` is None. In OpenRath the session tracks identity and fork metadata: each session has a stable id, fork products record parent session ids, and detach products no longer declare a parent chain.\n\nIn OpenRath\n\n```python\nfrom rath.session import Session\n\na = Session.from_user_message(\"Hello, how are you?\")\nb = a.fork()\nc = a.detach()\n\nprint(a.id)\nprint(b.parent_session_ids)\nprint(c.parent_session_ids)\n```\n\nIn PyTorch\n\n```python\nimport torch\n\na = torch.tensor([1.0], requires_grad=True)\nb = a * 2\nc = a.detach()\n\nprint(\"a:\", a)\nprint(\"b grad_fn:\", b.grad_fn)\nprint(\"c.grad_fn:\", c.grad_fn)\n```\n\n3. **Sandbox \u002F device**\n\nOpenRath models the sandbox backend in a device-like way: the session binds to an execution environment and working directory; chunk contents are not automatically rewritten when you rebind. The API mirrors PyTorch’s `to(device)` pattern: build the object, then declare where it runs.\n\nIn OpenRath\n\n```python\nfrom rath.session import Session\n\na = Session.from_user_message(\n    \"Please impl a full-stack todo app with auth, DB, React frontend.\"\n)\na = a.to(\"local\", spec=\".\u002F\")  # spec: host workspace path\na = a.to(\"opensandbox\", spec=\".\u002F\")\n```\n\nIn PyTorch\n\n```python\nimport torch\n\na = torch.ones(2, 3)\na = a.to(\"cuda:0\")\n```\n\n4. **Kernel \u002F tool**\n\nIn PyTorch, kernels or high-level ops take placed tensors, run numerically on that device, and return tensors. In OpenRath, the tool path takes structured payloads; the current sandbox interprets them inside an isolation boundary and returns command or file feedback into session chunks.\n\nThe call shapes line up: prepare inputs, invoke a thin API, and let the runtime do the heavy work.\n\nIn OpenRath\n\n```python\nfrom rath.flow.tool import flow_tool_files_list\nfrom rath.session import Session\n\na = Session.from_user_message(\n    \"Please impl a full-stack todo app with auth, DB, React frontend.\"\n)\na = a.to(\"local\", spec=\".\u002F\")\n\ntool_result = flow_tool_files_list(a, path=\".\u002F\")\n```\n\nIn PyTorch\n\n```python\nimport torch\nimport torch.nn.functional as F\n\nlogits = torch.tensor(\n    [\n        [2.0, 1.0, 0.1, -1.0, 0.3],\n        [0.2, 3.1, 0.5, 0.1, -0.4],\n        [1.2, 0.7, 2.5, 0.3, 0.1],\n    ]\n)\ntarget = torch.tensor([0, 1, 2])\n\nloss = F.cross_entropy(logits, target)\n```\n\n5. **Agent state \u002F parameters**\n\nModule parameters in PyTorch register on the module dict and optimizers collect tensors by name. `AgentParam` in OpenRath binds two pieces into one: agent-side session chunks seeded from the agent prompt (a stable prefix before each completion) and a `Provider` with model name and sampling-style request fields.\n\nIn OpenRath\n\n```python\nfrom rath import flow\nfrom rath.session import Session\n\nagent = flow.AgentParam(\n    agent_session=Session.from_agent_prompt(\"You are a helpful assistant.\"),\n    provider=flow.Provider(api_key=\"sk-...\", model=\"glm-5.1\"),\n)\n```\n\nIn PyTorch\n\n```python\nimport torch\nfrom torch import nn\n\nweight = nn.Parameter(torch.randn(1024, 4096))\n```\n\n6. **Workflow \u002F module**\n\nWorkflow code stays modular and composable, much like PyTorch `Module`. With sessions and chunks maintained by the framework, implementers mainly structure workflow composition and business logic.\n\nIn OpenRath\n\n```python\nfrom rath import flow\nfrom rath.flow.tool import FlowToolCall\nfrom rath.session import Session, run_session_loop\n\n\nclass Agent(flow.Workflow):\n    def __init__(\n        self,\n        system_prompt: str,\n        provider: flow.Provider,\n        tools: list[FlowToolCall] | None = None,\n    ) -> None:\n        super().__init__()\n        self.tools = list(tools or [])\n        self.agent = flow.AgentParam(\n            agent_session=Session.from_agent_prompt(system_prompt),\n            provider=provider,\n        )\n\n    def forward(self, session: Session) -> Session:\n        return run_session_loop(\n            user_session=session,\n            agent_session=self.agent.agent_session,\n            agent_provider=self.agent.provider,\n            tools=self.tools,\n        )\n\n\nagent_model = Agent(\n    system_prompt=\"You are a helpful assistant.\",\n    provider=flow.Provider(api_key=\"sk-...\", model=\"glm-5.1\"),\n)\n\nuser_session = Session.from_user_message(\n    \"List all files in the current directory. Summarize what you found.\"\n)\nuser_session = user_session.to(\"local\", spec=\".\u002F\")\nout_session = agent_model(user_session)\n```\n\nIn PyTorch\n\n```python\nimport torch\nimport torch.nn as nn\n\n\nclass Linear(nn.Module):\n    def __init__(self, in_features: int, out_features: int) -> None:\n        super().__init__()\n        self.weight = nn.Parameter(torch.randn(out_features, in_features))\n        self.bias = nn.Parameter(torch.zeros(out_features))\n\n    def forward(self, x: torch.Tensor) -> torch.Tensor:\n        return x @ self.weight.T + self.bias\n\n\nmodel = Linear(4, 2)\nx = torch.randn(3, 4)\ny = model(x)\n```\n\n---\n\n## License\n\nOpenRath uses a BSD-style license; see [LICENSE](LICENSE) at the repository root.\n","OpenRath 是一个开源的多代理框架，采用类似 PyTorch 的 API 风格，支持会话生命周期管理、工作流编排、工具调度和沙盒后端等功能。其核心特点在于将会话视为运行的主要载体，通过代理和会话构建的会话图来实现功能协同演进，避免了传统方法中历史记录跨代理边界复制、执行环境与工作空间不一致等问题。适用于需要复杂多代理交互场景的应用开发，如分布式系统中的任务调度与协作等。",2,"2026-06-11 03:54:41","CREATED_QUERY"]