Ollama の opencode 接続定義
本書では、tsd-ollama の複数モデル構成を前提に、opencode 側の設定方法を定義する。
1. 位置付け
本構成は、Host Mac 上で動く Ollama を devcontainer 内の opencode から利用するための接続定義である。Ollama は OpenAI互換の /v1/* API を提供しており、SpecDojo の opencode 連携では opencode.json の custom provider 方式に合わせて OpenAI互換 API を標準とする。
本書の対象は以下とする。
- opencode からローカル LLM(Ollama)を利用したい
- tsd-ollama の複数モデル構成を前提にしたい
opencode.jsonの custom provider で接続したい
2. 前提条件
事前に tsd-ollama の手順で以下が完了していることを前提とする。
- Host Mac 上の Ollama が起動していること
- 利用するモデルがダウンロード済みであること
- 用途別の派生モデル(
qwen3.8:27b-mlx-work-64k、gemma4:31b-mlx-work-64k、gemma4:e4b-mlx-light-8k)が作成済みであること
devcontainer 内から Host Mac に接続するため、接続先は localhost ではなく host.docker.internal を使う。
まず、devcontainer のターミナルで疎通確認する。
curl http://host.docker.internal:11434/v1/modelsdata 配列に作成済みモデルが含まれていれば、本書の設定値をそのまま使える。モデルが見えない場合は、Host Mac 側で ollama list を実行してモデルが存在することを確認する。
3. 接続方式
opencode では、OLLAMA_HOST 環境変数を渡す方式ではなく、opencode.json の custom provider を使って接続先を明示する。これにより、OpenAI 本家 API とローカル Ollama endpoint を役割分離できる。
このため、以下の環境変数は opencode 接続の必須条件ではない。
export OLLAMA_HOST=http://host.docker.internal:11434これは ollama CLI 向けには有効だが、opencode では opencode.json の provider 設定を優先して管理する。
4. opencode.json 設定
4.1. provider 追加方針
既存の provider を置き換えるのではなく、ollama-local を追加して併存させる。これにより、ローカル LLM の切り替えを model と small_model の差し替えだけで行える。
baseURL は OpenAI互換 API のルートである http://host.docker.internal:11434/v1 を指定する。Chat Completions の個別 URL である /v1/chat/completions を直接書かない。
4.2. 設定例
opencode.json の provider に以下を追加する。
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"ollama-local": {
"npm": "@ai-sdk/openai-compatible",
"name": "Ollama Local",
"options": {
"baseURL": "http://host.docker.internal:11434/v1",
"apiKey": "not-needed",
},
"models": {
"qwen3.8:27b-mlx-work-64k": {
"name": "Qwen3.8 27B-MLX 常用 (64k)",
},
"gemma4:31b-mlx-work-64k": {
"name": "Gemma 4 31B-MLX 常用 (64k)",
},
"gemma4:e4b-mlx-light-8k": {
"name": "Gemma 4 E4B 軽作業用 (8k)",
},
},
},
},
"model": "ollama-local/qwen3.8:27b-mlx-work-64k",
"small_model": "ollama-local/gemma4:e4b-mlx-light-8k",
}agent ごとに Qwen 3.8 または Gemma 4 を明示して選ぶ。expert agent は同じモデルタグに reasoningEffort: high を指定して thinking を有効化する。
5. 接続確認
設定後は、まず API 側が応答することを確認する。確認には軽量モデルを使い、初回ロード時間を抑える。
curl http://host.docker.internal:11434/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer not-needed" \
-d '{
"model": "gemma4:e4b-mlx-light-8k",
"messages": [
{"role": "user", "content": "短く疎通確認してください。"}
],
"max_tokens": 32,
"reasoning_effort": "none",
"stream": false
}'gemma4:e4b-mlx-light-8k は思考をともなったモデルのため、考える過程(reasoning)の生成にも出力枠を使う。max_tokens: 32 のまま reasoning_effort を付けないと、その考えだけで上限に達して finish_reason が length になり、content が空になりうる(母艦の Ollama で確認済み)。期待する結果は、reasoning_effort: "none" を足すことで考える過程を止め、finish_reason が stop になって content に短い本文が返ることである。
なお、"think": false ではこの思考の停止は実現しなかったため、考えの停止には "reasoning_effort": "none" を用いる。
次に、opencode 側で対象モデルが使われるように実行する。
opencode run --agent edit-agent "SpecDojo task を1件実行してください"失敗時は、まず curl の疎通確認に戻る。curl が通らない状態で opencode 側だけを調べても切り分けにならない。
6. 運用上の注意
6.1. model 名の整合
Ollama のカスタムモデル名は ollama list で確認できる。opencode.json の models キーは Ollama が認識するモデル名と一致させる必要がある。名前が一致しない場合は Chat Completions リクエストがエラーになる。モデルを再作成した場合も名前を合わせて opencode.json を更新する。
6.2. 重い実装用モデルへの切り替え
同一の opencode provider では max_concurrency: 1 を維持し、Qwen と Gemma が同時にロードされないようにする。モデル別 agent は名前で明示して選択し、thinking 用の派生モデルタグは作成しない。
6.3. 疎通確認は短い非 stream リクエストから始める
初回確認では、短いプロンプトと小さい max_tokens を使い、stream: false を明示する。長い履歴や大きい max_tokens のまま opencode から実行すると、初回トークンまでの待ち時間が長くなり、Ollama 側の問題を切り分けにくくなる。
6.4. Ollama の起動確認
Host Mac 側で Ollama が停止していると、devcontainer からの接続がタイムアウトになる。接続できない場合は、Host Mac 側で以下を確認する。
- Ollama が起動していること:
curl http://localhost:11434/api/tags - モデルが存在すること:
ollama list - devcontainer が Docker Desktop 上で動作していること
host.docker.internalが名前解決できること:getent hosts host.docker.internal