パート1では、Harper上で会話型AIエージェントを構築しました — セマンティックキャッシュ、ベクターメモリ、ローカル埋め込み、Web検索、チャットUIをすべて1つのプロセス内にまとめました。ClaudeにはAnthropicのダイレクトAPI経由で話しかけていました。
これは、個人開発者やスタートアップにはとてもよく機能します。ですが、組織がGoogle Cloudで運用しているなら、ClaudeはVertex AI経由にしたくなるはずです。請求も同じ、IAMも同じ、そしてGCPプロジェクト内の他のものと同じ監査ログが使えます。
朗報です。エージェントのロジックを作り直すことなく、ファイル変更3回で済みました。
なぜVertex AIなのか?
すでにGCP上にいるなら、Vertex経由でClaudeを動かすことで:
- 請求の統合 — Claudeのコストが、Compute Engine、BigQuery、Cloud Storageと同じ請求書に表示されます
- IAMと組織ポリシー — 既に管理しているのと同じロールと権限で、誰がClaudeを呼び出せるかを制御できます
- データの保管場所(データレジデンシ) — データをどこに置く必要があるかに応じて、リージョナル、マルチリージョン、またはグローバルのエンドポイントを選べます
- APIキー管理不要 — AnthropicのAPIキーを渡し回るのではなく、GCPのサービスアカウントで認証します
- クォータ制御 — GCPのクォータシステムを使って、プロジェクト単位・モデル単位でトークン上限を設定できます
ベースとなるモデルは同一です。Claudeも同じで、機能も同じで、応答品質も同じです。違いは入口(フロントドア)だけです。
変更したこと
Anthropic SDKとVertex SDKは、同じmessages.create()インターフェースを共有しています。違いは、クライアントを初期化する方法だけです。
1. Vertex SDKをインストールする
npm install @anthropic-ai/vertex-sdk
新しい依存関係が1つ増えるだけです。@anthropic-ai/sdkと並べて配置されるので、環境変数でプロバイダーを切り替えられるまま両方をインストールした状態にできます。
2. 設定を更新する(lib/config.js)
変更前 — Anthropicのみ:
export const config = {
anthropic: {
apiKey: () => required('ANTHROPIC_API_KEY'),
model: () => optional('CLAUDE_MODEL', 'claude-sonnet-4-5-20250929'),
},
}
変更後 — プロバイダー対応:
export const config = {
provider: () => optional('LLM_PROVIDER', 'anthropic'),
anthropic: {
apiKey: () => required('ANTHROPIC_API_KEY'),
model: () => optional('CLAUDE_MODEL', 'claude-sonnet-4-5-20250929'),
},
vertex: {
projectId: () => required('VERTEX_PROJECT_ID'),
region: () => optional('VERTEX_REGION', 'global'),
model: () => optional('VERTEX_MODEL', 'claude-sonnet-4-6'),
},
}
LLM_PROVIDERは、エージェントがどの経路を取るかを制御します。デフォルトはanthropicなので、既存のデプロイが壊れません。
3. エージェントを更新する(resources/Agent.js)
クライアントの初期化は、1行の記述から条件分岐に変わります:
import Anthropic from '@anthropic-ai/sdk'
import { AnthropicVertex } from '@anthropic-ai/vertex-sdk'
let _client
const getClient = () => {
if (_client) return _client
if (config.provider() === 'vertex') {
_client = new AnthropicVertex({
projectId: config.vertex.projectId(),
region: config.vertex.region(),
})
} else {
_client = new Anthropic({ apiKey: config.anthropic.apiKey() })
}
return _client
}
後続の呼び出し — getClient().messages.create(...) — はまったく同じままです。Vertex SDK は Anthropic SDK と API互換です。同じ messages、同じ tools、同じ system、同じ max_tokens。リファクタリング不要です。
唯一の機能上の違い:Anthropic のサーバーサイド Web 検索ツールは、デフォルトでは Vertex では利用できません(GCP 組織ポリシーの変更が必要なため)ので、スキップします:
const tools = isVertex() ? [] : [WEB_SEARCH_TOOL]
let apiResponse = await getClient().messages.create({
model: getModel(),
max_tokens: 1024,
...(tools.length && { tools }),
system: SYSTEM_PROMPT,
messages,
})
以上です。意味キャッシュ(semantic cache)、ベクトルコンテキスト(vector context)、ローカル埋め込み(local embeddings)、コスト計測(cost tracking)、チャットUI — すべてそのまま、変更なしです。
GCPセットアップ(5分)
まだ GCP プロジェクトがない場合は、console.cloud.google.com で作成してください。次に:
1. Vertex AI API を有効化:
https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOUR_PROJECT_ID
2. Model Garden で Claude を有効化:
Vertex AI Model Garden に移動し、「Claude」を検索します。有効化したいモデル(例:Claude Sonnet 4.6)を選んで有効化してください。ここで Anthropic の利用規約に同意します。
3. クォータの申請:
新しいプロジェクトは、パートナーモデルで tokens/min が 0 から始まります。IAM & Admin → Quotas に移動し、Claude のモデルでフィルタして、増加を申請してください。テストなら 100K tokens/min でも十分です。
4. サービスアカウントを作成:
IAM → Service Accounts → Create を開きます。Vertex AI User のロールを付与してください。JSON キーをダウンロードします。
5. .env を設定:
LLM_PROVIDER=vertex
VERTEX_PROJECT_ID=my-gcp-project
VERTEX_REGION=us-east5
GOOGLE_APPLICATION_CREDENTIALS=./my-service-account-key.json
6. エージェントを起動:
npm run dev
http://localhost:9926/Chat を開いてチャットを開始します。エージェントは現在、あなたの GCP プロジェクト経由で Claude を実行しています。
元に戻す
Anthropic の直接 API に戻したいですか? 1 行だけ変更してください:
LLM_PROVIDER=anthropic
再起動してください。完了です。Web 検索が自動的に復帰します。
変わらなかったこと
ここが強調する価値のある部分です。Vertex AI への切り替えでは、次の変更はゼロでした:
- 意味キャッシュ(semantic cache) — Harper の HNSW ベクトル検索は、LLM レスポンスがどこから来たか気にしません
-
ローカル埋め込み(local embeddings) —
bge-small-en-v1.5は、LLM プロバイダに関わらずプロセス内で動作します - スキーマ — 同じ 3 つのテーブル、同じベクトルインデックス、同じ TTL
- チャット UI — 同じ HTML、同じ WebSocket なしのポーリング、同じサイドバーの統計情報
- コスト計測 — トークン数は、両方の SDK から同じ形式で返ってきます
-
デプロイ —
harperdb deploy .は同じやり方で動きます
Harper が LLM 呼び出しより下のすべてを処理します。LLM 呼び出し自体は、バックエンドが 2 つあるだけの単一の関数です。バックエンドの入れ替えは書き換えではなく、設定変更です。
全体像
.env: LLM_PROVIDER=vertex
│
▼
┌─────────────────────────┐
│ resources/Agent.js │
│ │
│ getClient() ─────────► AnthropicVertex (GCP 認証情報)
│ getModel() ─────────► claude-sonnet-4-6
│ │
│ その他すべて: │
│ same cache, same │
│ embeddings, same │
│ vector search, same │
│ cost tracking │
└────────┬────────────────┘
│
▼
┌─────────────────────────┐
│ Harper │
│ DB + ベクトル + キャッシュ + │
│ API + 埋め込み │
│ (変更なし) │
└─────────────────────────┘
まず試してみる
返却形式: {"translated": "翻訳されたHTML"}リポジトリはgithub.com/stephengoldberg/agent-example-harperにあります。これをクローンし、プロバイダーを選択して、npm run dev を実行してください。
すでに第1部の内容でエージェントを実行している場合、差分は小さいです:
npm install @anthropic-ai/vertex-sdk
# .env を GCP の設定で更新
npm run dev
変更されたファイルは3つです。エージェントのロジックは一切書き換えていません。Claudeはそのまま、エンタープライズ向けのGCP統合です。



