想让一个智能体自己改代码、跑测试、开 PR,又不想把仓库交给云服务?OpenHands(All-Hands-AI 出品,原 OpenDevin,75K+ stars,MIT 协议)是这条路上最成熟的开源选项:它把智能体的动作——写码、执行命令、浏览网页、跑测试——全部关进 Docker 沙箱容器,宿主机只挂载工作区目录。云 API 也好、本地 Ollama 也好,模型只是大脑;沙箱是它的手,隔离是它的安全带。
本篇按官方文档与社区实测走通:CLI 安装、GUI 启动、接入本地 Ollama 模型、绕开 Docker 网络三坑,最后跑一个真实的修复任务。全部命令来自 docs.openhands.dev 官方文档原文或其直接改写,社区踩坑经验单独标注。
前置准备:Python 3.12(社区实测 CLI 要求 3.12,3.11 会失败、3.14 尚不支持——以官方仓库为准);Docker 已安装且在运行;接本地模型另备 Ollama 与足够的内存或显存。
沙箱容器会真实执行智能体生成的命令:挂载给它的目录就是它的活动范围。别把家目录、含密钥的目录挂成工作区;敏感仓库先在分支或副本上试跑,观察它改了什么再放行。
Step 1:安装 CLI:两条路线
最省事的路线是 uv 临时拉起,不污染全局环境:
# 路线 A:uv 一行起(推荐,无需安装到全局)
uvx --python 3.12 --from openhands-ai openhands
# 路线 B:pip 安装(注意包名带 -ai 后缀)
pip install openhands-ai
# 建议加个 alias
alias oh="uvx --python 3.12 --from openhands-ai openhands"
头一个坑就在包名上:PyPI 上叫 openhands 的是另一个无关项目,装错了自然跑不起来——这是社区反馈里最常见的头回踩坑点,正确包名是 openhands-ai。装完在项目目录里直接运行 openhands(或在项目外用 WORKSPACE_DIR 指定工作区),交互式配置会引导你选模型、填 Key。
从项目目录里启动,那个目录自动成为工作区,比传参指定路径更不容易挂错目录。先在一个无关紧要的练手仓库里跑通全流程,再换真实项目。
Step 2:起 Web GUI:聊天面板、文件树与实时终端
命令行够用,但看智能体干活还是 GUI 直观:
# Web GUI:聊天面板 + 文件浏览器 + 实时终端
openhands serve --mount-cwd # --mount-cwd 把当前目录挂为工作区
# 打开它输出的本地地址(如 http://localhost:3000)
serve 模式会在幕后自动拉起一个 Docker 容器作为沙箱——智能体写的每条命令都在容器里执行,与你的宿主机隔离。浏览器里你能实时看到它改了哪个文件、跑了哪条命令、测试结果如何,出问题时终端输出全部可回看。
GUI 依赖 Docker:没有运行中的 Docker 环境,沙箱起不来,智能体无法执行任何动作——「agent 启动后一动不动」多半是这一层的问题,先确认 Docker 状态再查模型配置。
Step 3:接入 Ollama:上下文长度是生死线
OpenHands 底层用 LiteLLM,所以本地 Ollama 就是配一个 OpenAI 兼容端点的事。官方 local-llms 文档给出的 Ollama 启动参数里有一条决定成败:
# 官方 local-llms 文档:上下文长度必须调大
export OLLAMA_CONTEXT_LENGTH=32768
export OLLAMA_HOST=0.0.0.0:11434
export OLLAMA_KEEP_ALIVE=-1
ollama serve # 前台运行;需要后台用 nohup 或 systemd 托管
ollama pull qwen3.6:35b-a3b
OLLAMA_CONTEXT_LENGTH 是本地跑 OpenHands 的生死线:Ollama 默认 4096 的上下文连 OpenHands 的系统提示都装不下,智能体会表现异常甚至完全不听指挥——官方文档原话是「默认值太小,连系统提示都放不进去」。拉模型前把这行环境变量设好,服务重启才生效。
然后在 GUI 里配连接:Settings 打开 Advanced 开关,Custom Model 填模型 ID(前面必须加 openai/ 前缀),Base URL 填 Ollama 地址,API Key 随便填个非空占位:
# GUI: Settings -> LLM -> 开启 Advanced
# Custom Model : openai/qwen/qwen3.6-35b-a3b (前缀 openai/ 必须有)
# Base URL : http://host.docker.internal:11434/v1
# API Key : local-llm (占位即可,非空就行)
API Key 必须非空:Ollama 本身不校验 Key,但底层的 LiteLLM 要求非空值,留空会直接连接失败。社区惯用 local-llm 或 ollama 占位,别在这上面浪费排查时间。
Step 4:Docker 网络三坑:localhost、网关与设置覆盖
本地模型接入的报错大多集中在这三层,按顺序排查:
# 坑 1:容器里访问宿主机不能用 localhost / 127.0.0.1
# 必须用 host.docker.internal
# 坑 2:Linux 上该主机名默认不解析,启动 OpenHands 容器时补:
docker run ... --add-host=host.docker.internal:host-gateway
# 坑 3:UI 设置与环境变量设成同一个值,避免互相覆盖
LLM_MODEL=ollama/qwen2.5-coder:7b
LLM_BASE_URL=http://host.docker.internal:11434
LLM_API_KEY=ollama
这三个坑在社区 issue 里有完整轨迹:症状高度一致——智能体正常启动,头一次模型调用立刻报连接错误。修复顺序永远是:地址改 host.docker.internal、Linux 补 --add-host、UI 与环境变量双写保持一致。第三条是因为历史上 UI 设置曾在某些版本里覆盖环境变量,双写是最稳的姿势。
排查连接问题时先在宿主机 curl 一下 Ollama 的 /v1/models 确认服务本身活着,再去查容器网络——把「模型服务挂了」和「容器连不上」两种故障分开,能省一半排查时间。
顺带说清容器架构,后面排查会轻松很多:serve 模式下 OpenHands 本体跑在宿主机,每次会话另起一个 runtime 容器当沙箱,两者通过 Docker API 通信。所以连接问题分属两段——OpenHands 到模型服务的一段(本节的网络三坑),和 OpenHands 到 Docker 的一段(Docker 进程没起、docker.sock 权限不对)。报错信息里带模型名或 HTTP 状态的查前一段,提 docker 或 sandbox 的查后一段,别混在一起猜。
Step 5:跑一个真实的修复任务
cd 到项目目录启动,把任务描述按「文件 + 症状 + 预期」给足:
# 好提示:文件 + 症状 + 预期行为
Fix the auth bug in src/auth/login.py where JWT tokens
expire immediately. The issue is in the token expiry
calculation. After fixing, run the test suite and make
sure all existing tests pass.
# 差提示:意图模糊,模型只能瞎猜范围
Fix the login.
任务运行时它会自己列计划、改文件、跑测试、看报错、再改——你的角色是审阅每一步的 diff,而不是盯着进度条。发现方向错了立刻打断,用一句话纠正而不是删掉重来。任务完成后先看它的测试是否真的跑过,再人工过一遍关键改动。审阅节奏上建议按「计划批准、中途抽查、收尾细看」三段投入注意力:开始时确认它的计划没有越出任务范围,中途只在关键节点(删文件、改配置、装依赖)介入,收尾时把 diff 从头到尾过一遍——把有限的注意力花在刀刃上,比全程紧盯更可持续。
上下文管理同样影响质量:任务跨多轮推进时,让它在收尾阶段把「做了什么、改了哪些文件、还剩什么没做」写成一段总结存进仓库(或贴进 PR 描述)。这段总结就是你下一次会话的接续点,比翻聊天记录可靠得多。
接 Ollama 等本地模型时,社区实测存在原生工具调用兼容问题(模型输出原始 JSON 而非执行动作)。CLI 可用 --llm-native-tool-calling false 显式关闭原生工具调用;该行为随版本演进,以官方文档与 issue 区的当前结论为准。云端模型(Claude/GPT 系列)无此问题。
让它跑长任务前,先在仓库里 git commit 干净的工作区。智能体的每步改动可回看,但「一键回滚到起点」永远是最快的保险绳。
Step 6:本地模型选型与预期管理
官方文档在 local-llms 页写得很坦诚:本地模型跑不好,问题多半在模型本身而非配置。社区实测口径如下:
# 现实预期(社区实测口径,随模型迭代更新)
OpenHands + 云 API 内存 8GB 无需 GPU 效果好,按 token 付费
OpenHands + 7B 本地模型 内存 16GB 显存 8GB 能跑,常规划差、循环烧 token
OpenHands + 14B+ 本地 内存 32GB 显存 16GB+ 社区报告 qwen2.5-coder-14b-instruct 表现稳定
务实的上线路径是反过来走:先用云 API 把流程跑顺、建立「正常表现」的基准,再切本地模型对比降级程度——而不是一上来就在本地小模型上怀疑配置。官方文档还列了社区验证过工具调用可用的模型(如 qwen2.5-coder-14b-instruct),选型直接从这份清单挑,别凭参数量猜。
团队私有化部署的常见形态:一台带 GPU 的内网机器跑 14B 级模型 + Ollama,开发者各自跑 OpenHands CLI 连过去。数据不出内网,成本一次投入——这是它对比云订阅的核心优势。
预期效果自查:GUI 能打开并完成 LLM 配置;一个修复任务跑完且测试真的通过(不是模型口头声称);改动的 diff 你能逐行看懂。三条全过,说明沙箱、模型、任务三层链路都通了,可以接真实项目。
常见问题 FAQ
和 Claude Code、Codex CLI 什么关系?形态不同:Claude Code 是官方订阅制的终端智能体,OpenHands 是开源自托管、模型可换(LiteLLM 支持上百供应商)的沙箱平台。要数据不出门、模型自选、架构透明,OpenHands 是少数能自洽闭环的选择;要开箱即用与效果上限,云托管方案仍占优。
能完全离线运行吗?模型层可以:本地 Ollama 全程离线。但拉镜像、装依赖、更新 OpenHands 本体需要联网——离线环境要提前在有网的机器上备好模型权重、运行时镜像与安装包。
Windows 能跑吗?可以,前提是装好 Docker Desktop;CLI 走 WSL2 或原生 Python 3.12 环境均可。社区反馈 Windows 上 Docker 网络同样用 host.docker.internal,坑位与 Linux 一致但 --add-host 通常不需要——遇到连接问题优先查 Docker Desktop 的网络设置。