8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

前書き

私は普段 Claude や Codex など、幾つかのサービスを契約して使っていますが、やっぱり料金が高いです。大学生のころ借りていたアパートの家賃より高いかもしれません:sweat_smile:

コーディングが有料になっていくと、「AI がないと効率が悪い、でも AI がお金がかかる」という矛盾が出てきて、ちょっとモヤっとするんですよね:frowning2::point_up_tone1:

そこで試してみたのが、ローカル LLM(Gemma 4)+ Ollama + Mastra Harness の組み合わせです。全部無料で使えて、自分のコーディングエージェント簡単に作れます。

40AF8D7C-A6D8-4D74-9146-9DFD1F1A0CA9_4_5005_c.jpeg

コーディングエージェントの構成要素

まず何が必要かを整理します。

役割 選んだもの 理由
モデル Gemma 4 12B Google の OSS モデル、ローカル実行できるサイズ感
ランタイム Ollama Mac でモデルをそのまま動かせる
エージェント基盤 Mastra Harness セッション管理・モード切替が組み込み済み
プロバイダー ollama-ai-provider-v2 Mastra の Agent から Ollama のモデルを呼ぶためのプロバイダー

Gemma 4 は 2026 年 3 月に公開されたモデルで、今回使う 12B は 6 月に追加されたばかり。12B サイズならローカルでも動く、というのが大きかったです。

ちなみに今回の検証環境は MacBook Pro(Apple M4 、メモリ 24GB) です。
gemma4:12b はだいたい 7.6GB なので、メモリ 24GB なら余裕をもって動かせます。
逆に 26B以上のクラスはこのマシンだと厳しいので、まずは 12B から始めることにしました:point_up_tone1:

エージェントの部分は Mastra の Harness を使えば作れそうなので、この構成で行くことにしました。

Gemma 4 とは

Gemma 4 は Google が公開した OSS モデルです。E2B・E4B・12B・26B・31B と幅広いサイズ展開があって、12B ならそこそこのスペックの Mac でも動きます。

ライセンスは Apache 2.0 で、商用利用も OK です。

用途としては、テキスト生成だけでなく画像も扱える マルチモーダル対応で、推論やコーディング、長文の読み込み(12B は 256K トークンのコンテキスト)が得意です。
チャットボット、要約、コード補助、ドキュメント解析あたりが定番で、今回はこの中の「コード補助」を狙って、ローカルのコーディングエージェントの頭脳として使います。

761864EA-06B0-4F41-A1E7-DD316B3E69C2.jpeg

Ollama のインストール

Ollama は ローカルで LLM を動かすためのランタイムです。Mac/Linux/Windows に対応しています。

インストールは Homebrew 一発でOKです。

brew install ollama

Homebrew を使わない場合は、https://ollama.com からインストーラーをダウンロードできます。

Homebrew で入れた場合は、モデルを操作する前に Ollama のサーバーを起動しておきます。別ターミナルで動かしっぱなしにしておくと楽です。

ollama serve

brew services start ollama でバックグラウンド起動にしてもOKです。公式インストーラーの macOS アプリ版を使っている場合は、アプリがサーバーを自動起動するのでこの手順は不要です。

サーバーが起動できたら、Gemma 4 のモデルをダウンロードします。12B は数 GB あるので、ダウンロードに少し時間がかかります。

ollama pull gemma4:12b

ダウンロード完了したら、まずターミナルで動作確認します。

ollama run gemma4:12b

ターミナル上でそのまま会話できるので、「こんにちは」と打ち込んでみてください。
返事が返ってきたら OK です:relaxed:

000ACE71-71BB-4FDE-96F1-DF00E302FE36.jpeg

通常の Mastra から Gemma を呼び出す

次は、Mastra エージェントから gemma4:12bを使ってみます。

Mastra は、TypeScript で AI エージェントやワークフローを作るためのフレームワークです

Mastra プロジェクトを作る

まずは Mastra の新規プロジェクトを用意します。

npm create mastra@latest

実行するといくつか設定を聞かれますが、今回の動作には影響しないため、すべてお好みで選択して問題ありません。:point_up_tone1:

