OpenClaw 接入 Ollama 本地模型:配置避坑与工具调用实战 简介面向本地大模型应用开发者代码包演示如何将OpenClaw连接到Ollama运行时实现支持工具调用的本地模型部署。通过OpenAI兼容API完成集成开发者可借助自动发现机制识别具备工具能力的模型也可手动指定推理模型与上下文窗口参数。包内共3个文件包含HTML页面、inscode配置及gitignore文件整体仅7KB轻量易用。已有182人学习适合希望摆脱云端API限制、在本地环境快速验证工具调用场景的开发者。内容涵盖从安装Ollama、拉取模型到显式配置与故障排除的完整思路可帮助读者避开常见集成坑点直接上手构建私有化智能助手。1. 把 OpenClaw 接到 Ollama 本地模型省掉的不只是网络延迟如果你在内网隔离环境里跑过 Agent大概率被两个问题卡过一是云端模型不让出网二是即使能调通云端接口权限和脱敏流程也能把你耗到怀疑人生。OpenClaw 集成 Ollama 本地模型这个代码包解决的就是这两件事——把 OpenClaw 的模型后端从云端切到本机 11434 端口所有对话和工具调用都在本地完成。它适合两类人一类是已经有 Ollama 和本地模型、但不想研究 OpenClaw 配置结构的人另一类是手里只有 CPU 也想跑通完整 Agent 链路的人。面对一套直接可用的源码包你要做的只是按步骤装齐环境、核对配置、跑一遍验证脚本。下面是我拆包复现的过程配置、参数和踩过的坑都在后面。2. 对接方式与选型OpenAI 兼容接口还是 Ollama 原生接口2.1 OpenClaw 的模型后端到底长什么样OpenClaw 是一个命令行形态的 Agent 框架核心能力是工具调用和任务编排但它本身不携带大模型。框架里有一个独立的模型适配层负责把用户消息和工具定义翻译成模型需要的请求体再发到某个模型服务上最后把模型返回的增量内容解析回框架。适配层默认做的是 OpenAI 协议那一套请求体是 messages 数组返回体是 choices 数组工具调用走 tool_calls 字段。这就引出一个关键点OpenClaw 并不在乎模型服务是谁提供的它在乎的是你给它的 base_url、model 和 api_key 三个字段能不能拼出一个可用的 OpenAI 风格接口。所以把一个本地模型服务接进来本质上是找一个跑在本机的、能说 OpenAI 风格协议的模型服务而 Ollama 在这个场景下几乎是现成的答案。Ollama 负责模型下载、显存调度和推理执行对客户端表现成一个本地 OpenAI API。这种设计有个很实际的好处排错范围被压缩得很小。如果集成后对话不通问题只会出现在三个地方——配置文件的 base_url 写没写对、模型名和本地是否一致、Ollama 服务本身是否在监听。你不需要去翻 OpenClaw 框架内部的请求构造逻辑因为它在模型适配层这部分是通用的出问题的概率很低。我一般会在动手前先确认一件事OpenClaw 和 Ollama 是不是跑在同一台机器上。同机部署时网络层面最简单base_url 直接写 127.0.0.1不需要考虑跨机防火墙、监听地址和鉴权这些额外变量。如果做不到同机那就要在第 3 章里的环境准备阶段多做一些网络配置后面会提到。2.2 两种接口的差异与选择一个请求从 OpenClaw 到本地模型的完整链路接 Ollama 有两条路走 OpenAI 兼容接口也就是 /v1/chat/completions或者走 Ollama 原生接口 /api/chat。这两条路的差别比大多数刚接触的人想象得更大。先说 OpenAI 兼容接口。它的核心价值在于消息结构完全对齐 OpenAI 标准特别是模型返回的 tool_calls 字段。OpenClaw 的工具调用逻辑就是解析这个字段来决定下一步执行哪个函数字段结构对不对直接决定工具调用能不能触发。走兼容接口这块不需要额外处理OpenClaw 拿到的返回体和它对接云端模型时拿到的完全一样。再走 Ollama 原生接口就折腾了。原生接口的返回结构里内容在 message.content 里工具调用格式也和 OpenAI 不完全一致。理论上也能接但要多写一层转换逻辑把原生返回转成 OpenAI 风格。这层转换不仅要处理正常回复还要处理工具调用、流式输出中断、多轮 history 拼接维护成本比想象中高。最尴尬的是你费劲写完转换层一旦想换另一个本地推理引擎这套代码基本作废。我这次复现实测下来结论很明确用 OpenAI 兼容接口。即使你后续想换其他本地推理服务只要对方提供了 OpenAI 兼容端点这套配置基本可以平移。下面这张表是我整理接口差异时用的你可以直接拿来当选型参考。对比项OpenAI 兼容接口 (/v1)Ollama 原生接口 (/api)消息结构直接对齐 OpenAI 标准需要用转换层适配工具调用tool_calls 原生支持需要额外解析和重包装切换推理引擎的成本低兼容端点普遍存在高转换层无法复用排查问题的复杂度低返回体可读性强中需要先弄清结构差异正确选型之后完整请求链路是这样的OpenClaw 进程把整个 messages 列表序列化成 JSONPOST 到 base_url 指向的 /v1/chat/completions。Ollama 收到请求后按请求体里的 model 名找到本地模型完成推理再把回答包装成 OpenAI 风格的 JSON 返回。OpenClaw 解析到 choices[0].message 里的 content 或 tool_calls继续后面的任务编排。整个过程不经过任何外部网络。选型这一步容易被忽略的还有一个点Ollama 原生接口虽然也能跑但你一旦想切换到另一款推理引擎原生接口的切换成本远高于 OpenAI 兼容接口。以我的经验把接口选型当成一块可替换组件来设计后面换模型、换引擎都会省心很多。这个代码包默认就走的兼容接口这也是我推荐直接用它而不是自己从零封装的原因。3. 环境准备装 Ollama、拉模型、把服务暴露给 OpenClaw3.1 安装 Ollama 并确认服务端口这次复现是在一台 Ubuntu 服务器上跑的OpenClaw 和 Ollama 同机部署。如果你手头是 macOS安装和验证的命令基本一致Windows 版本装完是后台服务原理一样只是没有 systemd 这一层。安装用官方一行命令装完自动注册服务curl -fsSL https://ollama.com/install.sh | sh # 安装完成后Ollama 会注册为系统服务并监听 11434 端口装完先确认服务状态这一步不能省systemctl status ollama # 看到 active (running) 说明服务已拉起 curl http://127.0.0.1:11434/api/tags # 返回 JSON 数组说明服务可访问空数组是正常的因为还没拉模型这里有个细节如果你之前装过旧版本 Ollama环境变量和配置可能残留安装新版本后不一定会自动覆盖。遇到这种情况我会先把旧配置清理干净再装避免后面排查时多一层干扰。11434 是 Ollama 的默认端口OpenClaw 配置里的 base_url 也会用到这个端口所以这一步确认清楚是关键。3.2 拉取模型并核对模型名服务跑起来之后拉一个能用的公开模型。Ollama 的模型拉取命令和镜像仓库的 tag 概念很像模型名由名称加标签组成标签一般表示参数量级或量化版本。ollama pull qwen2.5:7b # 拉取完成后用 list 命令查看本地已有的模型 ollama list # 输出 NAME、ID、SIZE、MODIFIED 四列NAME 就是后面要用的模型名这里有个很常见的翻车点拉模型时写的名字和 OpenClaw 配置文件里写的名字必须完全一致。比如你本地拉的是 qwen2.5:7b配置里写 qwen2.5在某些版本里会默认去找 latest 标签一旦本地没有这个标签就会报 model not found。所以我给自己定了个规矩配置里的模型名永远先从 ollama list 的输出里复制不手敲。关于模型选型如果你的机器只有 CPU优先挑 7B 量化版以下的模型比如 qwen2.5:7b、llama3.2:3b。这类模型在 CPU 上能跑只是速度会慢一些但验证 OpenClaw 集成链路完全够用。如果机器有独立显卡可以再考虑更大参数量的模型。7B 模型在 CPU 上首次请求的冷启动可能要几十秒后面请求会快一些这不一定是配置问题。3.3 设置 OLLAMA_HOST 与环境变量OpenClaw 和 Ollama 同机部署时默认的 127.0.0.1 回环地址就够了不需要额外配置。但如果你打算把 Ollama 跑在一台机器上、OpenClaw 跑在另一台机器上就必须把 Ollama 的监听地址从回环改成对外可访问否则远端请求会被拒掉。改监听地址通过环境变量 OLLAMA_HOST 完成# 让 Ollama 监听所有网卡而不是只监听本机回环 systemctl set-environment OLLAMA_HOST0.0.0.0 systemctl restart ollama设置完从另一台机器验证一下# 在 OpenClaw 所在机器上执行确认 11434 端口通了 curl http://服务器IP:11434/api/tags如果你用的是 macOS环境变量要在 launchctl 的 plist 里加或者直接用 export 配合前台方式启动。Windows 则在系统环境变量里设置后重启 Ollama 服务。这一步和 OpenClaw 本身无关但它决定了远端访问能不能通也是网络类故障的高发区。提示把 OLLAMA_HOST 设为 0.0.0.0 相当于把这个端口暴露到局域网如果所在网络环境不安全建议用防火墙把 11434 限制到 OpenClaw 所在机器的 IP而不是完全放开。装完环境后我习惯顺手做一次全链路自检先 ollama list 确认模型在再 curl /api/tags 确认服务通最后跑一个简单的对话请求确认推理正常。三步都过再往 OpenClaw 接这样后面出的问题基本都能圈定在框架侧。4. 集成实现配置文件、调用代码与三个必调参数4.1 OpenClaw 的配置文件长什么样OpenClaw 的模型接入信息集中在配置文件里。这个包默认用的是 config.yaml结构上把模型服务相关的字段放在 model 节点下。我复现时用的最小配置如下model: provider: openai_compatible # 走 OpenAI 兼容协议 base_url: http://127.0.0.1:11434/v1 model: qwen2.5:7b # 与 ollama list 里的 NAME 完全一致 api_key: ollama # 本地服务无鉴权但协议要求字段不能缺 temperature: 0.7 # 采样随机性任务型对话建议 0.5~0.8 max_tokens: 4096 # 单次回复最大 token 数provider 字段决定了 OpenClaw 用什么协议组装请求。openai_compatible 是兼容模式base_url 必须以 /v1 结尾因为 Ollama 的 OpenAI 兼容端点是挂在 /v1/chat/completions 上的去掉这个后缀请求会落在不存在的路由上。api_key 字段在本地 Ollama 场景下不会被校验你填一串任意字符串都行但字段本身不能删。OpenClaw 的请求头拼接逻辑会对 api_key 做非空校验删了会在启动时报配置错误。这是很多第一次接本地模型的人会踩的坑以为本地无鉴权就可以不写。max_tokens 要根据模型能力来定。7B 模型的单次生成能力有限设太大没有实际意义反而可能让模型在长输出时中途截断设太小又会影响代码生成这类长文本任务。我一般取 2048 到 4096 之间具体看你跑的任务类型工具调用为主的话 2048 够用写代码或生成文档建议 4096。4.2 一个最小可用的 Python 验证脚本配置文件写好后别急着直接启动 OpenClaw先用一个独立的 Python 脚本验证底层链路通不通。我习惯这么做因为这样能把问题圈定在模型服务层还是 OpenClaw 层排查效率高很多。import requests import json # 拼接 OpenAI 兼容端点地址 url http://127.0.0.1:11434/v1/chat/completions # 请求体结构模仿 OpenClaw 实际发送的 messages 序列 payload { model: qwen2.5:7b, # 必须与 ollama list 的输出一致 messages: [ {role: system, content: 你是一个内网运维助手回答要简短。}, {role: user, content: 帮我列出排查端口占用的三条命令。} ], stream: False, temperature: 0.7, max_tokens: 1024 } # 本地服务无鉴权api_key 传任意值 headers {Content-Type: application/json} resp requests.post(url, jsonpayload, headersheaders, timeout60) print(HTTP 状态码:, resp.status_code) data resp.json() # OpenAI 风格返回结构choices[0].message.content if choices in data and len(data[choices]) 0: print(模型回复:, data[choices][0][message][content]) else: print(返回结构异常:, json.dumps(data, ensure_asciiFalse, indent2))这段脚本做了三件事第一构造一个和 OpenClaw 同类的请求体包含 system 和 user 两条消息第二POST 到 /v1/chat/completions请求走本机网络栈不经过外部流量第三从返回 JSON 里解析 choices[0].message.content这个字段就是 OpenClaw 实际会读取的回复内容。脚本里的 timeout 设成 60 秒是有原因的。首次请求一个模型时Ollama 要把模型权重加载进内存可能会延迟 10 到 30 秒timeout 太短会误报超时。如果你看到首次请求慢、后续请求快这是正常的冷启动现象不是服务卡死。如果脚本输出正常说明模型服务和 API 协议都通剩下就是 OpenClaw 侧的问题。如果脚本报错按 HTTP 状态码去查404 一般是路径或模型名不对401 是鉴权字段缺失500 大概率是模型推理异常。这时候去翻 Ollama 的日志通常会有更具体的报错信息。4.3 参数怎么调temperature、num_ctx 与 keep_alive集成能跑通之后真正决定体验的是参数怎么调。我最先关注的是这三个参数它们分别控制生成风格、上下文窗口长度和模型驻留策略。参数作用范围本地模型建议temperature采样随机性越大越发散0.5~0.8任务型对话比较稳num_ctx模型能看到的上下文长度4096~8192受内存限制keep_alive模型在内存中驻留时间5m~30m减少重复加载num_ctx 是这个包里最容易忽略的。Ollama 默认的上下文窗口只有 2048大概能装一千多个汉字。OpenClaw 做多轮工具调用时system 提示词、工具定义、历史消息都算上下文2048 很快就会把窗口塞满表现就是聊到后面模型开始丢上下文或者回答变短。血泪教训是我第一次调大 num_ctx 时太贪心直接把内存撑爆了系统卡到 SSH 都敲不动。调大 num_ctx 有两种方式。一种是在 Ollama 侧创建自定义模型文件设定 num_ctx一种是在请求里透传。如果你用 OpenClaw 的兼容接口常见做法是在配置文件的 model 节点加一个 num_ctx 字段框架组装请求时带进去。具体字段名以这个代码包里的注释为准我用的是 num_ctx。keep_alive 影响的是内存占用和响应速度的平衡。默认行为是模型用完就释放下次请求重新加载冷启动一次可能要十几秒。如果你在 OpenClaw 里做的是长会话或者频繁工具调用把它调到 5m 以上能明显减少卡顿感。代价是模型会常驻内存7B 模型大概占 4 到 5GB小内存机器要留意。5. 避坑与排查五个高频问题的处理记录5.1 连接与鉴权类这一节记录的是我在复现和试用过程中实际撞到的问题每条都按现象、原因、解决来描述。坑 1OpenClaw 一直报 connection refused但 Ollama 明明在跑现象OpenClaw 启动后一对话就报无法连接本机用 curl 访问 11434 又完全正常。原因OpenClaw 跑在另一台机器上而 Ollama 默认只听 127.0.0.1远端请求根本进不去。OLLAMA_HOST 没有改成 0.0.0.0这是跨机部署时最容易漏的一步。解决按第 3 章的方法把 OLLAMA_HOST 设为 0.0.0.0 后重启服务。从那以后我每次检查连接性问题先分清是本机访问还是跨机访问再决定查哪个变量省了很多冤枉时间。坑 2配置文件照抄了别人的 base_url结果 404现象请求能到 Ollama但返回 404页面提示路径不存在。原因base_url 写了 http://ip:11434 而不是 http://ip:11434/v1OpenClaw 拼出来的请求落在 /chat/completions 这个不存在的路径上。这个坑很隐蔽因为 Ollama 的 /api/tags 在根路径也能访问容易产生路径都没问题的错觉。解决把 base_url 末尾补齐 /v1重启 OpenClaw 恢复正常。我在排查时习惯先用第 4 章的 Python 脚本直接打一次请求看到 404 后第一反应就是路径问题基本不会绕弯。5.2 模型与参数类坑 3报 model not found但 ollama list 里明明有现象提示找不到模型服务日志里列出了本地存在的模型列表里面却没有配置文件写的那个名字。原因配置里写了 qwen2.5本地只有 qwen2.5:7b。Ollama 对不带标签的模型名会默认去找 latest而本地没有这个标签。这个问题的玄学感很强因为报错信息不会直接告诉你还缺一个 latest只会说找不到模型。解决把配置里的 model 字段改成与 ollama list 输出完全一致的名字不手敲、不缩写。最简单的方法是先从 ollama list 复制名字再粘贴到配置里不要凭记忆写。坑 4长对话中途开始丢上下文回答越来越短现象对话一开始正常多轮之后模型像失忆一样要么不看前面的内容要么直接截断回复。原因num_ctx 还是默认的 2048多轮历史加工具定义把窗口塞满了模型只能看到最后那段文字。这个不是模型变笨了是窗口装不下最前面的内容被挤出去了。解决把 num_ctx 调到 8192 或更大同时留意内存占用。我自己的习惯是调参前先 free -h 看一眼可用内存再动手确认余量充足才拉大窗口不再盲目追求最大上下文。坑 5temperature 改了没反应现象不管 temperature 设 0.1 还是 1.5输出风格几乎没有变化。原因OpenClaw 走的是 OpenAI 兼容端点部分采样参数在这个端点上被忽略请求体里的 temperature 没有真正传进采样器。这个属于兼容端点的实现差异不同版本的 Ollama 行为不完全一样。解决确认代码包里对 temperature 的处理方式如果没有透传字段就通过 Ollama 原生 API 跑一次对比实验或者用自定义模型文件固定 temperature。这也是我写验证脚本的意义所在它能帮你确认参数到底有没有生效而不是靠猜。6. 验证与进阶写一个多模型切换脚本顺手测出本机上限集成完成只是开始这个代码包真正方便的地方是能快速切换本地模型。我写了一个小脚本遍历本机上所有 Ollama 模型发同一个测试问题统计每个模型的首次响应耗时和回复长度以此判断哪几个模型能胜任任务型场景。import requests import time base_url http://127.0.0.1:11434/v1/chat/completions prompt 用一句话解释什么是向量数据库。 # 先从 /api/tags 获取本机所有模型名 resp requests.get(http://127.0.0.1:11434/api/tags) models [model[name] for model in resp.json()[models]] for m in models: payload { model: m, messages: [{role: user, content: prompt}], stream: False, max_tokens: 256 } start time.time() r requests.post(base_url, jsonpayload, timeout120) cost time.time() - start if r.status_code 200: content r.json()[choices][0][message][content] print(f{m}: {cost:.1f}s, {len(content)} 字) else: print(f{m}: HTTP {r.status_code})脚本的核心是先用 /api/tags 自动列模型再逐个发起请求。第一次跑的时候没加 timeout结果某个大模型加载了半分钟也没返回脚本直接卡死。后来我把 timeout 设成 120 秒还加了一行打印当前模型名的逻辑这样就算某个模型卡住我也知道卡在哪一个。跑完这个脚本你能很直观地看到参数量和响应耗时之间的关系也能顺便验证 keep_alive 是否真的生效——把两次连续请求之间的耗时对比一下如果第二次明显快于第一次说明模型驻留策略起作用了。另外还有一个很实用的习惯在 OpenClaw 的配置里同时准备几套模型配置一套用 3B 小模型做日常快速问答一套用 7B 模型做复杂任务切换时只改 model 字段。这个包之所以值得留一份是因为省掉了重新接线的时间配置文档和验证脚本都在换个模型不用动框架代码。我最早调这个包的时候栽过的最大跟头就是在 num_ctx 上太贪心总想一次性把上下文拉到最大结果本机内存被吃满整个系统卡到连 SSH 都敲不动。从那以后我每次改参数都遵循一个固定流程先查内存、再改参数、重启服务、跑一遍验证脚本确认没问题再接回 OpenClaw。希望这套步骤和分析能帮你少走这一步弯路。本文还有配套的精品资源点击获取