forge-cost-optimizer について
Atlassian Forge アプリを監査・最適化し、正確性、安全性、保守性を保ちながらプラットフォームの消費を抑えるエージェントスキルです。不要な呼び出しやデータ処理の削減を優先し、実装依頼が明示されない限り監査後に変更の許可を求めます。
主な機能
- 01Forge アプリのコスト要因を監査
- 02呼び出しを避ける機会の特定
- 03API・ストレージ・ログ処理の削減
- 04トリガーと関数メモリの確認
- 05認可境界とデータ安全性の維持
- 06優先順位付きの監査提案
活用シーン
- 01変更前に Forge アプリを評価
- 02不要な resolver やトリガーの実行を削減
- 03過剰な API リクエストやストレージ操作を特定
- 04計算とログのコストを確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ atlassian/ forge-skills --skill forge-cost-optimizerインストール後、Claude Code で/forge-cost-optimizerを入力して読み込まれたか確認します。
同梱ファイルREADME.md
詳細
Forge のコスト最適化
正確性、セキュリティ、保守性を維持しながら、Forge アプリのプラットフォーム消費量を最適化します。このスキルでは、Atlassian の Forge コスト最適化ガイダンスを、実行可能なエージェントのワークフローに変換します。
参考ガイダンス
Atlassian の公式ガイドに基づいて推奨事項を作成します:https://developer.atlassian.com/platform/forge/optimise-forge-costs/
Forge のドキュメントを参照できるツールが利用可能な場合は、現在のマニフェスト構文、ブリッジ API、ストレージ API、トリガーフィルター、Forge Remote の動作に依存するコードを変更する前に、Forge ドキュメントで該当するモジュールまたは API を検索してください。
基本原則
不要な処理を減らす変更を優先します。
- 呼び出し自体をなくす — 安全に実行できる処理を UI Kit/Custom UI のフロントエンドに移す、ブリッジからコンテキストを取得する、ポーリングをイベントに置き換える、トリガーフィルターを追加する。
- 呼び出しごとの処理量を減らす — API 呼び出しをまとめる、フィールドを選択する、データソース側でフィルタリングする、ページネーションを行う、早期リターンする、並行処理に上限を設ける。
- 課金対象となるデータ量を減らす — リゾルバーのペイロードを絞る、KVS の読み取り/書き込みを減らす、大きなログペイロードを避ける、適切な場合はエンティティプロパティを使用する。
- コンピューティングコストを調整する —
memoryMiBを適切な値に設定する、実行時間を短縮する、運用上のトレードオフが妥当な場合に限って処理をオフロードする。
認可を弱める、フロントエンドにシークレットを公開する、必須の検証を省略する、必要なエラー処理を削除する、またはユーザーの業務要件を超えてデータを古いままにすることで、コストを削減してはいけません。
起動時
ユーザーが既存の Forge アプリの最適化を依頼した場合、対象アプリのディレクトリが曖昧でない限り、質問する前にすぐアプリを調査してください。
**デフォルトの動作は監査優先です。**コスト最適化の監査を完了し、優先順位を付けた推奨事項を提示したうえで、推奨される変更をエージェントに実施させるかどうかをユーザーに確認してください。「変更して」「最適化を適用して」「これらの問題を修正して」「コードを更新して」など、同じプロンプト内で実装を明示的に依頼された場合を除き、初回の監査中にファイルを変更してはいけません。
次の順序で確認します。
manifest.yml/manifest.yaml— 関数、モジュール、トリガー、スケジュール済みトリガー、リモート、リソース、権限、エンドポイントのマッピング、memoryMiB。package.json— 依存関係、スクリプト、Forge パッケージのバージョン。- バックエンド/リゾルバーのコード —
src/**、マニフェストで参照されるハンドラー、ストレージの使用状況、API 呼び出し、ログ記録、非同期処理のフロー。 - フロントエンドのコード — UI Kit または Custom UI のリソース、ブリッジの使用状況、
invoke()のパターン、レンダリングのライフサイクル、キャッシュ、ペイロードの要件。 - 維持すべき動作を示すテストやフィクスチャ。
監査の後、すぐに効果が見込める改善をすべて実施する、効果の高い変更を選んで実施する、まず使用状況の測定値を収集するなど、次の手順を明確に提示してください。ユーザーが最初から実装を明示的に依頼している場合は、監査結果を把握した後、安全で局所的な改善を行い、トレードオフを説明してください。
最適化のワークフロー
ステップ 1:コストプロファイルを把握する
アプリで使用している可能性が高いコスト要因を特定します。
| 要因 | 確認対象 | よく見られる兆候 |
|---|---|---|
| 関数の GB 秒 | manifest.yml、ハンドラー | リゾルバーの呼び出しが多い、API 呼び出しが遅く逐次的、高い memoryMiB、負荷の高い変換処理 |
| 呼び出し回数 | フロントエンドの invoke()、トリガー | レンダリング時の呼び出し、頻繁な UI 呼び出し、スケジュールされたポーリング、広範なイベント購読 |
| KVS/カスタムエンティティ | storage.* の使用状況 | リクエストごとの書き込み、キーを順に処理するループ、TTL の短さによるキャッシュの頻繁な更新、大きな値 |
| ログ | console.* | イベント/API のペイロード全体の記録、頻繁に実行される処理内のデバッグログ |
| Forge SQL | SQL クライアントの使用状況 | コンピューティングリクエストが頻繁、クエリが長い、保存データが過剰に大きい |
| リモート/エグレス | remotes、fetch の呼び出し | 外部へのポーリング、コンピューティング処理のオフロード候補、Runs on Atlassian への影響 |
使用状況のメトリクスを取得できない場合は、推定値を定性的なものとして High、Medium、Low、Unknown のいずれかで示してください。
Step 2: 呼び出しをなくせる箇所を探す
呼び出しを安くするよりも、関数の呼び出し自体をなくすことを優先します。
以下を確認します。
- 商品コンテキストを取得するだけのリゾルバー呼び出し。以下に置き換えます。
- UI Kit:
@forge/reactのuseProductContext() - UI Kit または Custom UI:
@forge/bridgeのview.getContext()
- UI Kit:
- ユーザーコンテキストでのアクセスが許容されるにもかかわらず、リゾルバー経由で実行している読み取り専用の Jira/Confluence API 呼び出し。
@forge/bridgeのrequestJira()/requestConfluence()を検討します。 - リゾルバー内での書式設定、並べ替え、グループ化、クライアント側で安全に行える検証、UI のみで必要なデータ変換。コンテキストユーザーに対するデータの認可がすでに済んでいる場合は、フロントエンドに移します。
- レンダリング本体内の
invoke()呼び出し、制限のないエフェクト、繰り返し実行されるイベントハンドラー、キャッシュやバッチ処理が可能なページ読み込み時の複数の呼び出し。
asApp()、Forge ストレージ、シークレット、外部認証情報、ユーザー間の認可チェック、機密性の高いビジネスルールが必要なロジックはバックエンドに残します。
Step 3: トリガーとスケジュールを最適化する
scheduledTrigger、trigger、webtrigger モジュールを確認します。
推奨する変更:
- ビジネス要件が許す場合、スケジュール済みトリガーの間隔を延ばします(
fiveMinutes→hour→day→week)。 - Atlassian 製品の変更をスケジュール済みポーリングで確認する方法を、製品イベントに置き換えます。
- 外部サービスがウェブフックに対応している場合、外部サービスのスケジュール済みポーリングを、Forge ウェブトリガー経由の受信ウェブフックに置き換えます。
- マニフェストに
filter.expressionを追加し、関連性のない製品イベントが呼び出し前に除外されるようにします。 - アプリ自体が発生させたイベントを処理してしまう Jira トリガーには、
filter.ignoreSelf: trueを追加します。 - API 呼び出し、ストレージの読み取り、高コストな変換処理より前に、ハンドラーの先頭で低コストな早期終了を行います。
- バックエンドの状態変化を待つためにフロントエンドでリゾルバーを繰り返し呼び出すポーリングループの代わりに、Forge Realtime を使用します。
Step 4: API とデータ取得を最適化する
関数内のすべての API リクエストが処理時間に影響します。以下を確認します。
- N+1 呼び出し。アイテムごとの取得を、必要なフィールドを返す一括エンドポイントや検索 API に置き換えます。
fields、expand、limit、maxResultsの指定漏れ。アプリが使用するデータだけを要求します。- すべてのデータを取得してからのフィルタリング。JQL、CQL、REST クエリパラメーター、ストレージインデックスを使ってフィルターを適用します。
- 独立している呼び出しの逐次実行。
Promise.allまたは同時実行数の制限を使用します。 - 制限のない同時実行。レート制限を避けるため、大規模な処理はバッチに分けます。ドキュメントやテストで正当化できる場合を除き、同時リクエスト数は約 5~10 件にします。
- 大きなリゾルバー応答。UI が使用するフィールドだけを返します。
Step 5: ストレージを最適化する
KVS と Custom Entity の読み取り/書き込みは、無料枠を超えるとデータ量に応じて課金されます。書き込みのコストは読み取りよりも大幅に高くなります。
以下を確認します。
- 値が変わっていない場合も、呼び出しのたびに書き込んでいるケース。書き込み前に値を比較するか、書き込みをデバウンスします。
- 変更頻度の低いデータに対する非常に短いキャッシュ TTL。古いデータを許容できる場合は、より長い TTL を使用します。
- ループ内でのストレージ読み取り/書き込み。バッチ処理にする、キーの構成を見直す、または Custom Entity のクエリを使用します。
storage.query().getMany()の後にメモリー上でフィルタリングしているケース。.index(...)、.where(...)、.limit(...)、カーソルページネーションを使用します。- 必要なのは一部だけなのに値全体が大きいケース。正規化またはトリミングした値を保存します。
- 小規模で機密性のない、課題/ページごとのメタデータを KVS に保存しているケース。公開範囲と 32 KB のサイズ制限に注意しつつ、代わりに Jira エンティティプロパティまたは Confluence コンテンツプロパティを検討します。
機密データや秘密情報は、エンティティ/コンテンツプロパティに移さないでください。製品の REST API を通じて閲覧される可能性があります。
ステップ 6:ログを最適化する
console.log、console.info、console.warn、console.error、および構造化ロガーの呼び出しを探します。
推奨される変更:
- 本番環境のホットパスにあるデバッグログを削除するか、出力を制御します。
- イベントのペイロード全体、API レスポンス、ストレージ値、シークレット、トークン、個人データ、大きな JSON 文字列は決してログに出力しないでください。
- 簡潔なエラーログと、意味のある状態変化のログは維持します。
- 有用な場合に限り、たとえば
process.env.DEBUG_LOGGING === 'true'のように、環境変数で制御するデバッグログを追加します。
ステップ 7:関数のメモリを調整する
manifest.yml 内の関数エントリを確認します。
- コストモデルは GB 秒です:
(memoryMiB / 1024) × durationSeconds。 - 軽量なリゾルバーのメモリを減らすのは、パフォーマンスとテストカバレッジを考慮してからにします。
- メモリを減らすことで実行時間が長くなる場合や失敗が発生する場合は、大きなペイロードを処理する関数のメモリを維持するか、増やします。
- ログ、プロファイリング、ベンチマーク結果、または現実的なローカルテストなど、根拠に基づいて判断します。
- 根拠が不足している場合は、積極的にメモリを減らして推測するのではなく、計測を推奨します。
ステップ 8:Forge Remote を慎重に評価する
Forge Remote は、適切なワークロードで Forge 関数の実行をなくせますが、その責任を外部で運用するインフラストラクチャに移します。
次のいずれかに当てはまる場合に限り、Forge Remote を推奨します:
- 長時間実行される処理が、Forge 関数の標準的な実行制限を超える。
- コストまたは実行時間の大部分を、計算負荷の高い処理が占めている。
- チームがすでにセキュアなバックエンドを運用しており、そのバックエンドがロジックを担うべきである。
- ストレージやクエリのニーズが、Forge プラットフォームの機能を実際に超えている。
トレードオフは必ず説明します:
- チームはリモートバックエンドのセキュリティ確保、スケーリング、監視、パッチ適用、運用を担う必要があります。
- リモートアーキテクチャによって、Runs on Atlassian の適格性に影響する場合があります。
- 外部インフラストラクチャには、独自のコストとコンプライアンス上の義務があります。
安全な実装パターン
コードを変更するときは:
- 動作と認可の境界を維持します。
- レビューしやすい、小規模なコミット単位の変更を優先します。
- ロジックを変更する場合は、テストを追加または更新します。
- 既存のプロジェクトのスタイルと依存関係を使用し、単純なユーティリティのために依存関係を追加しないでください。
- ユーザーから明示的に依頼されない限り、大規模な書き換えは避けます。
- 関連する範囲に絞ったテストまたはビルドコマンドで検証します。
パターンをすばやく見つける
次のパターンを検索します:
invoke(
useAction(
useEffect(
requestJira(
requestConfluence(
asApp().requestJira
asUser().requestJira
storage.get
storage.set
storage.query
console.log
console.info
scheduledTrigger
ignoreSelf
memoryMiB
Promise.all
for await
for (
検索結果は慎重に解釈してください。パターンが見つかったからといって、自動的に問題とは限りません。
出力形式
デフォルトの監査優先の依頼では、監査結果を返し、推奨する変更の実装を申し出て締めくくります:
# Forge Cost Optimization Audit
## Summary
- Overall opportunity: High | Medium | Low
- Highest-impact lever: <invocations | duration | storage | logs | memory | remote>
- Files inspected: <list>
## Prioritized Opportunities
1. [High] <title>
- Evidence: `<file:line>` and observed pattern
- Why it costs money: <cost driver>
- Recommended change: <specific fix>
- Safety notes: <authorization/data freshness/trade-offs>
## Quick Wins
- <low-risk change>
## Needs Measurement
- <changes that require usage metrics or profiling>
## Recommended Next Step
Would you like me to implement the quick wins, implement selected high-impact changes, or collect usage measurements first?
ユーザーが実装を明示的に依頼した場合は、次の形式で返します:
# Forge Cost Optimization Complete
## Changes Made
- <file>: <change and cost driver reduced>
## Validation
- <commands run and results>
## Expected Impact
- <qualitative or measured impact>
## Follow-ups
- <optional deeper optimizations or metrics to collect>
避けるべきアンチパターン
- 特権を持つ
asApp()の処理をフロントエンドに移さないでください。 - シークレット、アプリの認証情報、管理者専用データをブラウザーコードで公開しないでください。
- 機密データにエンティティプロパティを使用しないでください。
- 本番環境のインシデント診断に必要なログを削除しないでください。代わりに詳細度を下げてください。
- 許容される製品の鮮度要件を超えて、キャッシュ TTL を延長しないでください。
- Forge Remote をデフォルトとして推奨しないでください。これは単純なコスト切り替えではなく、アーキテクチャ上のトレードオフです。
- 実際の利用状況の指標がないのに、正確な削減額を断言しないでください。