OpenHands 开源 AI Agent 部署实战
OpenHands 是一个开源的 AI Agent 框架,支持自定义工具调用和复杂任务自动化。本教程涵盖 Docker 部署、本地开发、工具注册全流程。
OpenHands(原 OpenIntern)是由 微软开源的 AI Agent 框架,能够自主执行复杂的多步骤任务。它可以像人类一样操作浏览器、读写文件、执行代码,是目前最强大的开源 Agent 之一。
Table of Contents
OpenHands 是什么
OpenHands 的核心能力:
- 浏览器操作 — AI 可以自主浏览网页、填写表单、点击按钮
- 代码执行 — 内置 Jupyter 兼容的执行环境
- 文件操作 — 读写本地文件、执行 Shell 命令
- 工具调用 — 支持自定义 Python 函数作为工具
- 多模型支持 — Claude 3.5 / GPT-4 / Gemini / 本地模型
| 对比项 | OpenHands | LangChain Agents |
|---|---|---|
| 浏览器自动化 | ✅ 内置 Playwright | ❌ 需自行集成 |
| 代码执行 | ✅ Jupyter 内核 | ❌ 需自行集成 |
| Web UI | ✅ 开箱即用 | ❌ 需自行开发 |
| 部署难度 | ⭐ 简单(Docker) | ⭐⭐⭐ 复杂 |
Docker 快速部署
最简单的部署方式,一行命令启动:
$
docker run -it \
--name openhands \
-p 3000:3000 \
-e OPENHANDS_MODEL=anthropic/claude-sonnet-4-5 \
-e OPENHANDS_API_KEY=sk-ant-xxxxx \
-v openhands_data:/app/data \
openhands/openhands:latest启动后访问 http://localhost:3000 打开 Web UI。
使用 Docker Compose(推荐)
version: '3.8'
services:
openhands:
image: openhands/openhands:latest
container_name: openhands
restart: unless-stopped
ports:
- "3000:3000"
environment:
- OPENHANDS_MODEL=anthropic/claude-sonnet-4-5
- OPENHANDS_API_KEY=${OPENHANDS_API_KEY}
- OPENHANDS_SANDBOX_TYPE=local
volumes:
- openhands_data:/app/data
# GPU 支持(可选)
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all
# capabilities: [gpu]
volumes:
openhands_data:
$
export OPENHANDS_API_KEY=sk-ant-xxxxx
docker compose up -d本地开发环境配置
安装依赖
$
git clone https://github.com/All-Hands-AI/OpenHands.git
cd OpenHands
uv venv && source .venv/bin/activate
uv pip install -e .
# 安装 Playwright 浏览器
playwright install chromium配置环境变量
$
# 创建 .env 文件
cat > .env << 'EOF'
OPENHANDS_MODEL=anthropic/claude-sonnet-4-5
OPENHANDS_API_KEY=sk-ant-xxxxx
OPENHANDS_SANDBOX_TYPE=local
EOF启动开发服务器
$
python openhands/app/app.py
开发模式优势
本地开发可以直接修改源码、调试 agent 行为、使用 IDE 的断点调试功能。适合需要深度定制 OpenHands 的用户。
本地开发可以直接修改源码、调试 agent 行为、使用 IDE 的断点调试功能。适合需要深度定制 OpenHands 的用户。
自定义工具注册
OpenHands 支持通过 Python 装饰器注册自定义工具,让 Agent 可以调用任意 API。
创建自定义工具
# tools/custom_tools.py
from openhands.tools import tool
@tool
def search_hackernews(query: str) -> str:
"""Search Hacker News for articles matching the query.
Args:
query: Search keywords (e.g., 'AI agents', 'Rust web frameworks')
Returns:
Top 5 matching articles with titles, scores, and URLs
"""
import requests
from datetime import datetime
# 使用 Hacker News API
base_url = "https://hn.algolia.com/api/v1"
# 先搜索
resp = requests.get(f"{base_url}/search", params={"query": query, "tags": "story", "hitsPerPage": 5})
data = resp.json()
results = []
for hit in data.get("hits", []):
title = hit.get("title", "Untitled")
score = hit.get("points", 0)
url = hit.get("url", f"https://news.ycombinator.com/item?id={hit['objectID']}")
date = datetime.fromtimestamp(hit.get("created_at_i", 0)).strftime("%Y-%m-%d")
results.append(f"- [{title}]({url}) ⬆️{score} ({date})")
if not results:
return f"No results found for '{query}'"
return f"Top results for '{query}':\n" + "\n".join(results)
@tool
def get_github_trending(language: str = "python", since: str = "daily") -> str:
"""Get trending GitHub repositories.
Args:
language: Programming language filter (default: python)
since: Time period: daily, weekly, monthly (default: daily)
Returns:
Top 10 trending repositories with stars and description
"""
import requests
url = f"https://api.github.com/search/repositories"
params = {
"q": f"language:{language} created:>{get_date(since)}",
"sort": "stars",
"order": "desc",
"per_page": 10
}
headers = {"Accept": "application/vnd.github.v3+json"}
resp = requests.get(url, params=params, headers=headers)
data = resp.json()
results = []
for repo in data.get("items", []):
name = repo["full_name"]
stars = repo["stargazers_count"]
desc = repo.get("description", "No description")
results.append(f"- **{name}** ⭐{stars}: {desc}")
return "\n".join(results) if results else "No trending repos found"
def get_date(since: str) -> str:
from datetime import datetime, timedelta
days = {"daily": 1, "weekly": 7, "monthly": 30}.get(since, 1)
return (datetime.now() - timedelta(days=days)).strftime("%Y-%m-%d")
注册工具
在 config.toml 中添加:
[tools]
enabled = ["search_hackernews", "get_github_trending"]
[[tool_dirs]]
path = "./tools"
Web UI 使用指南
OpenHands 的 Web UI 包含三个主要区域:
- 任务输入框 — 描述你想让 Agent 执行的任务
- 执行日志 — 实时显示 Agent 的思考和行动
- 文件浏览器 — 查看 Agent 创建/修改的文件
任务示例
在任务框中输入:
$
Search Hacker News for the best articles about AI coding assistants from the past week.
Create a markdown file called ai_coding_assistants.md with a summary of the top 5 articles,
including the title, URL, score, and a one-sentence description of each.Agent 会自动:
- 调用
search_hackernews工具 - 分析结果并决定内容
- 创建 markdown 文件
- 将结果写入文件
实战任务示例
1. 自动化代码审查
$
Clone the repository https://github.com/torvalds/linux and run a code review
on the most recent 10 commits. Create a file called code_review.md with a summary
of any potential issues found, categorized by severity.2. 数据分析与可视化
$
Download the CSV file from https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv.
Create a Python script that generates 4 visualizations (histogram, scatter plot,
pair plot, box plot) and saves them as PNG files in the current directory.3. 自动化测试生成
$
Read the file /path/to/my_module.py. Generate comprehensive unit tests using pytest.
Save the tests to test_my_module.py. Make sure to cover all public functions
with at least 3 test cases each (normal, edge, and error cases).常见问题
Q: Agent 执行任务时卡住不动
增加 timeout 或使用更长的 max_steps:
# 在 config.toml 中
[agent]
max_steps = 100 # 默认 30
llm_timeout = 300 # 秒
Q: Playwright 浏览器报错
$
playwright install chromium --with-depsQ: 如何使用本地模型
配置 Ollama 作为后端:
OPENHANDS_MODEL=ollama/llama3.2:3b
OPENHANDS_BASE_URL=http://localhost:11434/v1
OPENHANDS_API_KEY=ollama # Ollama 不需要真实 key
Advertisement