AI Connect/Integration/エラーハンドリング

エラーハンドリング

VinkiusについてAIに質問

ケイパビリティの失敗を返却データとして扱い、スローされる VinkiusError のサブクラスを絞り込み、SDK がどのリクエストを再試行するかを理解し、シークレットを含まない診断情報を記録しましょう。

ケイパビリティの実行には 2 つの失敗経路があり、その両方を扱えるかどうかが、回復できるエージェントとクラッシュするエージェントの分かれ目です。

ケイパビリティの失敗を返却データとして確認する

isError: true で解決された実行は、リクエスト自体は完了し、コネクタが失敗したアクションを報告したことを意味します。これはスローではなく結果なので、エージェントループはエラーテキストをモデルに返し、モデルに回復を委ねることができます:

typescript
const result = await capability.execute(args, { idempotencyKey });

if (result.isError) {
  const text = result.content.map((part) => part.text).join('\n');
  // return the text to the model as the tool result
}

スローされるエラーを具体的なものから一般的なものへ絞り込む

ケイパビリティの結果以外のすべて(認証、HTTP、バリデーション、レート制限、クォータ、タイムアウト、ネットワーク、設定)はスローされます:

typescript
import {
  VinkiusError,
  AuthError,
  RateLimitError,
  QuotaError,
  ConnectorNotConnectedError,
} from '@vinkius/connect';

try {
  const result = await capability.execute(args, { idempotencyKey });
  if (result.isError) {
    // connector-level failure: feed result.content back to the model
  }
} catch (error) {
  if (error instanceof ConnectorNotConnectedError) {
    // send the user through the connector setup flow
  } else if (error instanceof RateLimitError) {
    // back off using the response's retry information
  } else if (error instanceof QuotaError || error instanceof OverageError) {
    // plan limit reached: surface an upgrade path
  } else if (error instanceof AuthError) {
    // application key rejected: check rotation and environment
  } else if (error instanceof VinkiusError) {
    // any other API error
  } else {
    // hooks can throw their own errors; keep an unknown branch
  }
}

すべての VinkiusError には codestatusrequestIddetails があります。ローカルエラーとトランスポートエラーはステータス 0 を使用します。requestId はサーバーが提供した場合にのみ存在します。

エラーの分類

エラー意味
ConfigErrorローカルの設定問題。リクエストの前にスローされる
AuthErrorHTTP 401 または 403: アプリケーションキーが拒否された
ValidationErrorリクエストペイロードがサーバー側のバリデーションに失敗した
NotFoundError指定されたユーザー、接続、またはリソースが存在しない
RateLimitErrorHTTP 429: リクエストが多すぎる
QuotaErrorプランに含まれるクォータを使い切った
OverageError超過保護がリクエストを拒否した
ConnectorNotConnectedError存在しない接続を必要とする操作である
ConnectionError接続が操作を許可する状態にない
NotImplementedErrorエンドポイントは存在するが、この環境では利用できない
ProtocolErrorレスポンスが期待されるプロトコルに違反した
VinkiusErrorその他の非成功レスポンス(details を保持する)

SDK がどのリクエストを繰り返すかを把握する

デフォルトの上限は初回試行に再試行 2 回を加えたものです。ネットワークエラー、タイムアウト、HTTP 429502503504 は一時的と見なされますが、繰り返し可能なリクエストのみが再試行されます。デフォルトでは GETPUTDELETE。ユーザー作成と接続作成は契約が upsert/get-or-create であるため対象。ケイパビリティの実行は idempotencyKey が指定された場合のみです。

アプリケーションで実行キーを生成し検証する

トランスポートは undefined のべき等キーを「再試行を有効にしない」として扱い、truthy な文字列に対してのみ Idempotency-Key ヘッダーを送信します。したがって空文字列は、ヘッダーを送信せずに再試行を有効にします。キーは論理操作から導出し、空でないことを検証し、同じ操作を再試行するときにのみ再利用してください:

typescript
const key = `create-issue:${operationId}`;
if (!key.trim()) throw new Error('idempotency key required');

実行オプションについてアダプターのディスパッチに頼らない

アダプターのディスパッチヘルパーやファクトリにバインドされた関数は、ExecuteOptions なしで capability.execute(args) を呼び出します。キーもなく、呼び出し元のシグナルもなく、トランスポート試行は 1 回だけです。アダプターのディスパッチャーに渡された不明な名前は VinkiusError ではなくプレーンな Error をスローします。キャンセルやべき等性が必要な場合は、Capability を解決して execute() を直接呼び出してください。

シークレットを記録せずに診断情報を記録する

typescript
try {
  // ...
} catch (error) {
  if (error instanceof VinkiusError) {
    logger.error({ code: error.code, status: error.status, requestId: error.requestId });
  }
  throw error;
}

オブザーバビリティフックはマスキングされたビューを受け取ります(認証ヘッダーと既知のシークレット項目名は取り除かれます)が、送信された認証情報の値は、ご自身のログでもシークレットとして扱う必要があります。フックのコールバックは元のエラーをスローすることがあり、再試行バックオフ中の中断はシグナルの理由をそのまま伝播させることがあります。スローされる値がすべて VinkiusError だと決めつけず、最後に unknown の分岐を用意してください。

次のステップ