プロジェクト初期化ができたら、そのディレクトリに入って、
Ollama とつなぐためのプロバイダー ollama-ai-provider-v2 を追加します。

npm install ollama-ai-provider-v2

エージェントを定義する

エージェントを新規作成して、 Agent の modelollama('gemma4:12b') をセットします。
今回は会話履歴を覚えてもらうために Memory も持たせています。

src/mastra/agents/ollama-agent.ts
import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { ollama } from 'ollama-ai-provider-v2';

export const ollamaAgent = new Agent({
  id: 'ollama-agent',
  name: 'Ollama Agent',
  instructions: '君はフレンドリーなアシスタントです。ユーザーの質問に対して、適切な回答を提供してください。常に正確で役立つ情報を提供するよう努めてください。',
  model: ollama('gemma4:12b'),
  memory: new Memory(),
});

あとは、作ったエージェントを Mastra インスタンスに登録します。

src/mastra/index.ts
import { Mastra } from '@mastra/core/mastra';
import { ollamaAgent } from './agents/ollama-agent';

export const mastra = new Mastra({
  agents: { ollamaAgent },
  // storage / logger などは mastra create の雛形そのままでOK
});

Memory は会話履歴の保存にストレージを使いますが、mastra create の雛形が LibSQL ストレージを設定済みなので、そのまま動きます。

