プロファイルを選ぶ
セッションがどのモデル・ツール・権限モードで動くかを決めるプロファイル
プロファイル (profile) は、セッションの動作方式を決める。runtime とそのバージョン、モデル、ツール一覧、権限モード、モデル provider、リポジトリを使うかどうかである。運用担当者のプロファイル は、そのインストールのすべてのワークスペースが使える最も広い範囲を決める。インストールのデータベースにあり、ユーザーは id を指定して選ぶ。プロファイルごとに動作できるリポジトリの一覧もその行にある。新しいインストールにプロファイルはない。インストールのオーナーがコンソールの設定 > エージェント接続 > モデル接続で接続を追加し、プロファイルを作るときにその接続を選ぶ。プロファイル画面では接続を作ったり変更したりせず、選ぶだけである。接続もインストールのデータベースにある。接続の追加ダイアログは、選んだ種類の公式エンドポイント (anthropic は https://api.anthropic.com) を入力済みにする。プロキシや互換サーバーを使うときだけ変更すればよく、空のまま送っても同じアドレスで保存される。公式アドレスのない種類 (litellm) は、エンドポイントを自分で入力する。エンドポイントは作成後に変更できない。接続を使用停止すると、その接続だけでモデルを呼ぶプロファイルとエージェントは、再び有効にするまで動かない。確認ダイアログは、取得できた影響の数 (プロファイル、有効なリリースのエージェント、未終了のセッション) を示す。使用停止した接続は、同じ画面の再び有効にするで戻せる。ただし、保存したキーがない場合や、同じ定義の別の接続が使用中の場合は戻せない。プロファイルが使っていた接続が利用できなくなったときは、フォームが先頭の接続に置き換えず、接続を選び直させる。
一覧を見る
SDK の例は SDK のインストールで作った werft クライアントを、HTTP API の例はサーバーのアドレス API とキー KEY のシェル変数を使う。
const profiles = await werft.profiles.list();
for (const profile of profiles.items) {
console.log(profile.id, profile.model, profile.repository_mode);
}claude-coding-auto claude-sonnet-5 required
claude-coding-local claude-sonnet-5 required
general claude-sonnet-5 none| フィールド | 意味 |
|---|---|
model | デフォルトのモデル |
tools | セッションで使えるツール。これ以外のツールは実行されない (権限) |
deny | このプロファイルがブロックする組み込みツール。このインストールがその runtime バージョンでサポートする組み込みツールのうち、tools にないもの。サポート一覧がないバージョンなら null (ツールのブロックリスト) |
billing | metered ならコストをセッションの上限に計上する。none なら計上しない |
repository_mode | required (リポジトリ必須)、optional、none (リポジトリなし) |
provider のアドレスと認証情報は一覧に表示されない。その値は worker にも渡されない。
セッションで選ぶ
セッションを作成するとき、profile_id で選ぶ。プロファイルが複数のモデルを許可している場合は model でその中の 1 つを選び、省略するとデフォルトのモデルで動く。
実行中のセッションのモデルが許可リストから外れると、モデルへのリクエストはまもなく切断される。セッションのイベントに error イベント(code: MODEL_NOT_ALLOWED、model)が 1 回残り、セッション詳細のタイムラインに「… がプロファイルの許可リストから外れたため、このセッションのモデルリクエストがブロックされました」と表示される。許可リストを元に戻すか、別のモデルで新しいセッションを開始する。
モデルが許可リストから外れたためにブロックされる経路は、どれもそのモデル名を伝える。
- 実行中のターンは上の
errorイベントである。プロファイルやモデル接続ごとなくなってブロックされるときも同じイベントが残り、causeはprofile_removed(モデルだけが外れた場合はmodel_removed)、modelにはセッションが使っていたモデルが入る。 - 次のメッセージで新しい worker を起動しようとして止まると、セッションは
failedになる。同じerrorイベント(cause: model_removed)と「モデル … がプロファイル … の許可リストから外れた」という理由が、セッションのイベントと入力 receipt に残る。セッション詳細のattention(CATALOG_MISMATCH)も外れたモデル名を伝える。 - 許可リストにないモデルで新しいセッションを作ると、
422 UNSUPPORTED_CAPABILITYがモデル名を伝える。リクエストがモデルを指定せず、リリースのモデルで動く場合も同じである。 - 許可リストから外れたモデルのリリースを有効化したり、そのリリースでセッションを作ったりすると、
PROFILE_DIGEST_MISMATCHがリリースのモデルが許可リストから外れたことをモデル名とともに伝える。
プロファイル詳細は「このプロファイルを使うエージェント」の上に、エージェントの概要は準備状況の上に、どのモデルが外れたかと対処(モデルをリストに戻すか、エージェントの詳細設定でモデルを許可されたものに変更して保存する)を警告として表示する。
同じシリーズの新しいモデルへ切り替える
運用担当者のプロファイル(設定ドキュメントの profiles)に model_families を書いておくと、リストから外れたモデルのセッションは、止まる代わりに同じシリーズの新しいモデルへ切り替わる。モデル名から推測はせず、書かれた値だけを使う。
"model_families": {
"claude-sonnet-5-0": { "family": "sonnet", "rank": 0 },
"claude-sonnet-5-1": { "family": "sonnet", "rank": 1 }
}familyが同じモデルは 1 つのシリーズで、rankが大きいほど新しい。同じfamilyでrankが重なると設定は拒否される。- リストから外れたモデルのエントリも消さない。ないと、そのモデルがどのシリーズか分からず、これまでどおり止まる。
- 候補は、許可リストにある同じ
familyでrankが高いモデル。複数あれば最も近い(最も低い)1 つ。低いrankへ下がることも、別のfamilyへ移ることもない。候補がなければ上で説明したとおり止まる。 model_familiesはセッションの固定値(フィンガープリント)に入らない。書いたり変えたりしても、作成済みのセッションとリリースはそのまま。
切り替えは、セッションが次のターンを始める claim で行う。ターンを待っているセッションだけが切り替わり、実行中のターンには触れない。そのターンは上で説明したとおりモデルリクエストが切られる。切り替えるとセッションイベントに system イベント(subtype: model_migrated、from、to)が残り、タイムラインに「…から…に切り替えました」と表示される。前のモデルで作ったチェックポイントは、切り替え後もそのまま復元できる。
リリースのモデルが外れても候補があれば、そのリリースでセッションを作れる。セッションは候補のモデルで始まり、セッションを作ってもリリースは変わらない。リクエストが model を直接指定した場合は、許可リストにあるモデルでなければならない。プロファイルの要約(GET /v1/profiles)の model_successors が、外れたモデルと切り替え先を示し、このときエージェントの概要はブロックの警告ではなくお知らせを表示する。
エージェントのアクティブなリリースも候補に切り替わる。サーバーが理由 model_migration の新しいリリースを作って有効化し、監査 receipt に前後のモデルと automatic: true が残る。人が操作したものではないため、実行者はそのリリースを最後に有効化した人(owner か admin が必要) になる。その人が無効化されている、または owner・admin でなくなっている場合は切り替えず、エージェントはブロックされたままで、管理者に失敗の DM が届く。切り替えた後はエージェントの管理者に DM が届く。エージェントの auto_model_migration(PATCH /v1/agents/{id}、既定は true)を false にすると、リリースの書き換え・セッションの切り替え・新しいセッションでの候補の利用がすべて止まり、このエージェントはブロックされる。エージェント概要の警告からも切り替えられる。
この仕組みは、運用担当者のプロファイルのモデルリストが変わる場合を扱う。ワークスペースのプロファイルのバージョンは、作成後にモデルリストが変わらない。
最初にブロックされたとき、Slack の DM も 1 回届く。DM にも外れたモデル名が入る。宛先はセッションを作成した人とエージェントの管理者(直接指定した管理者、管理者チームのメンバー、担当チームの lead)で、それぞれこのエージェントの Slack アプリがインストールされたチームに Slack アカウントを連携している場合だけ届く。1 つのセッションにつき 1 人 1 回なので、同じセッションの次の試行がブロックされても再送されない。ほかの理由で終了したセッションには送らない。
const created = await werft.sessions.create({
profile_id: "claude-coding-local",
model: "claude-sonnet-5",
repository_id: "sample-app",
message: 'GATE-SPEC {"id":"profile","steps":[],"final":"ok"}',
});
const sessionId = created.session_id;
console.log((await werft.sessions.get(sessionId)).runtime);{
kind: 'claude_agent_sdk',
version: '0.3.319',
profile_id: 'claude-coding-local',
model: 'claude-sonnet-5',
permission_mode: 'default'
}カタログにないプロファイル、そのリポジトリで動作できないプロファイル、プロファイルが許可していないモデルは 422 になる。
エージェントのリリースを作成するときは、runtime_profile_id で選ぶ。カードの model がそのプロファイルで実行できるモデルのひとつで、カードのツールがすべてプロファイルにある必要がある (作成)。
ツールのブロックリスト
プロファイルのバージョンは、使うツールを並べる代わりに、ブロックする組み込みツールだけを deny に書ける。運用担当者のプロファイルなら、サーバーはバージョンを保存するとき、このインストールがその runtime バージョンでサポートする組み込みツールのうち deny にないものを tools として保存する。ワークスペースのプロファイルは、下のとおりベースのツールの中で計算する。セッションとリリースは保存された tools だけを見る。
- 制限なしはサポート一覧の中での話である。 運用担当者のプロファイルの
deny: []はサポート一覧の組み込みツールをすべて開く。エンジンに入っていても、このインストールがサポートしないツールは開かない。サポート一覧とツールごとの実行場所 (boundary) は、オーナーがGET /v1/installation-profiles/optionsのtool_catalogsで見る。 - 実行場所。
localは worker の中で、egressはプラットフォームの外部接続プロキシを通って外へ、providerはモデル provider 側で動く。provider 側のツール (WebSearch) は外部接続プロキシでは止められず、プロファイルのブロックだけが止める。そのため、新しい名前の最初のバージョンは provider 側のツールをdenyに入れて始めることを勧める。API はdenyに書いたものだけをブロックするので、deny: []はWebSearchも開く。コンソールは最初のバージョンで provider 側のツールを既定でブロックしておく。 - あとから増えたツールはブロックされたまま引き継がれる。 バージョンは保存したときのサポート一覧で
toolsを固定し、既存のバージョン・リリース・セッションは新しいツールを得ない。エンジンを上げると runtime バージョンが変わるので、新しいプロファイルのバージョンを作ることになる。このとき、前のバージョン (運用担当者のプロファイルはprevious_id、ワークスペースのプロファイルは同じ名前の最新バージョン) が検討していないツールは、accept_added_toolsに書いたときだけ新しいtoolsに入る。そのようなツールがdenyにもaccept_added_toolsにもなければ400(reason_code: added_tool_not_accepted) になる。前のバージョンをtoolsで作っていれば、その一覧の外のツールがすべてこれにあたる。 denyは組み込みツールの名前とmcp__<server>__<tool>の名前を受け付ける。 MCP の名前は、ツール一つを指すmcp__<server>__<tool>の形でなければならない。サーバー全体やパターンではブロックできない。形が違えば400(mcp_tool_name)、組み込みの GitHub サーバーのツールなら400(github_server) になる。このインストールの一覧にないサーバーなら400(unknown_mcp_server) になる。前のバージョンがすでにブロックしていた名前は、そのサーバーが一覧から外れていても改めて判定しない。レスポンスでは MCP の名前はdenyではなくmcp_denyに並べ替えて出て、denyには組み込みツールだけが残る。accept_added_toolsは組み込みツールの名前だけを受け付ける。 そこに MCP の名前を書くと400(mcp_tool) になる。denyとaccept_added_toolsのどちらでも、Bash(rm:*)のようなパターンは400(tool_pattern)、一覧にない名前は400(unknown_tool) になる。許可リスト (tools) で保存しても、前のバージョンがブロックしたmcp__の名前は引き継がれる。有効なリリースのプロファイルがブロックした MCP ツールは、エージェントの MCP 設定でも新たに許可できない (mcp_tool_denied)。- MCP のブロックは次のバージョンに引き継がれ、
unblock_mcp_toolsでだけ解除できる。 新しいバージョンは、前のバージョンがブロックしたmcp__の名前をすべて引き継ぐ。解除するには、その名前をunblock_mcp_toolsに書く。前のバージョンがブロックしていない名前は400(mcp_unblock_unknown)、同じ名前をdenyにも書くと400(mcp_unblock_conflict)、前のバージョンがなければ400(mcp_unblock_no_previous) になる。ワークスペースのプロファイル (POST /v1/workspace-profiles) の新バージョンは、前のバージョンをprevious_idで指す。その間に同じ名前でより新しいバージョンができていれば409(stale_previous) になる。 - ベースのプロファイルの上に作るバージョンは、ベースがブロックした MCP の名前を
denyに自分で書く。 書き漏らしたりunblock_mcp_toolsで解除しようとしたりすると400(base_mcp_deny_dropped) になる。 toolsとdenyのどちらか一方。 リクエストはどちらか一方だけを送る。両方送る、またはどちらも送らないと400になる。accept_added_toolsはdenyと一緒にだけ送る。toolsで送ると、これまでどおりその一覧のまま保存される。サポート一覧がない runtime バージョンはtoolsだけを受け付け、denyは400(no_tool_catalog) になる。- ワークスペースのプロファイルはベースを超えない。
toolsは、ベースのプロファイルのtoolsのうちサポート一覧にあるツールからdenyを除いたものである。そのためdeny: []でも、ベースが使わないツールは開かない。ベースがdenyで作ったバージョンでサポート一覧が同じなら、ベースがブロックしたツールをdenyから外すリクエストは400(base_denies) になる。 - 既存のバージョンはそのままである。
toolsで作ったバージョンも、一覧のdenyにはサポート一覧からtoolsを除いたものが出る。広げるにはdenyで新しいバージョンを作る。
下の例は、オーナーが 作成 の WEB ヘッダーで呼ぶ。まず、サポート一覧のうち worker の外へ出るツールを見る。
curl -sS "$API/v1/installation-profiles/options" "${WEB[@]}" \
| jq -c '.tool_catalogs[0].tools | map(select(.boundary != "local"))'[{"name":"WebFetch","boundary":"egress"},{"name":"WebSearch","boundary":"provider"}]ローカルプロファイルの次のバージョンを、WebSearch だけをブロックして作る。ローカルプロファイルは tools で作ったバージョンなので、NotebookEdit・WebFetch は検討したことのないツールである。
next=$(jq -nc '{name: "coding-local", previous_id: "claude-coding-local",
connection_id: "fake-messages", runtime_kind: "claude_agent_sdk", runtime_version: "0.3.319",
model: "claude-sonnet-5", models: ["claude-sonnet-5"], permission_mode: "default",
repository_ids: ["sample-app"], deny: ["WebSearch"]}')
curl -sS "$API/v1/installation-profiles" "${WEB[@]}" -d "$next" | jq -c '.error.details'
curl -sS "$API/v1/installation-profiles" "${WEB[@]}" \
-d "$(echo "$next" | jq -c '.accept_added_tools = ["NotebookEdit", "WebFetch"]')" \
| jq -c '.profile | {id, tools, deny}'{"reason_code":"added_tool_not_accepted","field":"accept_added_tools"}
{"id":"op_coding-local_v1","tools":["Read","Edit","Write","Glob","Grep","NotebookEdit","Bash","AskUserQuestion","WebFetch"],"deny":["WebSearch"]}リファレンス: POST /v1/installation-profiles
進行中のセッションのプロファイルを変更する
sessions.changeProfile(POST /v1/sessions/{id}/profile)で変更する。実行中のターンは開始時のプロファイルで終わり、その次の入力から新しいプロファイルで動く。会話と作業ツリーは最後の checkpoint から引き継がれる。同じプロファイルに変更しても何も変わらず、receipt だけが残る。
import { waitForTurn } from "@werft-ai/sdk";
await waitForTurn(werft, sessionId, created.turn_id);
const { revision } = await werft.sessions.get(sessionId);
const changed = await werft.sessions.changeProfile(sessionId, {
expected_revision: revision,
profile_id: "claude-coding-local",
});
console.log(changed.receipt_status);succeeded新しいプロファイルの runtime の種類・バージョンや課金方式が異なる場合、またはそのリポジトリと組み合わせられない場合は 422 UNSUPPORTED_CAPABILITY になる。エージェントのリリースで作成したセッションは、リリースがプロファイルを決めるため 409 RELEASE_PROFILE_MISMATCH になる。scope は sessions:control である。
ワークスペースのプロファイルを作る
ワークスペースのオーナーと管理者は、運用担当者のプロファイルを 1 つもとにして、このワークスペースだけで使うプロファイルを作れます。コンソールの ワークスペース > プロファイル で プロファイルを作成 を押します。
- 減らすことだけができます。モデルとツールはベースプロファイルにあるものから選び、権限モードはベースプロファイルと同じか、人がより多く確認するモードだけを選べます。ベースプロファイルが
autoを許可する場合(もとがautoかbypassPermissions)、新しいプロファイルはautoから始まり、プロファイルを作成 はそのようなベースプロファイルを先に選びます。もとが許可しないauto・bypassPermissionsは選べない選択肢として表示されます。bypassPermissionsのベースプロファイルは運用担当者がインストール設定を有効にしたインストールにだけあります。bypassPermissionsを選ぶと危険の案内が表示されます。runtime、provider、認証情報、リポジトリとの組み合わせはベースプロファイルのものをそのまま使います。 - 保存したバージョンは変わりません。編集 して保存するたびに新しいバージョンの id
ws_<ワークスペースの slug>_<名前>_v<n>ができ、画面は保存前にその id を表示します。前のバージョンを使う release は、新しいバージョンで release を作り直すまで変わりません。一覧は名前ごとに最新のバージョンを 1 行で表示し、前のバージョンは 前のバージョン N 件 を押して開きます。 - 行を押すと詳細画面(
/profiles/<id>)が開きます。モデル・ツール・権限モード・ベースプロファイル、同じ名前のバージョン履歴、有効なリリースがそのバージョンを使うエージェントが表示されます。エージェント一覧はエージェントを管理できる人だけに表示されます。オーナー・管理者は 使用可能 なバージョンの詳細で 編集 を押すと現在の値が入った編集画面を開きます(ベースプロファイル変更済み なら 作り直す、使用停止したバージョンやもとがないバージョンにはボタンがありません)。運用担当者のプロファイルの詳細では ワークスペースのプロファイルを作成 で新しいワークスペースのプロファイルを始めます。 - 一覧(
GET /v1/profiles)には運用担当者のプロファイル(source: "operator")とこのワークスペースのバージョン(source: "workspace")が一緒に出ます。コンソールは運用担当者のプロファイルを変更できません。運用担当者のカタログはws_で始まる id を使えないため、両者は重なりません。 - 運用担当者がベースプロファイルを変更するとバージョンは ベースプロファイル変更済み、削除すると ベースプロファイルなし、オーナーがブロックすると ベースプロファイルブロック中 になります。そのバージョンでは新しいリリースとセッションを作れません。もとが変わったバージョンは 作り直す で新しいバージョンを作ります。
- 使用停止 したバージョンは新しいリリースとセッションが選べません。すでにそのバージョンを使う release とセッションは動き続けます。使用停止は元に戻せません。
- リリースのプロファイル一覧は運用担当者のプロファイルとワークスペースのプロファイルを分けて表示し、新しいリリースを受けないバージョンは選べません。
- メンバーは一覧を見るだけです。作成・編集・使用停止はコンソールにログインしたオーナー・管理者だけができ(
POST /v1/workspace-profiles、POST /v1/workspace-profiles/{profile_id}/retire)、API key では 403 です。
auto ルールとスクリプト上限は画面に場所だけがあり、まだ変更できません。
運用担当者のプロファイルをブロックする
オーナーは運用担当者のプロファイルを 1 つ、いま動いているセッションまで含めて止められる。使用停止 (retire) は新しいリリースとセッションだけを止めるが、ブロックはそのプロファイルで動くものをすべて止める。Web ログインの cookie で、オーナーだけが行う。管理者・メンバーと API key は 403 になる。コンソールでは運用担当者のプロファイル詳細の ブロック・ブロック解除 から行い、確認ダイアログを通す。下の例は 作成 の WEB ヘッダーを使う。
curl -sS -X POST "$API/v1/installation-profiles/claude-coding-local/block" "${WEB[@]}" \
| jq -c '{state: .profile.installation.state, receipt_id}'{"state":"blocked","receipt_id":"…"}- プロファイルは ブロック中 (
blocked) になり、その上のワークスペースのプロファイルは ベースプロファイルブロック中 (base_blocked) になる。 - 新しいリリース、リリースの有効化、セッションは
409 PROFILE_BLOCKEDで拒否される。error.details.reason_codeはblocked(選んだプロファイルがブロック中)かbase_blocked(そのベースがブロック中)で、error.details.profile_idは選んだプロファイルである。そのプロファイルの既存セッションは新しいメッセージを409 PROFILE_BLOCKEDで拒否し(ブロック前に受け付けたメッセージを同じIdempotency-Keyで再送すると元の応答が返る)、GET /v1/sessions/{id}のattentionがPROFILE_BLOCKEDになる。ブロック前に積まれたターンは始まるときにcatalog_mismatchで終わり、いま動いているターンは 1 秒ほどでモデルとリポジトリへのリクエストが切れる。 POST /v1/installation-profiles/{profile_id}/unblockで解除すると元の状態に戻る。終わったセッションとターンは自動では動き直さないので、必要な入力をもう一度送る。- すでにその状態なら何も変わらず、
receipt_idはnullになる。