Genkit Goは、Googleがオープンソース(Apache-2.0)で開発しているGo向けのAIアプリ開発フレームワークです。Gemini・Claude・GPT・Ollamaなどのモデルを同じ関数で呼び出し、Goの構造体をそのまま入出力の型にした「フロー」として組み立て、HTTPで公開するところまでを1つのモジュールで扱えます。
初の安定版v1.0.0は、Goモジュールの版の日付が2025年9月9日(UTC)で、翌10日にGoogleが「Genkit Go 1.0」として発表しました。2026年10月時点の最新はv1.14.0です(版の日付は2026年10月19日、GitHubのリリース公開は10月20日)。なお「Go 1.0」はGo言語そのものの最初の安定版(2012年3月28日)を指すこともありますが、本記事で扱うのはGenkitのGo版の1.0以降です。以下のコードはGo 1.27.2とGenkit Go v1.14.0で、ビルドとテストを実行して確認しました。
まとめ:Genkit Goの要点と採用判断
- 正体:Google製のGo向けAIフレームワーク。モジュールパスは
github.com/firebase/genkit/goだが、Firebaseの契約やプロジェクトは不要 - 版:1.0(2025年9月)から約1年でv1.14.0まで進んだ。1.x系の安定APIは破壊的変更をしない方針
- 要件:Go 1.25以上。Geminiを使うなら
GEMINI_API_KEYを設定する - 中心機能:フロー(
DefineFlow)、型付きの構造化出力(GenerateData)、ツール呼び出し(DefineTool)、HTTP公開(Handler)、ローカルのDeveloper UI - v1.14の要点:ツールのerrorを
tool.Failでモデルに返して続行できるようになり、ツール内のpanicでプロセスが落ちなくなった。HTTPの失敗応答はJSONになった - 注意点:エージェントAPI(1.10で追加)と
expパッケージはプレビュー扱いで、マイナー版でも仕様が変わる - 向く場面:GoのバックエンドにLLM呼び出しを組み込み、モデルの切り替え・トレース・型検証をまとめて持ちたい場合。複数エージェントの編成と評価が主目的ならADK for Goも候補になる
以下、位置づけ、版ごとの変更点、導入手順、実装例と実測した挙動、テスト方法、ADK for Goとの使い分け、採用を見送る条件の順に説明します。
Genkit Goの位置づけ:Google製のGo向けAIフレームワーク
1.0までの経緯とリポジトリの移転
Genkitは先にJavaScript/TypeScript版が出ており、Go版は2024年7月17日にGoogle Developers Blogで「alpha」として紹介されました。その後v0.7.0(2025年8月25日)を経て、v1.0.0で本番利用を前提とした安定版になっています。1.0の告知では、型安全なフロー、複数プロバイダーを統一したモデルインターフェース、ツール呼び出し・RAG・マルチモーダル、単体バイナリのCLIとDeveloper UI、AIコーディングアシスタント向けの genkit init:ai-tools コマンドが挙げられています。
開発リポジトリは現在 github.com/genkit-ai/genkit に移り、旧URLの firebase/genkit から転送されます。一方、Goのモジュールパスは github.com/firebase/genkit/go のままです。公式のAPI安定性ページは「v1系の間はこのパスを変えず、v2を出すときは /v2 を付ける」と明記しているため、既存の import 文を書き換える必要はありません。
Google Gen AI SDKとの違い
Gemini APIを呼ぶだけなら、Googleの Google Gen AI SDK のGo版(google.golang.org/genai)でも足ります。Genkit Goの googlegenai プラグインは内部でこのSDKを使っており、v1.12からは Client() でSDKのクライアントを取り出せます。違いは上に乗る層で、Genkitはモデルの差し替え、入出力のJSONスキーマ検証、ツール呼び出しのループ、トレース、HTTP公開を持っています。Gemini以外のモデルに切り替える可能性があるか、フローの実行履歴を追いたいなら、Genkitを選ぶ理由になります。複数のエージェントフレームワークを横並びで比べたい場合は AIエージェントフレームワークの比較記事 を参照してください。
1.0からv1.14までの版ごとの変更点
GitHubのリリースノート(タグ go/v*)から、機能追加のあった版を抜き出しました。日付はGoモジュールプロキシが返す各版の日時(UTC)で、GitHubのリリース公開日とは1日ずれることがあります。
| 版 | 版の日付 | 主な変更 |
|---|---|---|
| v1.0.0 | 2025-09-09 | 初の安定版 |
| v1.1.0 | 2025-10-14 | Vertex AI Vector Searchプラグイン、ModelResponse.Media() |
| v1.3.0 | 2026-01-07 | Anthropicプラグイン、マルチパートツール、プロンプトのバイナリ埋め込み |
| v1.4.0 | 2026-01-14 | セッション、ツール割り込みAPIの改良 |
| v1.5.0 | 2026-03-19 | NewFlow、チャネル型ストリーミングフロー、HandlerFunc |
| v1.7.0 | 2026-04-29 | ミドルウェアV2(再試行・フォールバック・ツール承認) |
| v1.9.0 | 2026-06-16 | gemini-3系・Imagen 4・TTSモデルの登録 |
| v1.10.0 | 2026-06-26 | エージェントAPI(プレビュー)、双方向ストリーミング |
| v1.12.0 | 2026-08-17 | xAI・DeepSeek・Qwen・Kimi・GLM・OpenRouterに対応、エラー分類の統一 |
| v1.13.1 | 2026-09-03 | 失敗時も途中結果を返す、サブエージェントのバックグラウンド実行 |
| v1.14.0 | 2026-10-19 | 型付きの再開ツール、tool.Fail、ツールのpanic回復、使用量の集計と上限、HTTP失敗応答のJSON化 |
v1.13.0は同じ日にv1.13.1へ差し替えられ、go.mod で撤回(retract)されています。go get で1.13系を指定するならv1.13.1を選びます。v1.13ではツールやフローがerrorと一緒に値も返すようになり、ブロックされた応答が ai.ErrGenerationBlocked になりました。値の有無だけで分岐しているコードは、上げる前に見直してください。
v1.14.0の主な変更:ツールのエラー・HTTP応答・割り込みAPI
v1.14.0のリリースノートは、ツールと割り込みを「型付きで安定」させた版だと説明しています。既存コードに影響しやすい点は次の4つです。
- ツールのエラーをモデルに返せる:ツール関数が
tool.Failでerrorを包むと、生成は止まらず、モデルに{"error": "..."}が渡ります。包まないerrorは従来どおり生成全体を止め、ai.ErrToolFailedで判定できます(次章で実測) - ツール内のpanicでプロセスが落ちない:panicは「tool panicked」というツールのerrorに変わり、値とスタックはエラーログにだけ出ます
- HTTPの失敗応答がJSONになった:
genkit.Handlerの非ストリーミングの失敗は{"status":"INVALID_ARGUMENT","message":"..."}の形で返ります。本文を文字列として読んでいたクライアントは直す必要があります - 割り込みAPIの多くが非推奨:
ai.InterruptWith・RestartWith・WithToolRestartsなどは、genkit.DefineResumableToolとai.WithResume、ai/toolパッケージの関数へ置き換えが案内されています。非推奨のAPIはv1.14でもコンパイルは通ります
このほか、ツール往復を含む全モデル呼び出しのトークン数を合計する resp.TotalUsage、トークン数や費用で実行を止める Budget ミドルウェア(実験的。上限の判定は各モデル呼び出しの前に行うため、1ターン分超えることがあります)、長いツールループの文脈を圧縮するミドルウェアが入りました。公式CIのテストはGo 1.27で回っています。
安定APIとプレビューAPIの境界
API安定性ページによると、破壊的変更がメジャー版に限られる安定APIと、マイナー版でも変わりうるプレビューAPIが分かれています。プレビューはパッケージパスの exp または x(ai/exp/localstore や core/x/streaming のようにその配下も含む)と、genkit.WithExperimental() の指定で見分けます。エージェント、セッションストア、A2UI、再接続できるストリーミングなどがプレビューに当たります。genkit/exp の関数は genkit.Init に genkit.WithExperimental() を渡さないと使えず、手元で試すと「experimental features are not enabled」というpanicで止まりました。本番コードはまず安定APIだけで組み、プレビューは版を固定して使うのが安全です。
導入手順:Go 1.25以上とAPIキーの準備
現行のGet startedは「Go 1.25以降が必要」と書いており、v1.14.0の go.mod も go 1.25.0 です。以前のFirebaseドキュメントには「Go 1.24以降」とあるので、古い手順を見ている場合は注意してください。プラグインは同じモジュールに入っているため、go get は1回で済みます。
mkdir hello-genkit && cd hello-genkit
go mod init example/hello-genkit
go get github.com/firebase/genkit/[email protected]
export GEMINI_API_KEY='ここをGoogle AI Studioで発行したキーに置き換える'
# コードを書いたあとで依存を解決する
go mod tidy
GEMINI_API_KEY(または GOOGLE_API_KEY)が未設定のまま起動すると、genkit.Init の中でpanicになり、サーバーは立ち上がりません。OpenAIは OPENAI_API_KEY、Anthropicは ANTHROPIC_API_KEY を読み、ローカルのOllamaはキー不要です。
Initの性質:errorを返さず、1プロセスに1つ
Get startedは genkit.Init の性質を次のように説明しています。サーバーに組み込む前に押さえておく点です。
- errorを返さない:APIキーの欠落、同名プラグインの重複、指定したプロンプトディレクトリが無いといった設定の誤りは、すべて
Initの中のpanicになります。コンテナで動かすなら、起動前に環境変数を検査するか、起動直後に落ちることを前提に監視してください - 1プロセスに1つ作って共有する:返る
*genkit.Genkitは複数のgoroutineから同時に使ってよく、Define*が返すフローやツールも同様です。定義はリクエストを受ける前の起動時にすべて済ませます - 既定のタイムアウトは無い:リクエストごとのタイムアウトは設定されず、再試行やプロバイダーの切り替え(フォールバック)もミドルウェアを足したときだけ動きます。HTTPサーバー側か
context.WithTimeoutで上限を決めてください
フローと構造化出力の実装例
料理名と人数を受け取り、レシピを構造体で返すフローをHTTPで公開する最小構成です。次のコードを main.go に保存し、依存解決後に go run . で起動します。使用する gemini-flash-latest は参照先が更新されるため、本番では利用可能な具体的モデル版を指定して動作を確認してください。DefineFlow の入出力の型からJSONスキーマが作られ、入力の検証とDeveloper UIへの登録が自動で行われます。
package main
import (
"context"
"log"
"net/http"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
type RecipeInput struct {
Dish string `json:"dish"`
Servings int `json:"servings,omitempty"`
}
type Recipe struct {
Title string `json:"title"`
Ingredients []string `json:"ingredients"`
Steps []string `json:"steps"`
}
func main() {
ctx := context.Background()
// GEMINI_API_KEY を環境変数から読む
g := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-flash-latest"),
)
recipeFlow := genkit.DefineFlow(g, "recipeFlow",
func(ctx context.Context, in RecipeInput) (*Recipe, error) {
r, _, err := genkit.GenerateData[Recipe](ctx, g,
ai.WithPrompt("%sのレシピを%d人分で作ってください", in.Dish, max(in.Servings, 1)),
)
return r, err
})
mux := http.NewServeMux()
mux.HandleFunc("POST /recipeFlow", genkit.Handler(recipeFlow))
log.Fatal(http.ListenAndServe(":8080", mux))
}
起動後は、入力を data キーで包んでPOSTします。応答は result キーに入ります。
curl -X POST http://localhost:8080/recipeFlow \
-H "Content-Type: application/json" \
-d '{"data": {"dish": "肉じゃが", "servings": 2}}'
# 応答の形: {"result": {"title": "...", "ingredients": [...], "steps": [...]}}
genkit.Handler は標準の http.HandlerFunc を返すため、net/httpやChiにそのまま組み込めます。Ginでは gin.WrapF、Echoでは echo.WrapHandler などでハンドラーの型を変換します。errorを返すハンドラーを前提とするフレームワーク向けには、v1.5から genkit.HandlerFunc があります。公式のGet startedには、Gin・Echo・Chi・net/httpそれぞれのバックエンドのガイドと、Next.js・SvelteKit・Nuxtなどからフローを呼ぶフロントエンドのガイドがあります。
GenerateDataの戻り値は3つ
genkit.GenerateData[T] は (*T, *ai.ModelResponse, error) の3つを返します。v1.13.1のREADMEにある構造化出力の例は recipe, _ := genkit.GenerateData[Recipe](...) と2変数で受けており、そのまま貼ると「assignment mismatch: 2 variables but genkit.GenerateData[Recipe] returns 3 values」でコンパイルできませんでした。v1.14.0のREADMEでは recipe, resp, err := の3変数に直っています。古いREADMEやブログから写す場合は戻り値の数を確認し、トークン数などを使わないなら上の例のように2つ目を _ で捨てます。
スキーマの渡し方とJSONが崩れたときの挙動
モデルが構造化出力に対応しているかどうかで、スキーマの渡し方が変わります。スタブのモデルを登録し、モデルが受け取ったリクエストと戻り値を記録して確かめました。v1.13.1とv1.14.0で結果は同じです。
| 条件 | 実測した挙動 |
|---|---|
| モデルが制約付き出力に非対応 | プロンプト末尾にスキーマ指示の文が追加される |
| モデルが制約付き出力に対応 | スキーマはリクエストの出力設定で渡り、プロンプトは変わらない |
| 応答が “`json で囲まれている | 中のJSONを取り出して成功する |
| 型違い・必須フィールド欠落 | errorになる(再試行はしない) |
| JSONでない文章 | 「data is not valid JSON」のerrorになる |
非対応モデルに付く指示文は「Output should be in JSON format and conform to the following schema」で始まり、生成されたスキーマには additionalProperties: false が入っていました。omitempty の無いフィールドは必須として扱われ、型違いと必須欠落のどちらでも、モデルの呼び出しは1回で終わりました。Gemini(googlegenai)は制約付き出力に対応したモデルとして登録されています。JSONの形式やスキーマの検証に失敗した場合は、GenerateData の呼び出し側で回数を制限して再試行します。標準のRetryミドルウェアはモデル呼び出しのエラーを対象とするため、その後に行われる出力検証の失敗は再試行しません。JSON出力の仕組みは JSONモードと構造化出力の解説 で詳しく扱っています。
ツール呼び出しとエラーの扱い(v1.14で変更)
ツールは DefineTool で定義し、ai.WithTools で渡します。モデルがツールを要求すると、Genkitが実行して結果をモデルへ返し、最終回答が出るまでこれを繰り返します。次の例は、登録の無い商品コードを tool.Fail でモデルに伝える書き方です(v1.14.0以降)。前の例と同じディレクトリに置くと main 関数が重複するので、stock/main.go のように別ディレクトリに保存して go run ./stock で実行します。
package main
import (
"context"
"fmt"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/ai/tool"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
type StockInput struct {
SKU string `json:"sku"`
}
type StockResult struct {
SKU string `json:"sku"`
Count int `json:"count"`
}
var inventory = map[string]int{"A-100": 12, "B-200": 0}
func main() {
ctx := context.Background()
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{}))
stockTool := genkit.DefineTool(g, "lookupStock",
"商品コード(SKU)の在庫数を返す",
func(ctx *ai.ToolContext, in StockInput) (StockResult, error) {
n, ok := inventory[in.SKU]
if !ok {
// モデルに {"error": "..."} を返して生成を続ける(v1.14以降)
return StockResult{}, tool.Fail(ctx, fmt.Errorf("SKU %s は登録されていません", in.SKU))
}
return StockResult{SKU: in.SKU, Count: n}, nil
})
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-flash-latest"),
ai.WithPrompt("A-100とC-300の在庫を教えてください"),
ai.WithTools(stockTool),
ai.WithMaxTurns(5),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Text())
}
ツールがerrorを返したときの実測
ツールを1回呼んだあと、返ってきたツールの応答を記録して回答するスタブのモデルで、ツール側の返し方を4通り試しました(v1.14.0)。
| ツール側の返し方 | Generateの結果 | モデル呼び出し | モデルが受け取ったもの |
|---|---|---|---|
| そのままerrorを返す | error(ai.ErrToolFailed) |
1回 | なし |
tool.Fail で包む |
成功 | 2回 | {"error": "no such code"}(isError=true) |
そのままerror+SoftToolErrors |
成功 | 2回 | {"error": "no such code"}(isError=true) |
| panicする | error「tool panicked」(ai.ErrToolFailed) |
1回 | なし |
何もしなければ、ツールのerrorは「tool “lookup” failed: error calling tool lookup: no such code」として Generate のerrorになり、モデルには渡りません。v1.13.1までのREADMEは、モデルが回避できる失敗をerrorでなく結果の値(見つからなかったことを示すフィールドなど)に入れて返すよう案内していました。v1.14.0では、モデルが入力を直せば済む失敗(存在しないコード、SQLの構文誤りなど)は tool.Fail で返し、DB接続断のように続けても意味のない失敗は通常のerrorで止める、という使い分けができます。自分で書いていないツール(MCPサーバーのツールなど)のerrorをまとめてモデルに返すには、plugins/middleware の SoftToolErrors を ai.WithUse で付けます。panicは回復されて生成のerrorになり、プロセスは落ちませんでした。
ツール往復の上限は既定で50回
ツールを要求し続けるスタブのモデルでは、モデル呼び出し51回のあと「exceeded maximum tool call iterations (50)」で止まりました。v1.14.0のソース(ai/generate.go)でも既定値は50です。APIの課金はこの回数分かかるので、ai.WithMaxTurns で用途に見合う回数に下げておきます。v1.14.0からは、ツール往復を含む全モデル呼び出しのトークン数が resp.TotalUsage に合算されるので、1回の生成でどれだけ消費したかをログに残せます。
ツールをMCPサーバーとして外部に出したい場合、Genkit Goには mcp プラグインがあります。公式SDKで書く方法は MCP Go SDKの使い方 を参照してください。
APIキーなしでフローをテストする方法
genkit.DefineModelAction で決まった応答を返すモデルを登録し、WithDefaultModel でそれを既定にすれば、APIキーもネットワークも無しでフローのテストを回せます。モデルが受け取ったプロンプトも記録できるので、プロンプトの組み立てを検査できます。
モジュール直下に recipe ディレクトリを作り、次のコードを recipe/recipe.go、その次のテストを recipe/recipe_test.go に保存します。フローの定義は recipe パッケージに切り出し、*genkit.Genkit を引数で受け取る形にしておきます。
package recipe
import (
"context"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/core"
"github.com/firebase/genkit/go/genkit"
)
type RecipeInput struct {
Dish string `json:"dish"`
Servings int `json:"servings,omitempty"`
}
type Recipe struct {
Title string `json:"title"`
Ingredients []string `json:"ingredients"`
Steps []string `json:"steps"`
}
func DefineRecipeFlow(g *genkit.Genkit) *core.Flow[RecipeInput, *Recipe, struct{}] {
return genkit.DefineFlow(g, "recipeFlow",
func(ctx context.Context, in RecipeInput) (*Recipe, error) {
r, _, err := genkit.GenerateData[Recipe](ctx, g,
ai.WithPrompt("%sのレシピを%d人分で作ってください", in.Dish, max(in.Servings, 1)),
)
return r, err
})
}
package recipe
import (
"context"
"strings"
"testing"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
)
func TestRecipeFlow(t *testing.T) {
ctx := context.Background()
g := genkit.Init(ctx, genkit.WithDefaultModel("test/stub"))
var gotPrompt string
genkit.DefineModelAction(g, "test/stub",
&ai.ModelOptions{Supports: &ai.ModelSupports{Multiturn: true}},
func(ctx context.Context, req *ai.ModelRequest, _ any, _ ai.ModelStreamCallback) (*ai.ModelResponse, error) {
gotPrompt = req.Messages[0].Content[0].Text
return &ai.ModelResponse{
Message: ai.NewModelTextMessage(`{"title":"肉じゃが","ingredients":["じゃがいも"],"steps":["煮る"]}`),
FinishReason: ai.FinishReasonStop,
}, nil
})
flow := DefineRecipeFlow(g)
got, err := flow.Run(ctx, RecipeInput{Dish: "肉じゃが", Servings: 2})
if err != nil {
t.Fatal(err)
}
if got.Title != "肉じゃが" {
t.Errorf("title = %q", got.Title)
}
if !strings.Contains(gotPrompt, "2人分") {
t.Errorf("prompt = %q", gotPrompt)
}
}
Go 1.27.2とv1.14.0で go test ./recipe -v を実行した結果は --- PASS: TestRecipeFlow でした。構造化出力のパース、プロンプトへの人数の埋め込み、フローの入出力型を、実モデルを呼ばずに確かめられます。前の章の「スキーマ不一致」「ツールのerror」も、スタブの応答を変えれば同じ方法で再現できます。古い例にある DefineModel は非推奨で、ここで使っている DefineModelAction が後継です。
HTTP公開時のエラー応答
入力の型がスキーマと合わない場合、Handler は400を返します。{"data": 123} を文字列入力のフローに送ったときの応答本文は、版と環境変数で次のように変わりました。
| 条件 | 400の応答本文 |
|---|---|
| v1.13.1(本番) | invalid argument |
| v1.14.0(本番) | {"status":"INVALID_ARGUMENT","message":"invalid argument"} |
v1.14.0(GENKIT_ENV=dev) |
messageに「data did not match expected schema」を含む検証エラーの詳細 |
本番では検証エラーの詳細はサーバー側のログにしか出ません。READMEの説明では、クライアントに届くのは PublicErrorf で作ったメッセージだけで、それ以外は伏せられます。利用者に見せてよいエラー文は PublicErrorf で作り、本番で GENKIT_ENV=dev を付けたままにしないでください。v1.12でエラーの分類(NotFound・ResourceExhausted など)が統一され、分類に応じてHTTPのステータスコードが決まります。v1.14.0で本文がJSONになったのはJavaScript版のサーバーと形をそろえるためで、応答を文字列のまま表示していたクライアントは message を取り出すように直します。
Developer UIとCLIの使い方
CLIは単体バイナリで、macOSとLinuxは次のコマンドで入ります(Windowsは cli.genkit.dev から直接ダウンロード)。npmパッケージ genkit-cli としても配布されており、npmの latest は2026年10月6日(UTC)公開の1.44.1です。
curl -sL cli.genkit.dev | bash
genkit start -- go run .
genkit start でアプリを起動すると、Developer UIが http://localhost:4000 で開きます。登録したフローに任意の入力を与えて実行でき、モデル呼び出しごとのトレースも確認できます。ツール呼び出しが何往復したかを確かめるときに使います。
AIコーディングアシスタントにGenkitのコードを書かせる場合、現行のGet startedは npx skills add genkit-ai/skills でGenkitのAgent Skillを入れる方法を案内しています。1.0の告知で紹介された genkit init:ai-tools は、Gemini CLI・Firebase Studio・Claude Code・Cursor向けの設定を生成するコマンドで、それ以外のツールでは「generic」を選ぶと GENKIT.md が出力されます。
対応モデルとプラグイン
v1.14.0の plugins ディレクトリにあるモデル系プラグインと、読み込むAPIキーの環境変数は次のとおりです。OpenAI互換のプロバイダーは compat_oai の下にまとまっています。
| プラグイン | 対象 | 環境変数 |
|---|---|---|
| googlegenai | Gemini(Google AI) | GEMINI_API_KEY/GOOGLE_API_KEY |
| googlegenai | Gemini(Vertex AI) | ADC+GOOGLE_CLOUD_PROJECT(Express ModeはVERTEX_API_KEY) |
| anthropic | Claude | ANTHROPIC_API_KEY |
| compat_oai/openai | GPT | OPENAI_API_KEY |
| compat_oai/deepseek | DeepSeek | DEEPSEEK_API_KEY |
| compat_oai/xai | Grok | XAI_API_KEY |
| compat_oai/openrouter | OpenRouter経由の各社モデル | OPENROUTER_API_KEY |
| vertexai/modelgarden | Vertex AI上のClaude・Llama・Mistral | Google Cloudの認証 |
| ollama | ローカルモデル | 不要 |
このほか compat_oai の下にQwen(dashscope)・Kimi(kimi)・GLM(zai)があります。モデル以外では、ベクトル検索の pinecone・weaviate・postgresql・alloydb・localvec、Firestore連携の firebase、Cloud Loggingとトレースの googlecloud、評価用の evaluators、mcp、再試行やフォールバックの middleware がそろっています。v1.14.0では、OpenTelemetryのGenAIセマンティック規約でスパンとメトリクスを出す otelgenai が加わりました。同じ版から、Genkitはグローバルな TracerProvider を自分では登録しなくなっています。
ADK for Goとの使い分け
GoogleはGo向けに、Genkitとは別にADK for Go(Agent Development Kit)も公開しています。モジュールは google.golang.org/adk で、Goモジュールプロキシ上の版の日付はv1.0.0が2026年3月20日、v2系(google.golang.org/adk/v2)のv2.0.0が同年6月30日で、2026年10月時点ではv2.6.0(10月13日)とv1.9.0(10月15日)が並行して更新されています。どちらもApache-2.0で、go.mod の要件はv1.9.0がGo 1.25、v2.6.0がGo 1.26.6です。
READMEの説明では、ADKは「AIエージェントを構築・評価・デプロイするためのツールキット」で、複数の専門エージェントを組み合わせるマルチエージェント構成と、Cloud Runなどへのデプロイを前面に出しています。Genkitはモデル呼び出し・構造化出力・ツール・フローといった部品を、既存のGoサーバーに組み込む側に重心があります。迷ったときは次の基準で選びます。
| やりたいこと | 向く方 |
|---|---|
| 既存のAPIサーバーにLLM呼び出しを足し、入出力を構造体で検証したい | Genkit Go |
| Gemini以外(Claude・GPT・Ollamaなど)へ同じコードで切り替えたい | Genkit Go(プラグインで切り替え) |
| 役割の違うエージェントを複数組み合わせ、評価まで回したい | ADK for Go |
| PythonやJavaのADKで作ったエージェント構成をGoでもそろえたい | ADK for Go |
Genkit Goにもエージェント機能(1.10で追加)はありますが、v1.14.0の時点でもプレビューです。エージェントを本番の中心に置くなら、ADKの安定版と比べてから決めてください。ADKそのものの仕組みは、Python版を中心に ADKとは?GoogleのAgent Development Kitの仕組みと始め方 で解説しています。
Genkit Goの採用を見送るべき場面
次のどれかに当たるなら、Genkit Goを入れずに各社のSDKを直接呼ぶか、別のフレームワークを選ぶほうが割に合います。
- Geminiを1か所で呼ぶだけ:モデルを替える予定もトレースも不要なら、Google Gen AI SDKで足ります。Go 1.27.2でlinux/amd64向けにビルドすると、Gen AI SDK(
google.golang.org/genaiv1.57.0)を直接呼ぶ最小例が約22.3MB、Genkit v1.14.0のgooglegenaiを使った上のレシピの例が約29.8MBで、約7.5MBの差でした(-ldflags="-s -w"付きでは15.2MBと20.4MB)。起動時間は測っていないので、サーバーレスのようにサイズとコールドスタートが効く環境では、自分の構成で同じ条件で測ってから決めてください - エージェントAPIを本番の中心に据えたい:1.10で入ったエージェントはプレビューで、v1.14.0でも失敗したターンの扱いやスナップショットの読み方が変わりました。マイナー版を上げるたびに追従が要ります
- Pythonの機械学習ライブラリと密に連携する:前処理や評価をPythonで書いているなら、GenkitのPython版や他のPythonフレームワークのほうが、言語をまたぐ境界が減ります
逆に、GoのAPIサーバーにLLM機能を足し、入力と出力を構造体で検証し、トレースを見ながらプロンプトを詰めたい場合は、Genkit Goを入れる価値があります。安定APIの範囲で組めば、1.0のコードは1.x系の間はコンパイルが通る前提で運用できます。社内の業務システムに生成AIを組み込む設計から相談したい場合は、生成AI導入支援でも対応しています。Go本体の最新版は Go 1.27の新機能と移行ガイド で確認できます。
よくある質問
Genkit Goは無料で使えますか?
Genkit Go自体はApache-2.0のオープンソースで無料です。ただし呼び出すモデルのAPI料金(Gemini・OpenAI・Anthropicなど)は各社の料金体系で別にかかります。Ollamaでローカルモデルを動かす場合はAPI料金がかかりません。
Genkit GoはGoのどのバージョンから使えますか?
v1.14.0はGo 1.25以上が必要です(go.mod の go 1.25.0)。古いFirebaseのドキュメントにある「Go 1.24以降」は現行版には当てはまりません。本記事のコードはGo 1.27.2で確認しています。
Genkit Goを使うのにFirebaseは必要ですか?
必要ありません。モジュールパスに firebase が入っているのは開発元の経緯によるもので、プラグインなしで genkit.Init してフローを動かせることを手元で確認しました。FirestoreやFirebase Authenticationと連携したい場合だけ firebase プラグインを追加します。
Gemini以外のモデルも使えますか?
使えます。Claude(anthropic)、GPT(compat_oai/openai)、DeepSeek・Grok・Qwen・Kimi・GLM・OpenRouter(v1.12で追加)、Vertex AI Model Garden、Ollamaに対応しています。呼び出し側は ai.WithModelName("anthropic/...") のようにモデル名を指定します。ただし、切り替え先のプラグインの登録と認証設定が必要で、モデル固有の設定や対応機能も確認します。
ツールのエラーでGenerate全体が失敗するのを避けられますか?
v1.14.0以降は避けられます。ツール関数でerrorを tool.Fail で包むか、SoftToolErrors ミドルウェアを付けると、モデルに {"error": "..."} が渡って生成が続きます。包まないerrorは従来どおり生成全体を止めます。v1.13.1以前では、モデルに判断させたい失敗は結果の値に入れて返します。
Genkit Go 1.0で書いたコードは最新版でも動きますか?
安定APIだけを使っていれば、1.x系の間はシグネチャが変わらない方針で、v1.14で非推奨になった割り込み系のAPIもコンパイルは通ります。ただし、v1.13のerrorと一緒に返る値やv1.14のJSON化したHTTP失敗応答のように、戻り値や応答の中身は変わります。exp パッケージはマイナー版でも変更が入ります。