これだけで Mastra Studio(npm run devhttp://localhost:4111)から会話できるようになります。

50021559-911B-46B7-AA6A-83AAF3B8479E.jpeg

Mastra の Harness でコーディングエージェントを作る

完成したリポジトリはこちらです。

Mastra Harness は、AIエージェントアプリケーションを作るためのセッションコントローラーです。

Agent クラスだけでチャット型のコーディングエージェントを作ろうとすると、会話ループ・会話履歴の永続化・モデルの切り替え・ツール実行前の承認…といった、「エージェント本体じゃない周辺の配線」を全部自前で書くことになります、地味に面倒です:frowning2:

Harness は、その UI とエージェントループの間に挟まるランタイムの面倒ごとを、まるごと引き受けてくれるレイヤーです。

スレッド管理・モード切替・状態の永続化・ツール承認・サブエージェントの調整まで全部やってくれるので、こちらは「エージェントに何をさせるか」だけに集中できます。

機能 説明
Session 会話状態(モード・モデル・スレッド)をまとめて管理
Modes agent の指示・ツール・モデルを切り替えられるモード
Thread 会話の永続化(リスタートしても続きから始められる)
Tool approvals ツール実行前にユーザー承認を挟む HITL
Subagents サブエージェントに特定タスクを委譲

「plan → build → review」のような複数フェーズを 1 セッションで切り替えながら進めるコーディングエージェントが作りたいときに向いています。

Mastra 公式のターミナル型コーディングエージェント Mastra Code が、まさにこの Harness の上で動いています。
マルチモデル対応・会話の永続化・plan→execute を備えたツールが、同じ仕組みで自分でも作れる、というわけです:point_up_tone1:

Harness は現在 Alpha 機能です。マイナーバージョンアップで API が変わる可能性があります。

セットアップ

さきほど作ったプロジェクトに、そのまま Harness を足していきます。
Harness は @mastra/core に含まれているので追加インストールは不要です。

ツールとワークスペースを用意する

コーディングエージェントには、ファイルを読み書きするツールが要ります。
ただ、AI に好き勝手ファイルを触らせるのは怖いので、操作できる範囲を 1 つのディレクトリ(ワークスペース)に閉じ込めるところから始めます。

まずはそのサンドボックスを定義します、WORKSPACE_ROOT の外に出るパスは弾くようにしておきます。

実行前に forge-workspace/ を作っておきます(無いと read_file などが ENOENT になります)。ここがエージェントの「作業部屋」になり、レビュー対象のコードもこの中に置きます。

つづいてツール本体です。ファイル操作は createTool で定義し、さきほどの resolveInWorkspace を通すことでサンドボックスの外に出られないようにします。read_file / list_dir / write_file / edit_file の 4 つを用意しています。

今回は「自前のサンドボックス + 自作ツール」で済ませていますが、Mastra には公式の Workspace 機能もあります。
エージェントに FilesystemSandbox を与えるための仕組みで、ローカルから S3・E2B などのプロバイダーまで選べます。
ファイル操作ツールを毎回自作したくない・コマンド実行までさせたい、という段階になったら、こちらに乗るのが本筋です。

https://mastra.ai/docs/workspace/overview

Harness を組み立てる

Harness のキモは モードごとに違うエージェントを切り替えられることです。
今回は plan モードに 読み取り専用のエージェント、build モードに 読み書きできるエージェントを割り当てます。

まずは plan / build それぞれのエージェントを定義します。
planAgent は読み取り系ツールだけ、buildAgent は書き込み系も持たせます。

そして Harness を組み立てて、各モードにエージェントを割り当てます。
default: true が既定モード、memory を渡すと plan の調査結果が build に引き継がれます。

動かす

あとは Harness を初期化して、メッセージを送るだけです。
今回はターミナルで対話する REPL を repl.ts にしました(npm run forge で起動)。/plan /build でモードを切り替えながら進められます。

そして地味に気に入っているのが、起動時のバナーです:relaxed: 緑のハリネズミのマスコット(その名も「ハリネズミ Code」)と、いま開いている workspace・thread・モードがターミナルに出ます。
repl.tsmain() が起動直後に printBanner() を呼んでいるだけの、完全に趣味の部分です。

イベントの描画は render.ts に切り出しています。ポイントは、message_update が「その時点までの全文」を毎回返すので、すでに出力した分との 差分だけ を書き出すところです。

これで npm run forge を叩くと、バナーが出て plan モードで対話が始まります。
小さなコーディングエージェントが、ローカルで完全に動きます:relaxed:

D7791B50-D456-45F9-A588-0CDBA210A54E.jpeg

失敗談: Gemma 4 でツール呼び出しが空になる

最初は gemma4:12b をそのまま Harness に繋いで試したんですが、ツールを呼び出すとレスポンスが空になる問題が発生しました:frowning2:

> ツールを呼び出し中...
> (レスポンスなし、タイムアウト)

調べてみると、ローカルモデル + ollama-ai-provider-v2 のツール呼び出しでは「レスポンスが空になる」問題が知られているようでした。
Ollama プロバイダーのドキュメントでも、ツール呼び出しの信頼性を求めるなら、もう一つのコミュニティプロバイダー ai-sdk-ollamaが選択肢として挙げられています。

モデル切り替えで解決

qwen3:14b に切り替えたところ、安定して動くようになりました:relaxed::point_up_tone1: ツール呼び出しはモデルの素の賢さがそれなりに要るようで、4B 系より 14B のほうが手堅かったです。

ollama pull qwen3:14b

直すのは agents.tsmodelollama('gemma4:12b') から ollama('qwen3:14b') に変えるだけ。plan / build の両エージェントとも同じです。

ollama-ai-provider-v2qwen3 の hybrid reasoningを明示サポートしています。
ツール呼び出しが必要な場面では、qwen3 系の方が若干安定している印象です。

ただ、実際のところ快適とは言えません。
ワークスペースに Next.js プロジェクトを初期化して、img タグを削除してもらう——くらいのタスクでも結構つまずきます:sweat_smile: とはいえ、ローカル LLM も PC のスペックもこれから進化していくはずなので、将来に期待です:point_up_tone1:

CC15E459-2F18-41E4-9569-EF27ABDBBB94.jpeg

ローカルモデルでのツール呼び出しは、モデルによって相性があります。
まずはシンプルな会話から試して、ツール呼び出しが必要な場合は別モデルも検討してみてください。

最後に

ここまで触ってみての所感です。

  • ローカルで動くのはやはり良いです。API コストゼロ、プライバシー安心
  • Gemma 4 はモデルとしては優秀ですが、ツール呼び出しには qwen3 の方が今のところ安定している
  • Mastra Harness はまだ Alpha ですが、「plan → build のモード切替」や「会話の永続化」が標準でついてくるのは便利

コーディングエージェントを作り込もうとすると、いずれ Claude や GPT クラスの高性能モデルが必要な場面は出てきます。

でも、チャットボットや文章作成、画像のようなマルチモーダルなメディア情報の読み取りといった用途なら、Gemma 4 で十分すぎるくらい使えます。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?