building-nango-functions-remotely について
Nango プロジェクトをチェックアウトせずに、Nango のアクションや同期処理を開発・変更するためのスキルです。チェックポイントと削除戦略を重視し、Nango API 経由で関数のコンパイル、ドライラン、デプロイを行います。
主な機能
- 01関数のリモートコンパイル、ドライラン、デプロイ
- 02Nango アクションと同期処理の作成
- 03チェックポイントと削除処理の設計
- 04入力、スキーマ、ランタイム制約の遵守
活用シーン
- 01Nango インテグレーション向けの単発アクション実装
- 02再開可能なページングまたは差分同期の設計
- 03API 経由で単一ファイル関数を検証・デプロイ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nangohq/ skills --skill building-nango-functions-remotelyインストール後、Claude Code で/building-nango-functions-remotelyを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/actions.mdapi.mdsyncs.md詳細
Nango 関数をリモートで構築する
チェックアウト済みの Nango プロジェクトがなくても、単一ファイルの TypeScript 関数を Nango の /functions/compile、/functions/dryruns、/functions/deployments API に送信して、Nango のアクションや同期を構築できます。
実装範囲
- Nango 関数の実装を構築または変更する
- Nango で
createAction()を使用してアクションを構築する - Nango で
createSync()を使用して同期を構築する - コンパイル、ドライラン、テスト、デプロイの手順には、アクティブなワークフロースキルを使用する
同期戦略の確認(コード作成前に必須)
タスクが同期の場合、コード作成前に references/syncs.md を読み、まず次のいずれかの方針を明示してください。
- チェックポイント計画:
- 変更ソース(
updated_at、modified_since、変更レコードのエンドポイント、カーソル、ページトークン、オフセット/ページ、since_id、または Webhook) - チェックポイントのスキーマ
- チェックポイントがプロバイダーへのリクエストまたは再開状態をどのように変更するか
- リクエストが引き続きデータセット全体を走査するのか、変更された行のみを返すのか
- 削除戦略
- 変更ソース(
- 全件更新が必要な理由:
- ドキュメントまたはサンプルペイロードに記載された、プロバイダーの具体的な制約
- その制約によりチェックポイントを使用できない理由
無効な同期実装:
- より簡単だからという理由で全件更新にする
getCheckpoint()を使わずにsaveCheckpoint()を呼び出す- チェックポイントを読み取る、または保存するだけで、リクエストパラメーターやページネーション状態に使用しない
- 新しい同期で
syncType: 'incremental'またはnango.lastSyncDateを使用する checkpointスキーマを指定しない全件更新、または各ページの後に保存しない全件更新。実行時間の上限を超えるたびに、実行がページ 1 から再開されますsaveCheckpoint()の実行を残りのページがある場合のみに制限する(例:if (nextCursor) { await nango.saveCheckpoint(...) })。最後のページを含む、成功したすべてのページでsaveCheckpoint()を呼び出す必要があります。そうしないと、1 ページのみの同期がチェックポイント行のない状態でclearCheckpoint()に到達し、checkpoint_conflictで失敗します。clearCheckpoint()より前にtrackDeletesEnd()を呼び出す、またはclearCheckpoint()を先に呼び出さずにtrackDeletesEnd()を呼び出す- 変更のみを対象とするチェックポイント(
modified_after、updated_after、変更レコードのエンドポイント)でtrackDeletesStart()/trackDeletesEnd()を使用する。これらのリクエストでは変更されていない行が省かれるため、trackDeletesEnd()がそれらを誤って削除します。 - 削除されたレコードのイベントをすでに明示的に処理している増分同期で、
trackDeletesStart()/trackDeletesEnd()を使用する
方針を選択する
アクション:
createAction()で構築する、ユーザーが実行する単発のリクエスト- コード作成前に
references/actions.mdを読む
同期:
createSync()で構築する、スケジュールまたは Webhook によるキャッシュ更新- まず同期戦略の確認を完了する
- コード作成前に
references/syncs.mdを読む
必要な入力(不足している場合はユーザーに確認)
常に必要:
- インテグレーション ID(プロバイダー名)
- スクリプト/関数名(ケバブケース)
- API リファレンス URL またはサンプルレスポンス
- アクティブなワークフローで関数の検証またはドライランを行う場合は、接続 ID
アクション固有:
- ユースケースの概要
- 入力パラメーター
- 出力フィールド
- 必要に応じてメタデータ JSON
- アクティブなワークフローでアクションの検証またはドライランを行う場合は、テスト入力 JSON(入力がないアクションでは
{}を使用)
同期固有:
- モデル名(単数形、パスカルケース)
- 頻度(1 時間ごと、5 分ごとなど)
- チェックポイントのスキーマ(タイムスタンプ、カーソル、ページトークン、オフセット/ページ、
since_id、または複合型) - チェックポイントがプロバイダーへのリクエストまたは再開状態をどのように変更するか
- 削除戦略(削除されたレコードのエンドポイント/Webhook、または全件更新が必要な理由)
- 全件更新を提案する場合は、チェックポイントを妨げるプロバイダーの具体的な制約(ドキュメント/サンプルレスポンスに記載)
- 必要に応じてメタデータ JSON(team_id、workspace_id)
必須の外部情報が不足している場合は、リポジトリとプロバイダーのドキュメントを確認してから、具体的な質問をしてください。同期では、プロバイダーが対応している限り、チェックポイントと削除戦略を選択してください。実行可能なチェックポイント戦略が見つからない場合は、全件更新を実装する前に、その理由を具体的に説明してください。
必ず守るルール
共有プラットフォームの制約
- Nango 関数では
createAction()/createSync()を使用します。 - 任意のパッケージは追加できません。選択したワークフローでサポートされている場合に限り相対インポートを使用してください。組み込みで使用できるものには
zod、crypto/node:crypto、url/node:urlがあります。 - 関数コードの外で接続の検索、認証情報の取得、プロキシ呼び出しを行う場合は、Nango HTTP API を使用してください。CLI のトークンや接続に関するコマンドを作り出さないでください。
- 各プロバイダー呼び出しの上に、API ドキュメントへのリンクコメントを追加してください。
- アクションの出力は 2MB を超えられません。
- ファイルのアップロードとダウンロードはアクションとして実装できません(サンドボックス化されたランタイムでは
fsとaxiosが使えず、出力上限は 2 MB です)。代わりに{integration}/proxy/内で@nangohq/nodeを使用したプロキシスクリプトを使ってください。詳しくはreferences/actions.mdを参照してください。 - HTTP の再試行回数のデフォルトは
0です。retriesは意図的に設定してください。通常の上限は3としてください。同期処理でのプロバイダー呼び出しでは、安全かつ必要であることがドキュメントで証明されない限り、3を超える値は実質的に禁止です。API が冪等性をサポートしていない場合、冪等でない書き込み処理では再試行を避けてください。 - 非推奨の関数定義ルーティングフィールドは設定しないでください。アクションの
endpointと同期のendpointsが該当します。SDK/API からアクション名でアクションを実行し、レコード API から同期レコードを取得してください。
同期のルール
- 同期レコードには安定した文字列の
idが必要です。 - 新しい同期では
checkpointスキーマを定義し、最初にnango.getCheckpoint()を呼び出し、各ページまたはバッチの処理後にnango.saveCheckpoint()を呼び出してください。 - チェックポイントが有効なのは、リクエストまたは再開状態(
since、updated_after、cursor、page_token、offset、page、since_idなど)に反映される場合に限られます。チェックポイントを保存しても使用しない場合は、増分同期ではありません。 - 新しい同期では
syncType: 'incremental'やnango.lastSyncDateを使用しないでください。 - デフォルトでは
nango.paginate(...)+nango.batchSave(...)を使用してください。cursor、link、offsetによるページネーションが使える場合は、while (true)による手動ループを避けてください。 - プロバイダーから削除、削除済みを示すレコード、または削除ウェブフックが返される場合は、
batchDelete()を優先してください。 - プロバイダーから変更、削除、再開状態を取得できない場合、またはデータセットがごく小さい場合に限り、フルリフレッシュを使用してください。
- フルリフレッシュを行う場合は、プロバイダーの制約を示すドキュメントまたはペイロード内の該当箇所を正確に引用してください。「その方が簡単だから」では不十分です。
- フルリフレッシュの同期でも、増分同期と同様に、ページネーションの進捗を保持するための
checkpointスキーマ(ページ、カーソル、オフセット)を設定する必要があります。Nango の同期は実行時間に制限のある実行ウィンドウ内で動作します。チェックポイントのないフルリフレッシュは、ウィンドウを超えるたびに毎回 1 ページ目から再開されます。同じ序盤のページを再取得してコンピューティングリソースを浪費し、残りのページに到達できません。 deleteRecordsFromPreviousExecutions()は非推奨です。フルリフレッシュでは、実行のたびにtrackDeletesStart()を呼び出してください(安全で冪等です。すでに開始済みのウィンドウの開始位置は上書きされません)。その後、各ページの後にsaveCheckpoint()を呼び出し、最後のページの後にclearCheckpoint()を呼び出してから、trackDeletesEnd()を呼び出してください。- フルリフレッシュでは、最後のページを含む成功したすべてのページの後に
saveCheckpoint()を呼び出してから、clearCheckpoint()を呼び出してください。「残りのページがある」という条件で保存を制御してはいけません。個別の実行経路でチェックポイントがまったく作成されない場合(たとえば、処理対象のページがない場合)は、その経路でclearCheckpoint()を呼び出さないでください。実行時にcheckpoint_conflictが発生します。この例外を、最終ページの保存の代わりにしてはいけません。 trackDeletesStart()/trackDeletesEnd()と、変更分のみを対象とするチェックポイント(modified_after、updated_after、変更されたレコードを返すエンドポイントなど)を組み合わせてはいけません。変更のない行が対象から漏れるため、trackDeletesEnd()によってそれらの行が削除されます。- チェックポイントを使うフルリフレッシュも、フルリフレッシュであることに変わりはありません。チェックポイントを完了してクリアする実行でのみ
trackDeletesEnd()を呼び出してください。 - 同期にメタデータ(例:
team_id、workspace_id、guild_id)が必要な場合は、autoStart: falseを設定してください。呼び出し側がメタデータを設定するまで同期は実行できないため、自動的に開始すると失敗します。
規約
- フィールドの大文字・小文字の形式は外部 API に合わせます。パススルーフィールドはプロバイダーの形式を維持し、パススルーではないフィールドには、その API で主流の形式を使用します。
- 明示的なフィールド名を優先します。
- ID、タイムスタンプ、列挙型、URL には
.describe()の例を追加します。 anyは避け、インラインのマッピング型を使用します。- リストアクションには
cursorと、その API で主流の形式(next_cursor、nextCursorなど)による次のカーソルのフィールドを含めます。 - カスタム検証やログ記録が必要な場合にのみ
nango.zodValidateInput()を使用します。それ以外の場合は、スキーマと選択した検証ワークフローに依拠します。
スキーマのセマンティクス
- 必須でない入力は、デフォルトで
.optional()にします。 .nullable()はnullに意味がある場合(通常は更新時に値をクリアする場合)にのみ使用します。呼び出し元がフィールドを省略することもできる場合は、.optional()も追加します。- 生のプロバイダースキーマはプロバイダーに合わせます。省略されるフィールドには
.optional()、明示的なnullには.nullable()を使用します。.nullish()は、プロバイダーが実際に両方を許容する場合にのみ使用します。 - 最終的なアクション出力と正規化された同期モデルでは
.optional()を優先し、nullに意味がない限り、上流のnullは省略に正規化します。 - 生成されるスキーマでは、必須でない入力と正規化された出力に
.optional()をデフォルトで使用します。上流の契約によって正当化される場合にのみ、許容範囲を広げます。 z.union([z.null(), T])やz.union([T, z.null()])より.nullable()を優先します。- 出力スキーマが許容する場合にのみ
nullを返します。 z.object()はデフォルトで未知のキーを除去します。プロバイダーのパススルーにはz.object({}).passthrough()、z.record(z.unknown())、または最小限の絞り込みを加えたz.unknown()を使用します。
フィールド名と大文字・小文字の形式に関するルール
- API で主流の形式に従い、明示的なサフィックスを使用します。ID(
user_id、userId)、名前(channel_name、channelName)、メールアドレス(user_email、userEmail)、URL(callback_url、callbackUrl)、タイムスタンプ(created_at、createdAt)などです。
マッピング例(API が別のパラメーター名を想定している場合):
const InputSchema = z.object({
userId: z.string()
});
const config: ProxyConfiguration = {
endpoint: 'users.info',
params: {
user: input.userId
},
retries: 3
};
API が snake_case の場合は、代わりに user_id を使用します。目的は API 全体で一貫性を保つことです。
参考資料
- アクションのパターン、CRUD の例、メタデータの使用方法、ActionError の例:
references/actions.md - 同期のパターン、具体的なチェックポイントの例、削除戦略、完全な再取得のフォールバック:
references/syncs.md
Nango の便利なドキュメント(クイックリンク)
- 関数ランタイム SDK リファレンス:https://nango.dev/docs/reference/functions
- アクションの実装:https://nango.dev/docs/implementation-guides/use-cases/actions/implement-an-action
- 同期の実装:https://nango.dev/docs/implementation-guides/use-cases/syncs/implement-a-sync
- チェックポイント:https://nango.dev/docs/implementation-guides/use-cases/syncs/checkpoints
- 削除の検出(完全と増分):https://nango.dev/docs/implementation-guides/use-cases/syncs/deletion-detection
- インテグレーションのテスト(dryrun、
--save、Vitest):https://nango.dev/docs/implementation-guides/platform/functions/testing - Nango HTTP API リファレンス:https://nango.dev/docs/reference/api
API ドキュメントが表示されない場合
Web 取得でドキュメントが不完全な場合(JavaScript によってレンダリングされる場合):
- ユーザーにサンプルレスポンスを依頼します
- ワークスペースに既存の Nango アクションや同期がある場合は、パターンとして使用します
- 成功するまで、スキル固有の検証または dryrun ワークフローを使用します
前提条件(コードを書く前に実施)
- Nango プロジェクトがチェックアウトされている必要はありません。
NANGO_SERVER_URLは、環境変数、.envファイル、フォールバックのhttps://api.nango.devの順に解決します。- 関数エンドポイントを呼び出す前に
NANGO_SECRET_KEYを解決します。 - そのシークレットキーに紐づく環境を使用します。
- キーが必要なスコープを持っていることを確認します。コンパイルには
environment:functions:compile、dryrun とポーリングにはenvironment:functions:dryrun、デプロイにはenvironment:deployが必要です。 - リモートエンドポイントが複数ファイルのペイロードを受け付ける直接的な根拠がない限り、関数は 1 つの TypeScript ファイルに自己完結させます。
- 現在のプロジェクト/ディレクトリ内にファイルを作成または変更してはいけません。ファイルを作成する必要がある場合は、一時フォルダーを使用します。
ワークフロー(必須)
- これがアクションか同期処理かを判断します。
- 該当するリファレンスファイル(
references/actions.mdまたはreferences/syncs.md)を読みます。 - 同期処理の場合は、プロバイダーのドキュメントまたはペイロードを調べてチェックポイントと削除を確認し、エンドポイントが全データを返すのか変更された行を返すのかを判断して、Sync Strategy Gate を完了します。
- 必要な入力と外部値を収集します。対象環境の
NANGO_SECRET_KEYと、ドライランに必要なメタデータも含めます。 - 環境変数の
NANGO_SERVER_URL、次に.env、最後にhttps://api.nango.devの順でホストを解決します。 createAction()またはcreateSync()を使用し、自己完結した TypeScript ファイル 1 つとして関数を作成または更新します。POST {host}/functions/compileを実行し、コンパイルに成功するまで修正します。- 対象のインテグレーション、接続、関数タイプ、コード、および必要な
input、metadata、checkpointを指定して、POST {host}/functions/dryrunsでドライランを開始します。 - ドライランが
successまたはfailedになるまで、GET {host}/functions/dryruns/{id}をポーリングします。 - コンパイルまたはドライランを成功させられない場合は停止し、不足している外部状態、入力、または API コントラクトとの不一致を報告します。
- 要求された場合にのみ、
POST {host}/functions/deploymentsでデプロイを開始します。 - デプロイが
successまたはfailedになるまで、GET {host}/functions/deployments/{id}をポーリングします。
リモート API ワークフロー(必須)
リモート呼び出しを行う前に、references/api.md を読みます。
必須の順序:
- 最初に
POST /functions/compileでコンパイルします。 - 次に
POST /functions/dryrunsでドライランを開始します。 GET /functions/dryruns/{id}でドライランのステータスを終端状態になるまでポーリングします。- 要求された場合にのみ、最後に
POST /functions/deploymentsでデプロイを開始します。 GET /functions/deployments/{id}でデプロイのステータスを終端状態になるまでポーリングします。
ルール:
- これらのエンドポイントは相対パスです。必ず選択した
NANGO_SERVER_URLを基準に解決してください。 Authorization: Bearer <NANGO_SECRET_KEY>とContent-Type: application/jsonを送信してください。- 必要な API キーのスコープは、コンパイルが
environment:functions:compile、ドライランの作成とステータス確認がenvironment:functions:dryrun、デプロイの作成とステータス確認がenvironment:deployです。 - API ドキュメントまたは既存の呼び出し元でサポートが確認できない限り、クエリパラメーターを送信しないでください。
- サーバーの検証エラーを使ってペイロードを修正してください。API がリクエストを拒否した場合、ドキュメントにないフィールドを作り出さないでください。
- コンパイルでは
{ "code": "..." }のみを送信します。 - ドライランでは
integration_id、function_type、code、connection_idを送信します。 - デプロイでは
type: "function"、integration_id、function_name、function_type、codeを送信します。versionまたはallow_destructiveを追加するのは、明示的に必要な場合だけです。 - アクションの場合、必要な場合にのみ
inputとmetadataをドライランに含めます。 - 同期処理の場合、再開された実行をシミュレートする必要があれば、
metadataとcheckpointをドライランに含めます。新しい同期処理の設計にlast_sync_dateを導入しないでください。 - ドライランは非同期です。
POST /functions/dryrunsはidを返します。status、output、result、またはerrorを確認するには、GET /functions/dryruns/{id}をポーリングしてください。サンドボックス内部のため、/functions/dryruns/{id}/resultは呼び出さないでください。 - デプロイは非同期です。
POST /functions/deploymentsはidを返します。status、deployed、deployed_functions、output、またはerrorを確認するには、GET /functions/deployments/{id}をポーリングしてください。サンドボックス内部のため、/functions/deployments/{id}/resultは呼び出さないでください。 waitingとrunningは終端状態ではありません。ポーリングを停止するのはsuccessまたはfailedの場合だけです。- リモートドライランでは CLI の
--validateや--saveは公開されません。実行前にコンパイルされ、ステータスエンドポイントを通じて実行結果が返されますが、ローカルのモックは記録されません。
最終チェックリスト
アクション:
- アクションのパターンには
references/actions.mdを使用しました - スキーマと型が明確で、関数は1つのファイル内で完結しています
- 必要な場合は
createAction()に入力、出力、スコープが含まれており、非推奨のendpointは省略されています - フィールドでは、パススルーの大文字・小文字表記または API の多数派の表記を使用しています
- プロバイダー呼び出しに API ドキュメントへのリンクコメントが含まれており、リトライは意図的に設定されています
- 想定されるエラーには
nango.ActionErrorを使用しています -
NANGO_SERVER_URL、.env、またはhttps://api.nango.devからホストを解決しました -
POST /functions/compileでコンパイルが成功します -
POST /functions/dryrunsでドライランを開始しました -
GET /functions/dryruns/{id}でドライランのステータスがsuccessになり、期待されるアクション出力が得られました - 要求された場合は
POST /functions/deploymentsでデプロイを開始しました - 要求された場合は
GET /functions/deployments/{id}でデプロイのステータスがsuccessになりました
同期:
- 同期のパターンには
references/syncs.mdを使用しました - モデルマップを定義し、IDは安定した文字列で、正規化モデルでは
nullが重要な場合を除き.optional()を優先しています - まず差分同期を選択し、ドキュメントまたはペイロードに基づいて全件更新が明確に正当化される場合を除き、チェックポイントのスキーマを用意しています
- 冒頭で
nango.getCheckpoint()を読み取り、各ページまたはバッチの後にnango.saveCheckpoint()を実行しています - チェックポイントデータがプロバイダーへのリクエストまたは再開状態(
since、updated_after、cursor、page_token、offset、page、since_idなど)に反映されます - 変更分のみを対象とするチェックポイント同期(
modified_after、updated_after、変更レコード用エンドポイント)では、trackDeletesStart()/trackDeletesEnd()を使用していません - チェックポイントを使用しなかった場合、実行可能なチェックポイント戦略が存在しない理由を回答で正確に説明しています
- 全件更新同期には
checkpointスキーマがあり、ページネーションをそこから再開し、各ページの後にsaveCheckpoint()を呼び出すため、実行時間の上限に達しても1ページ目から再開しません - 全件更新の
trackDeletesEnd()はclearCheckpoint()の後、最終ページを完了する実行でのみ実行されます - プロバイダー API 呼び出しでは
retries: 3を使用しています。文書化された例外がない限り、同期のリトライ値は3を超えません - リモート API が複数ファイルのサポートを明確に示している場合を除き、関数は1つのファイル内で完結しています
-
NANGO_SERVER_URL、.env、またはhttps://api.nango.devからホストを解決しました -
POST /functions/compileでコンパイルが成功します -
POST /functions/dryrunsでドライランを開始しました -
GET /functions/dryruns/{id}でドライランのステータスがsuccessになり、期待される変更セットが返されます - 要求された場合は
POST /functions/deploymentsでデプロイを開始しました - 要求された場合は
GET /functions/deployments/{id}でデプロイのステータスがsuccessになりました