ai-infrastructure-ollama
Ollama JavaScriptクライアントを活用し、ローカル環境で大規模言語モデル(LLM)の推論を実行、チャットやストリーミング、ツール連携、画像認識、埋め込み、構造化出力、モデル管理などをOpenAI互換のエンドポイントで実現するSkill。
📜 元の英語説明(参考)
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint
🇯🇵 日本人クリエイター向け解説
Ollama JavaScriptクライアントを活用し、ローカル環境で大規模言語モデル(LLM)の推論を実行、チャットやストリーミング、ツール連携、画像認識、埋め込み、構造化出力、モデル管理などをOpenAI互換のエンドポイントで実現するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o ai-infrastructure-ollama.zip https://jpskill.com/download/10208.zip && unzip -o ai-infrastructure-ollama.zip && rm ai-infrastructure-ollama.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10208.zip -OutFile "$d\ai-infrastructure-ollama.zip"; Expand-Archive "$d\ai-infrastructure-ollama.zip" -DestinationPath $d -Force; ri "$d\ai-infrastructure-ollama.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
ai-infrastructure-ollama.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
ai-infrastructure-ollamaフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Ollama のパターン
クイックガイド:
ollamanpm パッケージを使用して、LLM をローカルで実行します。会話にはollama.chat()を、単一のプロンプトにはollama.generate()を使用します。stream: trueでストリーミングを有効にし、for awaitで反復処理します。構造化された出力には、JSON スキーマ (zodToJsonSchema経由) でformatを使用します。関数呼び出しにはtools配列を使用します。埋め込みにはollama.embed()を使用します。モデルはあなたのマシン上で実行されます -- ローカルで使用する場合は API キーは不要ですが、モデルのロード時間とメモリ使用量に注意してください。
<critical_requirements>
重要: この Skill を使用する前に
すべてのコードは、CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順、
import type、名前付き定数)
(会話には必ず ollama.chat() を、単一プロンプトの補完には ollama.generate() を使用してください -- パラメータの形状が異なります)
(モデルのロード遅延を必ず処理してください -- モデルのロード後の最初の要求は、モデルの初期化により大幅に時間がかかります)
(構造化された出力には、zod-to-json-schema の zodToJsonSchema() を必ず使用してください -- JSON スキーマを手動で構築しないでください)
(複数ターンのインタラクションで会話履歴を維持するために、ストリーミングされる thinking、content、および tool_calls フィールドを必ず累積してください)
(モデルがすでにプルされていると決して仮定しないでください -- ollama.list() で確認するか、モデルが見つからないエラーを適切に処理してください)
</critical_requirements>
自動検出: Ollama, ollama, ollama.chat, ollama.generate, ollama.embed, ollama.pull, ollama.list, ollama.show, ollama.delete, ollama.ps, ollama.abort, ollama.create, keep_alive, zodToJsonSchema, OLLAMA_HOST, llama3, mistral, qwen, gemma, phi, deepseek, local LLM
使用する場面:
- 開発、テスト、またはプライバシーを重視するワークロードのために、LLM をローカルで実行する場合
- ローカルモデル (Llama, Mistral, Qwen, Gemma など) を使用してチャットアプリケーションを構築する場合
- JSON スキーマを使用して、ローカルモデルでテキストまたは画像から構造化データを抽出する場合
- ローカルでホストされたモデルで、ツール呼び出し/関数呼び出しを実装する場合
- クラウド API のコストなしで、RAG またはセマンティック検索用の埋め込みを生成する場合
- ローカルモデルのライフサイクル (pull, list, show, delete, copy) を管理する場合
- クラウドプロバイダーにコミットする前に、AI 機能をプロトタイピングする場合
カバーする主要なパターン:
- クライアントのセットアップ (デフォルトおよびカスタムインスタンス)
- チャット補完 (
ollama.chat) およびテキスト生成 (ollama.generate) for awaitを使用したストリーミングと累積された状態format+zodToJsonSchemaを使用した構造化された出力tools配列を使用したツール呼び出しとマルチターンのツールループimagesパラメータを使用したビジョン/マルチモーダル入力ollama.embed()を使用した埋め込み- モデル管理 (pull, list, show, delete, copy, ps)
- ドロップイン移行のための OpenAI 互換エンドポイント
使用しない場面:
- 稼働時間と SLA が保証された本番ワークロード -- クラウド LLM プロバイダーを使用してください
- OpenAI、Anthropic、Google 間を切り替える必要があるマルチプロバイダーアプリケーション -- 統合されたプロバイダー SDK を使用してください
- 最新のプロプライエタリモデル (GPT-5, Claude) を必要とするアプリケーション -- それらはクラウド専用です
例のインデックス
- コア: セットアップ、チャット & 生成 -- クライアントの初期化、チャット、生成、ストリーミング、エラー処理
- ツール呼び出し -- ツールの定義、単一/並列呼び出し、マルチターンのエージェントループ
- 構造化された出力 -- Zod 経由の JSON スキーマ、ビジョンの抽出
- 埋め込み & ビジョン -- 埋め込み、画像分析、マルチモーダル
- モデル管理 -- プル、リスト、表示、削除、コピー、ps
- クイック API リファレンス -- メソッドシグネチャ、オプション、応答タイプ、モデル名
<philosophy>
哲学
Ollama JavaScript ライブラリは、Ollama のローカル REST API (デフォルト http://127.0.0.1:11434) 上のシンクライアントです。クラウドの依存関係なしに、ローカルで実行されているオープンソース LLM への直接アクセスを提供します。
コア原則:
- ローカルファースト -- モデルはあなたのハードウェア上で実行されます。ローカルで使用する場合は API キーは不要、完全なデータプライバシー、トークンごとのコストはかかりません。トレードオフ: 十分な GPU/CPU メモリが必要です。
- シンプルな API --
ollama.chat()とollama.generate()が 2 つの主要なメソッドです。デフォルトのインポートは事前構成済みのシングルトンクライアントです。デフォルト以外のホストには、new Ollama()でカスタムインスタンスを作成します。 - REST ではデフォルトでストリーミング、SDK ではオプトイン -- REST API はデフォルトでストリーミングします。SDK はデフォルトで完全な応答を返します。
stream: trueを設定してAsyncGeneratorを取得します。 - モデルに依存しない -- 同じ API は、Ollama がサポートするすべてのモデル (Llama, Mistral, Qwen, Gemma, Phi, DeepSeek など) で動作します。モデルの機能 (ビジョン、ツール呼び出し、構造化された出力) はモデルによって異なります。
- OpenAI 互換 -- Ollama は
/v1/chat/completionsおよび/v1/embeddingsエンドポイントを公開しており、OpenAI SDK がbaseURL: 'http://localhost:11434/v1'で接続できるようになっています。
</philosophy>
<patterns>
コアパターン
パターン 1: クライアントのセットアップ
デフォルトのインポートは、http://127.0.0.1:11434 を指す事前構成済みのシングルトンです。
// lib/ollama.ts -- デフォルトクライアント (最も一般的)
import ollama from "ollama";
// 直接使用 -- localhost:11434 に接続
const response = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "Hello" }],
});
// lib/ollama.ts -- デフォルト以外のホスト用のカスタムクライアント
import { Ollama } from "ollama";
const ollama = new Ollama({
host: "http://192.168.1.100:11434",
});
export { ollama };
良い点: 最小限のセットアップ、デフォルトクライアントは構成不要、リモートサーバー用のカスタムクライアント
// 悪い例: ホストをインラインでハードコーディング
import { Ollama } from "ollama";
const response = await new Ollama({ host: "http://192.168.1.100:11434" }).chat({
model: "llama3.1",
messages: [{ role: "user", content: "Hello" }],
});
悪い点: リクエストごとに新しいクライアントインスタンスを作成、再利用されない、ホストが分散
(原文はここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Ollama Patterns
Quick Guide: Use the
ollamanpm package to run LLMs locally. Useollama.chat()for conversations andollama.generate()for single prompts. Enable streaming withstream: trueand iterate withfor await. Useformatwith a JSON schema (viazodToJsonSchema) for structured outputs. Usetoolsarray for function calling. Useollama.embed()for embeddings. Models run on your machine -- no API keys required for local use, but be aware of model loading time and memory usage.
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use ollama.chat() for conversations and ollama.generate() for single-prompt completions -- they have different parameter shapes)
(You MUST handle model loading delays -- the first request after a model is loaded takes significantly longer due to model initialization)
(You MUST use zodToJsonSchema() from zod-to-json-schema for structured outputs -- do NOT manually construct JSON schemas)
(You MUST accumulate streamed thinking, content, and tool_calls fields to maintain conversation history in multi-turn interactions)
(You MUST never assume a model is already pulled -- check with ollama.list() or handle errors from missing models gracefully)
</critical_requirements>
Auto-detection: Ollama, ollama, ollama.chat, ollama.generate, ollama.embed, ollama.pull, ollama.list, ollama.show, ollama.delete, ollama.ps, ollama.abort, ollama.create, keep_alive, zodToJsonSchema, OLLAMA_HOST, llama3, mistral, qwen, gemma, phi, deepseek, local LLM
When to use:
- Running LLMs locally for development, testing, or privacy-sensitive workloads
- Building chat applications with local models (Llama, Mistral, Qwen, Gemma, etc.)
- Extracting structured data from text or images using local models with JSON schemas
- Implementing tool calling / function calling with locally-hosted models
- Generating embeddings for RAG or semantic search without cloud API costs
- Managing local model lifecycle (pull, list, show, delete, copy)
- Prototyping AI features before committing to a cloud provider
Key patterns covered:
- Client setup (default and custom instances)
- Chat completions (
ollama.chat) and text generation (ollama.generate) - Streaming with
for awaitand accumulated state - Structured output with
format+zodToJsonSchema - Tool calling with
toolsarray and multi-turn tool loops - Vision / multimodal inputs with
imagesparameter - Embeddings with
ollama.embed() - Model management (pull, list, show, delete, copy, ps)
- OpenAI-compatible endpoint for drop-in migration
When NOT to use:
- Production workloads requiring guaranteed uptime and SLAs -- use a cloud LLM provider
- Multi-provider applications where you need to switch between OpenAI, Anthropic, Google -- use a unified provider SDK
- Applications requiring the latest proprietary models (GPT-5, Claude) -- those are cloud-only
Examples Index
- Core: Setup, Chat & Generate -- Client init, chat, generate, streaming, error handling
- Tool Calling -- Tool definitions, single/parallel calls, multi-turn agent loops
- Structured Output -- JSON schema via Zod, vision extraction
- Embeddings & Vision -- Embeddings, image analysis, multimodal
- Model Management -- Pull, list, show, delete, copy, ps
- Quick API Reference -- Method signatures, options, response types, model names
<philosophy>
Philosophy
The Ollama JavaScript library is a thin client over Ollama's local REST API (default http://127.0.0.1:11434). It provides direct access to locally-running open-source LLMs with zero cloud dependencies.
Core principles:
- Local-first -- Models run on your hardware. No API keys required for local use, complete data privacy, no per-token costs. Trade-off: you need sufficient GPU/CPU memory.
- Simple API --
ollama.chat()andollama.generate()are the two primary methods. The default import is a pre-configured singleton client; create custom instances withnew Ollama()for non-default hosts. - Streaming by default in REST, opt-in in SDK -- The REST API streams by default. The SDK returns full responses by default; set
stream: trueto get anAsyncGenerator. - Model-agnostic -- The same API works with any Ollama-supported model (Llama, Mistral, Qwen, Gemma, Phi, DeepSeek, etc.). Model capabilities (vision, tool calling, structured output) depend on the model.
- OpenAI-compatible -- Ollama exposes
/v1/chat/completionsand/v1/embeddingsendpoints, allowing the OpenAI SDK to connect withbaseURL: 'http://localhost:11434/v1'.
</philosophy>
<patterns>
Core Patterns
Pattern 1: Client Setup
The default import is a pre-configured singleton pointing to http://127.0.0.1:11434.
// lib/ollama.ts -- default client (most common)
import ollama from "ollama";
// Use directly -- connects to localhost:11434
const response = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "Hello" }],
});
// lib/ollama.ts -- custom client for non-default host
import { Ollama } from "ollama";
const ollama = new Ollama({
host: "http://192.168.1.100:11434",
});
export { ollama };
Why good: Minimal setup, default client requires zero configuration, custom client for remote servers
// BAD: Hardcoding host inline everywhere
import { Ollama } from "ollama";
const response = await new Ollama({ host: "http://192.168.1.100:11434" }).chat({
model: "llama3.1",
messages: [{ role: "user", content: "Hello" }],
});
Why bad: Creates a new client instance per request, no reuse, host scattered across codebase
See: examples/core.md for cloud API setup, custom headers, browser usage
Pattern 2: Chat Completions
Multi-turn conversations with message history. You manage the messages array.
import ollama from "ollama";
const response = await ollama.chat({
model: "llama3.1",
messages: [
{ role: "system", content: "You are a helpful coding assistant." },
{ role: "user", content: "Explain TypeScript generics." },
],
});
console.log(response.message.content);
Why good: Clear message roles, system message for behavior control, direct content access
// BAD: Not checking response, no system message
const res = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "do something" }],
});
Why bad: No system instruction means unpredictable behavior, vague prompt
See: examples/core.md for multi-turn conversations, model options
Pattern 3: Text Generation
Single-prompt completions without message history. Simpler than chat for one-shot tasks.
import ollama from "ollama";
const response = await ollama.generate({
model: "llama3.1",
prompt: "Write a haiku about TypeScript.",
system: "You are a creative writer.",
});
console.log(response.response);
Why good: Simpler API for one-shot tasks, system parameter instead of message array
See: examples/core.md for generate with images, suffix, raw mode
Pattern 4: Streaming
Set stream: true to get an AsyncGenerator. Iterate with for await.
import ollama from "ollama";
const stream = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "Explain async/await." }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.message.content);
}
console.log(); // newline
Why good: Progressive output for better UX, memory-efficient for long responses
// BAD: Not consuming the stream
const stream = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "Hello" }],
stream: true,
});
// Stream never consumed -- response is lost
Why bad: Stream must be consumed via iteration, otherwise the response is silently lost
See: examples/core.md for generate streaming, abort, thinking mode streaming
Pattern 5: Structured Output with Zod
Use format with a JSON schema to constrain model output. Use zodToJsonSchema() from zod-to-json-schema to convert Zod schemas.
import ollama from "ollama";
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
const Country = z.object({
name: z.string(),
capital: z.string(),
languages: z.array(z.string()),
});
type Country = z.infer<typeof Country>;
const response = await ollama.chat({
model: "llama3.1",
messages: [
{
role: "user",
content: "Tell me about France. Respond in JSON.",
},
],
format: zodToJsonSchema(Country),
});
const country: Country = Country.parse(JSON.parse(response.message.content));
console.log(country.capital); // "Paris"
Why good: Type-safe output via Zod, JSON schema constrains model output, parse validates response
// BAD: Using format: 'json' without a schema
const response = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "Tell me about France as JSON" }],
format: "json",
});
// No schema enforcement -- model can return any JSON shape
Why bad: format: 'json' only ensures valid JSON syntax, not structure -- use a JSON schema for reliable extraction
See: examples/structured-output.md for vision extraction, complex schemas
Pattern 6: Tool Calling
Define tools the model can request. Handle tool_calls in responses and feed results back.
import ollama from "ollama";
const tools = [
{
type: "function" as const,
function: {
name: "get_weather",
description: "Get the current weather for a city",
parameters: {
type: "object",
required: ["city"],
properties: {
city: { type: "string", description: "City name" },
},
},
},
},
];
const response = await ollama.chat({
model: "llama3.1",
messages: [{ role: "user", content: "What is the weather in Tokyo?" }],
tools,
});
if (response.message.tool_calls?.length) {
for (const toolCall of response.message.tool_calls) {
console.log(`Call: ${toolCall.function.name}`);
console.log(`Args:`, toolCall.function.arguments);
}
}
Why good: Standard tool schema format, checks for tool_calls before processing, arguments already parsed (not stringified JSON)
See: examples/tools.md for multi-turn tool loops, streaming tool calls, parallel tools
Pattern 7: Embeddings
Use ollama.embed() for text embeddings. Supports single or batch inputs.
import ollama from "ollama";
const EMBEDDING_MODEL = "nomic-embed-text";
const response = await ollama.embed({
model: EMBEDDING_MODEL,
input: [
"TypeScript is a typed superset of JavaScript.",
"Rust is a systems programming language.",
],
});
console.log(`Vectors: ${response.embeddings.length}`);
console.log(`Dimensions: ${response.embeddings[0].length}`);
Why good: Batch multiple inputs in one call, named constant for model, returns array of number arrays
See: examples/embeddings-vision.md for semantic search, cosine similarity
Pattern 8: Model Management
Pull, list, show, and delete models programmatically.
import ollama from "ollama";
// List available models
const models = await ollama.list();
for (const model of models.models) {
console.log(`${model.name} (${model.size} bytes)`);
}
// Pull a model with progress streaming
const stream = await ollama.pull({ model: "llama3.1", stream: true });
for await (const progress of stream) {
console.log(
`${progress.status}: ${progress.completed ?? 0}/${progress.total ?? 0}`,
);
}
// Show model details
const info = await ollama.show({ model: "llama3.1" });
console.log(`Parameters: ${info.details.parameter_size}`);
console.log(`Quantization: ${info.details.quantization_level}`);
// Delete a model
await ollama.delete({ model: "old-model" });
Why good: Streaming progress for large downloads, programmatic model lifecycle, detailed model metadata
See: examples/model-management.md for copy, create, running models (ps)
Pattern 9: OpenAI-Compatible Endpoint
Ollama exposes /v1/chat/completions and /v1/embeddings that work with the OpenAI SDK.
import OpenAI from "openai";
const OLLAMA_BASE_URL = "http://localhost:11434/v1";
const client = new OpenAI({
baseURL: OLLAMA_BASE_URL,
apiKey: "ollama", // Required by SDK but unused by Ollama
});
const completion = await client.chat.completions.create({
model: "llama3.1",
messages: [{ role: "user", content: "Why is the sky blue?" }],
});
console.log(completion.choices[0].message.content);
Why good: Drop-in replacement for OpenAI SDK code, named constant for URL, easy to switch between local and cloud
When to use: When migrating existing OpenAI SDK code to local models, or when you want to use OpenAI SDK tooling (structured outputs, streaming helpers) with local models
When not to use: For new Ollama-native code, prefer the ollama package directly -- it exposes Ollama-specific features (model management, keep_alive, thinking mode) that the OpenAI compat layer does not
See: reference.md for supported and unsupported OpenAI features
</patterns>
<decision_framework>
Decision Framework
ollama.chat() vs ollama.generate()
Need multi-turn conversation history?
+-- YES -> ollama.chat() (messages array with roles)
+-- NO -> Is it a single prompt completion?
+-- YES -> ollama.generate() (simpler API)
+-- NO -> ollama.chat() (default choice for most use cases)
Native Ollama SDK vs OpenAI-Compatible Endpoint
Do you have existing OpenAI SDK code to migrate?
+-- YES -> Use OpenAI SDK with baseURL: 'http://localhost:11434/v1'
+-- NO -> Do you need Ollama-specific features?
+-- YES -> Use ollama package (model management, keep_alive, thinking, abort)
+-- NO -> Either works, prefer ollama package for new code
Structured Output vs Plain Text
Do you need structured data from the model?
+-- YES -> Use format parameter with zodToJsonSchema()
| +-- Always include "respond in JSON" in the prompt
| +-- Always parse and validate with Zod after receiving response
+-- NO -> Omit format parameter (plain text response)
Model Selection Guidance
What is your task?
+-- General chat / coding -> llama3.1 (8B for speed, 70B for quality)
+-- Fast + small -> phi4-mini, gemma3 (smaller memory footprint)
+-- Code generation -> qwen2.5-coder, deepseek-coder-v2
+-- Vision/multimodal -> llama3.2-vision, gemma3
+-- Embeddings -> nomic-embed-text, all-minilm
+-- Tool calling -> llama3.1, qwen3, mistral
+-- Reasoning/thinking -> qwen3 (with think: true), deepseek-r1
</decision_framework>
<red_flags>
RED FLAGS
High Priority Issues:
- Not handling model loading time -- first request after model load can take 30+ seconds on CPU; show a loading indicator or set
keep_aliveto keep models warm - Using
format: 'json'instead of a JSON schema -- only ensures valid JSON syntax, not structure; always usezodToJsonSchema()for reliable extraction - Not accumulating streamed fields in multi-turn conversations -- you must collect
thinking,content, andtool_callsfrom all chunks to maintain history - Assuming all models support all features -- tool calling, vision, and structured output depend on the model; check model capabilities first
Medium Priority Issues:
- Not setting
keep_alivefor latency-sensitive applications -- models unload after 5 minutes of inactivity by default; setkeep_alive: '30m'orkeep_alive: -1(indefinite) for persistent sessions - Creating new
Ollama()instances per request instead of reusing a singleton client - Not handling
AbortErrorwhen usingollama.abort()-- listening threads throw when streams are cancelled - Ignoring model size vs available memory -- loading a 70B model on 8GB RAM will fail or swap heavily
Common Mistakes:
- Confusing
ollama.chat()andollama.generate()parameters --chatusesmessages[],generateusespromptandsystem - Using
ollama.embeddings()(deprecated) instead ofollama.embed()-- the newerembed()method supports batch inputs - Passing HTTP/HTTPS URLs to
imagesparameter -- Ollama accepts file paths,Uint8Array, or base64-encoded strings, but not remote URLs - Using tool calling with models that do not support it -- not all models handle tools; use Llama 3.1+, Qwen 3, or Mistral for reliable tool calling
- Forgetting to
JSON.parse()the response content when using structured output -- Ollama returns JSON as a string inmessage.content, not a parsed object
Gotchas & Edge Cases:
- Ollama returns tool call arguments as already-parsed objects (not JSON strings like OpenAI) --
toolCall.function.argumentsis an object, not a string - The
keep_aliveparameter accepts both duration strings ('5m','1h') and numbers (seconds) --0unloads immediately,-1keeps loaded indefinitely ollama.abort()cancels ALL active streams for that client instance -- for individual stream cancellation, usestream.abort()on the returned stream object- Model names can include tags (
llama3.1:8b,llama3.1:70b) -- omitting the tag uses the default (usually smallest) - The
thinkparameter enables extended reasoning but only works with models that support it (Qwen 3, DeepSeek R1) -- it adds athinkingfield to the response alongsidecontent - Browser usage requires importing from
ollama/browserinstead ofollama-- the default import uses Node.js-specific APIs - Cloud API access (ollama.com) requires an API key via
Authorization: Bearerheader and settinghost: 'https://ollama.com' - Response includes performance metrics:
total_duration,eval_count,eval_duration(in nanoseconds) -- calculate tokens/second witheval_count / eval_duration * 1e9
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use ollama.chat() for conversations and ollama.generate() for single-prompt completions -- they have different parameter shapes)
(You MUST handle model loading delays -- the first request after a model is loaded takes significantly longer due to model initialization)
(You MUST use zodToJsonSchema() from zod-to-json-schema for structured outputs -- do NOT manually construct JSON schemas)
(You MUST accumulate streamed thinking, content, and tool_calls fields to maintain conversation history in multi-turn interactions)
(You MUST never assume a model is already pulled -- check with ollama.list() or handle errors from missing models gracefully)
Failure to follow these rules will produce unreliable, poorly-typed, or broken local LLM integrations.
</critical_reminders>