项目简介
OpenEnv 通过类似 Gymnasium 的 API 提供了与智能体执行环境交互的标准。它包含环境创建工具和用于部署的命令行界面,支持隔离、安全且易于使用的 RL 后训练环境。
README 预览
# OpenEnv: Agentic Execution Environments\n\nAn e2e framework for creating, deploying and using isolated execution environments for agentic RL training, built using Gymnasium style simple APIs.\n\n\n \n \n \n \n \n \n\n\n---\n\n**Featured Example:** Train LLMs to play BlackJack using [torchforge](https://meta-pytorch.org/torchforge/) (PyTorch's agentic RL framework): [`examples/grpo_blackjack/`](examples/grpo_blackjack/)\n\n**Zero to Hero Tutorial:** End to end tutorial from our [GPU Mode](tutorial/README.md) lecture and other hackathons.\n\n## Quick Start\n\nInstall the OpenEnv package:\n\n```bash\npip install openenv\n```\n\nInstall an environment client (e.g., Echo):\n\n```bash\npip install git+https://huggingface.co/spaces/openenv/echo_env\n```\n\nThen use the environment:\n\n```python\nimport asyncio\nfrom echo_env import CallToolAction, EchoEnv\n\nasync def main():\n # Connect to a running Space (async context manager)\n async with EchoEnv(base_url="https://openenv-echo-env.hf.space") as client:\n # Reset the environment\n result = await client.reset()\n print(result.observation.echoed_message) # "Echo environment ready!"\n\n # Send messages\n result = await client.step(\n CallToolAction(\n tool_name="echo_message",\n arguments={"message": "Hello, World!"},\n )\n )\n print(result.observation.result) # "Hello, World!"\n print(result.reward)\n\nasyncio.run(main())\n```\n\n**Synchronous usage** is also supported via the `.sync()` wrapper:\n\n```python\nfrom echo_env import CallToolAction, EchoEnv\n\n# Use .sync() for synchronous context manager\nwith EchoEnv(base_url="https://openenv-echo-env.hf.space").sync() as client:\n result = client.reset()\n result = client.step(\n CallToolAction(\n tool_name="echo_message",\n arguments={"message": "Hello, World!"},\n )\n )\n print(result.obse常见问题 (5)
故障排除为什么 MCPToolClient 在 mode="production" 时使用 WebSocket /ws 而不是 HTTP /mcp JSON-RPC?
生产传输标志初始化不正确。在 src/openenv/core/mcp_client.py 中,将 self.use_production_mode = False 替换为:
self.use_production_mode = mode_lower == "production"
这使该标志与规范化后的 _mode 值保持一致。作为临时解决方法,在创建客户端后手动设置它:
client = MCPToolClient(..., mode="production")
client.use_production_mode = True
修复后,list_tools() 应通过 HTTP /mcp 调用 tools/list,call_tool() 应通过 /mcp 调用 tools/call,而模拟模式应继续使用 WebSocket /ws 的 step() 路径。更新回归测试,使其断言所选用的传输方式,而不是仅检查 type="step" 消息。
故障排除如何修复 MCPToolClient 在生产模式下使用 WebSocket 而非 HTTP /mcp JSON-RPC 传输的问题?
在 src/openenv/core/mcp_client.py 中,将 MCPToolClient 构造函数里硬编码的 self.use_production_mode = False 替换为:
self.use_production_mode = mode_lower == "production"
这样,当 mode="production" 时,list_tools() 和 call_tool() 将使用 HTTP /mcp JSON-RPC 方法 tools/list 和 tools/call,而模拟模式则继续使用 WebSocket step() 路径。
作为不修改源代码的临时变通方案,可在初始化客户端后立即设置该标志:
client = MCPToolClient(mode="production")
client.use_production_mode = True
更新 tests/core/test_mode_selection.py,断言生产模式会通过 /mcp 调用 tools/list 和 tools/call,并断言模拟模式仍会发送 WebSocket type="step" 消息。
故障排除如何修复因 'No such container' 错误文本不同导致 Docker 清理验证在 Docker 29 和 Podman 上失败的问题?
不要依赖匹配 inspect 或 rm 的错误文本。应通过列出容器来验证删除,并将空结果视为成功:
docker ps --all --filter "name=^/<container-name>$" --format '{{.Names}}'
空结果表示容器已被删除;非零退出码表示容器引擎无法访问。对于 Podman,启动容器时请使用:
--stop-timeout 0
这样 docker rm --force 就不会在 SIGKILL 之前等待默认的停止超时时间。此外,避免断言 CapDrop == ["ALL"],因为 Podman 会逐个报告被丢弃的 capability。应改为验证容器的 capability 边界集合(CapBnd)为空;即使边界 capability 仍然存在,非 root 用户的 CapEff 也可能为 0。针对 Docker 29 和 Podman 的输出添加特定于引擎的单元测试。
informationalOpenEnv RFC 005 的状态是什么?HarnessEnvironment 与 openenv.core.harness 有何不同?
RFC 005 仍然有效,并已在 main 上通过 PR #1097–#1100 实现。对于该 RFC 的多轮外部 harness 模式,请将 HarnessEnvironment 与 AgenticHarnessAdapter 配合使用。外部 harness 在环境内部运行,OpenEnv 通过 MCP 注入工具,每次 step() 调用代表一个对话轮次,而 harness 在 episode 内跨轮次保留上下文。在“Evaluate Claude Code in an Environment”教程和 examples/claude_code_harness_eval 中提供了一个完整的 Claude Code 在 τ²-bench 上的运行示例。
由 #471/#652 在 openenv.core.harness 下引入的 API——如 ResourceSession、HarnessAdapter、MCPHarnessAdapter、CLIHarnessAdapter 和 build_harness_rollout_func——是一个独立的会话/运行时层,而非 RFC 005 的实现。请将它们用于较低层级的会话/资源管理;将 HarnessEnvironment/AgenticHarnessAdapter 用于 RFC 005 风格的多轮 agent-in-environment rollout。更新后的 harness 文档会根据哪个组件拥有 agent loop 来组织这些选项。
故障排除如何修复 openenv init 之后重复的 Python .venv 层导致 Docker 镜像大小翻倍的问题?
生成的 Dockerfile 先显式复制了 /app/env/.venv,随后又复制了已经包含 .venv 的 /app/env,从而产生了两个约 500 MB 的层。请将 OpenEnv 升级到包含服务端 Dockerfile 模板修复的版本,或者手动修补生成的 Dockerfile。移除单独的 virtualenv 复制步骤,只保留项目复制,并创建一个符号链接:
# 删除这一行:
# COPY --from=builder /app/env/.venv /app/.venv
# 只复制一次项目,包括其内嵌的 .venv:
COPY --from=builder /app/env /app/env
# 为依赖 /app/.venv 路径的情况提供兼容性:
RUN ln -s /app/env/.venv /app/.venv
如果你的模板使用了 --chown,请在保留的 COPY 指令上保留这些标志。不使用缓存重新构建并验证各层:
docker build --no-cache -t your-image .
docker history your-image
# 或者
dive your-image
现在 virtualenv 应该只出现在一个大层中,符号链接增加的体积可以忽略不计。