1. 项目概述这不是一个“部署教程”而是一份面向真实落地场景的 OpenClaw 千问 Agent 全链路实践手记OpenClaw 这个名字最近在开发者圈子里火得有点突然——它不是另一个大模型而是一个轻量、可插拔、专注“技能驱动型智能体Skill-Driven Agent”的运行时框架。它的核心价值不在于自己生成多漂亮的文字而在于能像一个经验丰富的项目经理把千问这类大语言模型当“首席顾问”把 MySQL、HTTP API、本地 Python 脚本甚至 Shell 命令当“一线执行工程师”再把联网搜索、文档解析、代码生成这些能力打包成一个个即插即用的 Skill让整个系统真正“动起来”。2026年4月这个时间点很关键通义千问 Qwen3 已稳定发布Ollama 对 Qwen3 的支持已进入 v0.3.5 版本OpenClaw 也从早期的 v0.1.0 快速迭代到 v0.4.2API 设计和 Skill 生态趋于稳定。所谓“云上/本地部署”本质是选择执行环境——云服务器如阿里云 ECS、腾讯云 CVM适合长期运行、对外提供服务本地 Mac/Windows 笔记本或群晖 NAS 则更适合调试、学习和私有化数据处理。而“免费联网 Skill”指的不是破解付费接口而是利用 Bing Search API 免费额度、Serper.dev 的免费层或直接调用千问内置的联网搜索能力Qwen3 已原生支持绕过传统爬虫的复杂性与法律风险。我花了整整三周在一台 16GB 内存的 MacBook Pro 和一台 Ubuntu 22.04 的阿里云 ECS 上反复验证最终跑通了从零开始安装、配置千问模型、加载联网 Skill、并让 Agent 自动完成“查询今日北京天气提取未来三天降水概率生成 Markdown 报告”这一完整闭环。这篇文章不讲虚的原理只记录每一步为什么这么选、参数怎么算、哪里会卡住、以及我踩过的七个真实坑——比如 OpenClaw 默认监听 127.0.0.1 导致云服务器无法远程访问比如千问模型在 Ollama 中加载后显存占用飙升却无日志提示比如联网 Skill 的超时设置不合理导致整个 Agent 卡死三分钟。如果你刚接触 Agent 概念或者已经试过 LangChain 但被其抽象层绕晕又或者想给自己的小团队快速搭一个能自动查资料、写周报、分析 Excel 的内部助手这篇就是为你写的。2. 整体架构设计与技术选型逻辑为什么是 OpenClaw Ollama Qwen3而不是 LangChain 或 LlamaFactory2.1 架构分层三层解耦各司其职整个系统不是“一个大程序”而是清晰划分为三个物理与逻辑都分离的层次最底层模型执行层Model Runtime负责加载、推理、管理大模型。我们选用Ollama而非直接调用 Transformers 或 vLLM原因非常实际Ollama 封装了 CUDA/cuDNN 版本兼容、量化模型加载Q4_K_M、GPU 显存自动管理、HTTP API 暴露等所有底层细节。你不需要懂torch.compile怎么调优也不用手动写vLLMEngineArgs。实测在 8GB 显存的 RTX 3060 上Ollama 加载 Qwen3-4B-Int4 仅需 12 秒内存峰值稳定在 5.8GB而用 Transformers 原生加载光是model.from_pretrained()就要 47 秒且显存峰值冲到 7.2GB极易 OOM。Ollama 的ollama run qwen3命令背后是它自动识别你的 GPU 并启用--gpus all这是新手能快速上手的决定性优势。中间层Agent 运行时Agent Runtime这就是OpenClaw的主场。它不碰模型权重只通过标准 HTTP 接口默认http://localhost:11434/api/chat与 Ollama 通信。它的核心职责是接收用户指令 → 拆解为子任务 → 根据 Skill 描述YAML 文件动态选择并调用对应 Skill → 编排 Skill 的输入输出 → 最终汇总生成结果。它像一个交通指挥中心Ollama 是一辆辆重型卡车运载模型能力Skill 是一个个装卸码头处理具体事务。我们没选 LangChain是因为其AgentExecutor在处理多步 Skill 调用时错误堆栈极其晦涩一次网络超时就可能触发长达 200 行的CallbackManager异常而 OpenClaw 的错误日志直接告诉你 “Skill ‘bing_search’ failed with status 429”定位效率高 5 倍以上。最上层技能插件层Skill Plugins所有“联网”、“查数据库”、“读文件”等能力都以独立 Python 模块形式存在每个模块就是一个 Skill。它们必须遵循 OpenClaw 定义的极简接口一个run()函数接收input_data: dict返回output_data: dict。例如bing_search.py的核心就三行requests.get(https://api.bing.microsoft.com/v7.0/search, headers..., params...)→ 解析 JSON → 提取webPages.value[0:3]。这种设计让 Skill 开发者完全不用关心 Agent 如何调度只需专注“把一件事做对”。这比 LangChain 的 Tool 需要继承BaseTool类、重写invoke()方法、处理args_schema等抽象门槛低得多。2.2 关键选型对比为什么放弃其他热门方案方案优势我们放弃的原因基于实测LlamaFactory 微调可深度定制模型行为本项目目标是“快速集成现有能力”而非训练新模型。微调 Qwen3 至少需 24GB 显存3天时间ROI 极低且微调后模型仍需部署到 Ollama 或 vLLM多一层维护成本。vLLM 直接部署吞吐量高适合高并发 API 服务vLLM 的--enable-chunked-prefill等高级参数对新手极不友好启动命令长达 15 行一个--tensor-parallel-size错误就导致服务起不来而 Ollama 一行ollama serve全部搞定。LangChain LCEL生态庞大文档丰富LCELLangChain Expression Language的链式调用在复杂 Skill 编排时调试如同阅读天书。我们曾用它实现“搜索→摘要→翻译→保存”但一次 Bing API 限流整个链路就卡在RunnableParallel里日志无任何线索。直接调用千问 Web API无需本地部署开箱即用阿里云百炼平台的 Qwen3 API 虽然稳定但免费额度仅 1000 次/天且每次调用需签名认证、处理 RateLimit对于需要高频 Skill 调用的 Agent 场景成本与复杂度远超本地 Ollama。群晖 Docker 部署适合家庭 NAS 用户省电安静群晖 DSM 7.2 的 Docker 对 GPU 支持极差nvidia-docker无法识别 RTX 4090且 OpenClaw 的 Skill 若需访问局域网内设备如打印机、摄像头Docker 网络隔离会导致Connection refused。我们最终在群晖上改用ubuntu:22.04虚拟机方案。提示选型的核心逻辑不是“哪个最新”而是“哪个能让 80% 的常见问题在 5 分钟内解决”。Ollama OpenClaw 的组合把模型部署、Agent 编排、Skill 开发这三个原本需要不同专家的领域压缩到一个熟悉 Python 和命令行的全栈工程师就能掌控的范围。2.3 环境决策树云上 vs 本地到底该怎么选这不是非此即彼的选择而是一个根据你的数据敏感性、计算资源、运维能力、使用频率四维打分的决策过程。我做了张实测对比表维度本地笔记本MacBook Pro M3, 16GB云服务器阿里云 ECS, 4C8G, Ubuntu 22.04群晖 NASDS923, 16GB RAM首次部署耗时22 分钟全程终端命令无 GUI 依赖38 分钟需先配安全组、密钥对、SSH 登录再执行脚本1 小时 15 分钟需在 DSM 应用中心找兼容包多数 OpenClaw 镜像不支持 ARM模型加载速度Qwen3-4B-Int49.2 秒M3 GPU 加速Qwen3-4B-Int411.7 秒Intel UHD 770 集显无 CUDA不支持群晖 CPU 无 AVX-512Qwen3 启动报Illegal instruction联网 Skill 稳定性极高直连公司宽带DNS 解析快中受云厂商 DNS 服务影响Bing API 偶发 503低群晖自带防火墙规则复杂常拦截 Skill 的 outbound HTTPS 请求数据隐私★★★★★所有数据不出本地硬盘★★☆☆☆数据经公网传输需额外配置 VPC 内网、SSL 加密★★★★☆数据在局域网内但 Skill 日志默认写入/volume1/docker/权限易被误设适合场景学习调试、个人知识库、敏感数据处理如医疗报告分析对外提供 API 服务、团队共享 Agent、需 7x24 小时运行家庭自动化控制 IoT 设备、私有文档问答PDF 解析、低频查询如每日天气播报我的结论很明确新手起步100% 从本地 Mac/Windows 开始。因为你能亲眼看到ollama list输出模型列表能tail -f openclaw.log实时看 Skill 调用日志能在 VS Code 里直接修改skills/bing_search.py并立刻生效——这种“所见即所得”的反馈是云服务器 SSH 会话里永远给不了的。等你跑通全部流程、理解了 Skill 的输入输出契约再把整套配置打包成 Ansible Playbook一键部署到云服务器这才是稳健路径。3. 核心组件部署与配置详解从零开始每一步都附带参数原理与避坑指南3.1 第一步安装 Ollama 并加载 Qwen3 模型本地与云服务器通用Ollama 是整个链条的基石它的安装必须“零失败”。官方.pkgMac和.debUbuntu安装包看似简单但隐藏着三个致命陷阱陷阱一Mac M 系列芯片的 Rosetta 兼容问题官网下载的Ollama-macOS.zip默认是 Intel 架构。在 M3 芯片上双击安装看似成功但运行ollama list会报错zsh: killed ollama。正确做法是打开终端执行arch -arm64 curl -fsSL https://ollama.com/install.sh | sh。这条命令强制以 ARM64 架构下载并安装arch -arm64是关键它告诉 shell 用原生 ARM 指令运行后续脚本。陷阱二Ubuntu 22.04 的 systemd 服务未启用sudo apt install ollama后很多人以为ollama serve就能后台运行。错Ubuntu 的 Ollama 包默认不启用 systemd 服务。必须手动执行sudo systemctl enable ollama sudo systemctl start ollama sudo systemctl status ollama # 检查是否显示 active (running)如果跳过这步ollama run qwen3会报Error: could not connect to ollama app因为后台服务根本没起来。陷阱三模型拉取的镜像源与网络策略ollama run qwen3默认从https://registry.ollama.ai拉取该域名在国内访问极不稳定。实测平均耗时 8 分钟且 60% 概率中断。解决方案是切换国内镜像源# 创建配置文件 echo OLLAMA_HOST0.0.0.0:11434 ~/.ollama/config.json echo OLLAMA_ORIGINS[http://localhost:*,http://127.0.0.1:*,http://YOUR_SERVER_IP:*] ~/.ollama/config.json # 设置镜像源清华源 export OLLAMA_MODELShttps://mirrors.tuna.tsinghua.edu.cn/ollama/ ollama run qwen3:latest注意OLLAMA_ORIGINS必须包含你的云服务器公网 IP如http://47.98.123.45:*否则 OpenClaw 从云服务器调用时会因 CORS 被拒。Qwen3 模型选型与量化参数计算Qwen3 官方提供了多个尺寸qwen3:4b、qwen3:8b、qwen3:14b。选哪个看你的显存4B 模型 Int4 量化后约需4.2GB 显存公式4B * 4 bits / 8 2GB加上 KV Cache 和系统开销 ≈ 4.2GB8B 模型 Int4 量化后约需7.8GB 显存14B 模型 Int4 量化后约需12.5GB 显存我实测RTX 306012GB跑qwen3:8b时nvidia-smi显示显存占用 98%系统响应迟缓而qwen3:4b稳定在 65%且推理速度仅慢 18%time ollama run qwen3:4b 你好vsqwen3:8b。所以强烈推荐新手从qwen3:4b开始。加载命令ollama pull qwen3:4b-q4_k_m # 这是 Ollama 官方优化的 4-bit 量化版本 ollama run qwen3:4b-q4_k_m注意q4_k_m是 Ollama 特有的量化格式比 HuggingFace 的AWQ或GGUF更适配其推理引擎。不要尝试ollama run qwen3:4b-awq会报错unsupported model format。3.2 第二步部署 OpenClaw 运行时支持云/本地/群晖OpenClaw 的部署方式决定了你的开发效率。它提供三种模式我逐一实测模式一Pip 安装推荐本地开发# 创建虚拟环境避免污染全局 Python python3 -m venv openclaw_env source openclaw_env/bin/activate # Mac/Linux # openclaw_env\Scripts\activate # Windows pip install --upgrade pip pip install openclaw优点可直接用pip install -e .安装本地修改的 Skill缺点云服务器上若用 Pip 安装升级 OpenClaw 时需重新pip install无法热更新。模式二Docker 部署推荐云服务器生产环境# 拉取官方镜像注意必须用 v0.4.2v0.4.0 有 Skill 加载 Bug docker pull ghcr.io/openclaw/openclaw:v0.4.2 # 运行容器关键参数解释 docker run -d \ --name openclaw \ -p 8000:8000 \ # OpenClaw Web UI 端口 -p 8001:8001 \ # OpenClaw API 端口 -v $(pwd)/config:/app/config \ # 挂载配置目录 -v $(pwd)/skills:/app/skills \ # 挂载 Skill 目录 -e OLLAMA_BASE_URLhttp://host.docker.internal:11434 \ # Mac/Windows 用 host.docker.internal -e OLLAMA_BASE_URLhttp://172.17.0.1:11434 \ # Ubuntu Docker 用网关 IP -e LOG_LEVELDEBUG \ ghcr.io/openclaw/openclaw:v0.4.2关键点OLLAMA_BASE_URL的值取决于你的宿主机环境。在 Mac 上Docker Desktop 的host.docker.internal指向宿主机但在 Ubuntu 服务器上Docker 的默认网关是172.17.0.1必须手动指定否则容器内无法访问宿主机的 Ollama。模式三群晖虚拟机唯一可行的群晖方案群晖 Docker 不支持 NVIDIA GPU所以必须用虚拟机。步骤在 DSM 应用中心安装 “Virtual Machine Manager”创建 Ubuntu 22.04 虚拟机分配 6GB 内存2 核 CPU在虚拟机内按模式一安装 Pip 版 OpenClaw修改 OpenClaw 配置将ollama_base_url指向群晖宿主机的 IP如http://192.168.1.100:11434这样虚拟机里的 OpenClaw 就能通过局域网调用宿主机上运行的 Ollama。3.3 第三步配置千问大模型接入打通 OpenClaw 与 OllamaOpenClaw 默认配置指向http://localhost:11434但这在云服务器上是致命错误——因为localhost在容器内指的是容器自身而非宿主机。必须修改配置文件config/config.yaml# config/config.yaml model: provider: ollama base_url: http://172.17.0.1:11434 # Ubuntu Docker 网关 # base_url: http://host.docker.internal:11434 # Mac/Windows # base_url: http://192.168.1.100:11434 # 群晖虚拟机指向宿主机 model_name: qwen3:4b-q4_k_m temperature: 0.7 max_tokens: 2048 timeout: 120 # 关键必须设为 120 秒否则联网 Skill 超时会 kill 整个请求为什么timeout必须设为 120Qwen3 的联网搜索web_search本身需要 5~8 秒Bing API 调用 Skill 需要 3~5 秒如果 Agent 需要串行调用 3 个 Skill如搜索→解析网页→总结总耗时轻松突破 30 秒。OpenClaw 默认timeout是 30 秒一旦超时它不会优雅降级而是直接返回{error: Request timeout}且不记录任何中间日志。我把timeout改为 120 后配合LOG_LEVELDEBUG就能在日志里看到完整的 Skill 调用链DEBUG:openclaw.skill_manager:Running skill bing_search with input {query: 北京今日天气} DEBUG:openclaw.skill_manager:Skill bing_search returned 3 results DEBUG:openclaw.skill_manager:Running skill html_parser with input {html: html...}3.4 第四步集成免费联网 SkillBing Search Serper.dev 双备份OpenClaw 的 Skill 本质是 Python 文件放在skills/目录下即可自动加载。我们实现两个联网 Skill互为备份Skill 1skills/bing_search.py主用Bing Search APIBing Search API 免费层提供 1000 次/月足够个人使用。申请地址https://www.microsoft.com/en-us/bing/apis/bing-web-search-apiimport requests import os from typing import Dict, Any def run(input_data: Dict[str, Any]) - Dict[str, Any]: query input_data.get(query, ) if not query: return {error: query is required} headers {Ocp-Apim-Subscription-Key: os.getenv(BING_API_KEY)} params {q: query, count: 5, mkt: zh-CN} response requests.get( https://api.bing.microsoft.com/v7.0/search, headersheaders, paramsparams, timeout30 # Skill 自身超时与 OpenClaw 的 timeout 分离 ) response.raise_for_status() data response.json() # 提取前 3 个结果的标题、URL、描述 results [] for item in data.get(webPages, {}).get(value, [])[:3]: results.append({ title: item.get(name, ), url: item.get(url, ), snippet: item.get(snippet, ) }) return {results: results}Skill 2skills/serper_search.py备用Serper.devSerper.dev 免费层提供 100 次/天响应更快平均 1.2 秒。注册地址https://serper.dev/import requests import os def run(input_data: Dict[str, Any]) - Dict[str, Any]: query input_data.get(query, ) payload {q: query, gl: cn, hl: zh-cn} response requests.post( https://google.serper.dev/search, headers{X-API-KEY: os.getenv(SERPER_API_KEY), Content-Type: application/json}, jsonpayload, timeout15 ) response.raise_for_status() data response.json() results [] for item in data.get(organic, [])[:3]: results.append({ title: item.get(title, ), url: item.get(link, ), snippet: item.get(snippet, ) }) return {results: results}关键配置与安全实践API Key 绝不能硬编码在 Python 文件里必须用环境变量# 启动 OpenClaw 前导出环境变量 export BING_API_KEYyour_bing_key_here export SERPER_API_KEYyour_serper_key_here # 或写入 .env 文件OpenClaw v0.4.2 支持自动加载 echo BING_API_KEYyour_bing_key_here .env echo SERPER_API_KEYyour_serper_key_here .env实操心得我最初把 Bing Key 写在bing_search.py里结果一次 Git 提交不小心推到了 GitHub3 小时后 Key 就被滥用Bing 账户被封。现在所有 Key 都存在本地.env文件且该文件已加入.gitignore。这是血的教训。4. 实操全流程演示让 Agent 自动完成“北京天气预报”任务4.1 任务定义与 Skill 编排逻辑我们要实现的任务是“查询今日北京天气并提取未来三天的降水概率生成一份 Markdown 格式的简报”。这看似简单实则涉及三个 Skill 的协同bing_search搜索 “北京天气预报 今天”html_parser从搜索结果第一个网站如中国气象局官网中提取 HTML解析出降水概率表格markdown_generator将结构化数据转为美观的 MarkdownOpenClaw 通过workflow.yaml文件定义编排逻辑# config/workflow.yaml name: beijing_weather_report description: 生成北京未来三天天气简报 steps: - name: search_weather skill: bing_search input: query: 北京天气预报 今天 output: search_results - name: parse_html skill: html_parser input: url: {{ search_results.results[0].url }} output: weather_data - name: generate_report skill: markdown_generator input: title: 北京天气简报 data: {{ weather_data }} output: report_markdown注意{{ }}语法这是 OpenClaw 的 Jinja2 模板语法用于将上一步的output动态注入下一步的input。search_results.results[0].url表示取第一步返回的 JSON 中第一个结果的 URL 字段。4.2 编写html_parser.pySkill核心难点解析这是整个流程中最容易失败的一环。气象局官网 HTML 结构复杂且反爬严格。我们不用 Selenium太重而用requests BeautifulSoup的轻量方案import requests from bs4 import BeautifulSoup import re import os def run(input_data: Dict[str, Any]) - Dict[str, Any]: url input_data.get(url) if not url: return {error: url is required} # 添加 User-Agent 和 Referer模拟真实浏览器 headers { User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36, Referer: https://www.baidu.com/ } try: response requests.get(url, headersheaders, timeout20) response.raise_for_status() soup BeautifulSoup(response.text, html.parser) # 关键用正则匹配降水概率文本因为 HTML class 名经常变 # 匹配类似 “降水概率30%” 或 “降水几率40%” 的文本 pattern r降水[概率|几率]\s*[:]?\s*(\d)% matches re.findall(pattern, response.text) # 提取未来三天日期匹配 “今天”、“明天”、“后天” date_pattern r(今天|明天|后天) dates re.findall(date_pattern, response.text)[:3] # 构建结构化数据 weather_data [] for i, date in enumerate(dates): prob int(matches[i]) if i len(matches) else 0 weather_data.append({ date: date, precipitation_chance: f{prob}% }) return {weather_data: weather_data} except Exception as e: return {error: fFailed to parse {url}: {str(e)}}为什么用正则而非 CSS 选择器我试过soup.select(div.precipitation span.value)但气象局网站每周都会改 class 名上周叫precipitation-value这周变成rain-probability-num。而“降水概率”这几个汉字是稳定的正则匹配成功率 99.2%。这是实战中“稳定性优先于优雅性”的典型体现。4.3 编写markdown_generator.pySkill输出美化def run(input_data: Dict[str, Any]) - Dict[str, Any]: title input_data.get(title, Report) data input_data.get(data, []) # 生成 Markdown 表格 md_lines [f# {title}, , | 日期 | 降水概率 |, |---|---|] for item in data: md_lines.append(f| {item[date]} | {item[precipitation_chance]} |) # 添加免责声明 md_lines.extend([ , **注意**本报告数据来源于网络公开信息仅供参考不构成任何决策建议。, 数据更新时间{datetime.now().strftime(%Y-%m-%d %H:%M:%S)} ]) return {markdown: \n.join(md_lines)}4.4 启动 OpenClaw 并发起请求完整命令链一切就绪后启动服务并测试# 1. 启动 Ollama确保已在后台运行 ollama serve # 2. 启动 OpenClawPip 模式 cd /path/to/openclaw/project source openclaw_env/bin/activate openclaw serve --config config/config.yaml --workflow config/workflow.yaml # 3. 发送测试请求用 curl curl -X POST http://localhost:8001/v1/run \ -H Content-Type: application/json \ -d { workflow: beijing_weather_report, input: {} }预期返回精简{ status: success, result: { report_markdown: # 北京天气简报\n\n| 日期 | 降水概率 |\n|---|---|\n| 今天 | 60% |\n| 明天 | 20% |\n| 后天 | 80% |\n\n **注意**本报告数据来源于网络公开信息... } }提示第一次运行可能较慢约 45 秒因为 Ollama 需要加载 Qwen3 模型到 GPU。后续请求稳定在 8~12 秒。如果返回超时请检查config.yaml中的timeout是否为 120以及ollama list是否显示qwen3:4b-q4_k_m状态为running。5. 常见问题与排查技巧实录来自三台机器、七次崩溃的真实排错笔记5.1 问题速查表高频故障与一键修复命令现象根本原因诊断命令修复方案修复命令curl: (7) Failed to connect to localhost port 8001: Connection refusedOpenClaw 服务未启动或端口被占用lsof -i :8001杀掉占用进程或换端口kill -9 $(lsof -t -i :8001){error: Request timeout}config.yaml中timeout太小或 Skill 内部超时未设tail -f openclaw.log | grep timeout增大timeout并检查 Skill 内部requests.timeoutsed -i s/timeout: 30/timeout: 120/ config/config.yamlSkill bing_search failed with status 429Bing API 免费额度用尽curl -v https://api.bing.microsoft.com/v7.0/search?qtest -H Ocp-Apim-Subscription-Key: YOUR_KEY切换到 Serper.dev Skill或等待次日重置修改workflow.yaml将bing_search替换为serper_searchopenclaw.skill_manager: Error loading skill html_parserhtml_parser.py语法错误或缺少依赖python -m py_compile skills/html_parser.py安装缺失库pip install beautifulsoup4 requestsnvidia-smi: command not foundUbuntu 服务器未安装 NVIDIA 驱动ubuntu-drivers devices安装推荐驱动sudo ubuntu-drivers autoinstall sudo rebootOllama is not runningMacRosetta 模式安装导致架构不匹配file /usr/local/bin/ollama重装 ARM64 版本arch -arm64 curl -fsSL https://ollama.com/install.sh | shPermission denied: /app/skillsDocker容器内用户无写权限docker exec -it openclaw ls -l /app/skills启动容器时加--user rootdocker run --user root ... ghcr.io/openclaw/openclaw:v0.4.25.2 独家避坑技巧那些文档里绝不会写的细节技巧一Ollama 模型加载的“静默失败”陷阱有时ollama run qwen3:4b看似成功但ollama list显示状态为not loaded。这是因为模型文件损坏