Agent と自動化
AI コーディング Agent、バックエンドワーカー、メディアパイプライン向けの本番運用ガイド。
コピー可能な参照クライアント
モデル検索、タスク作成、失敗したタスクの再試行、状態取得、全終端状態、上限付き待機、冪等性、エラー処理を含む依存なしの例です。受理済みのタスクは取り消せません。
文書内の例であり、公開済み npm/PyPI パッケージではありません。10 分はローカル上限で、SLA ではありません。
AI コーディング Agent や自動処理から SpicyAPI を組み込む場合の実践ガイドです。API 仕様の確認、入力検証、一度だけの作成、安全な待機、完了確認、期限前の成果物保存までを、上限があり再開可能な処理として設計します。
API キーはサーバーだけに置く
SPICY_API_KEY をブラウザー JavaScript、モバイルアプリ、公開プロンプト、リポジトリ、Agent の会話ログに含めないでください。UI は自社バックエンドを呼び、バックエンドが SpicyAPI を呼びます。Agent には値ではなく SPICY_API_KEY というシークレット参照を渡します。
機械可読のディスカバリー
必要な情報を含む最小のファイルから読み始めると、コンテキストを節約し、古い情報の混入も抑えられます。
| エンドポイント | 用途 |
|---|---|
/agent.md | 短い統合ポリシーと安全な標準フロー |
/llms.txt | 製品・モデル・ドキュメントの公開索引 |
/llms-full.txt | 短い索引では足りない場合の拡張コーパス |
/api/agent | ツール向けの構造化 JSON マニフェスト |
/openapi.yaml | リクエストとレスポンスの正式な仕様 |
OpenAPI と最新のモデルカタログを実装の基準にします。広告用の例は Schema ではありません。コード生成前や検証エラー発生時には、キャッシュ済みの発見ファイルを更新してください。
公式 npm インテグレーション
SDK、CLI、MCP、汎用 Agent Skill は、それぞれ独立した MIT ライセンスの npm パッケージです。必要なものだけをインストールしてください。@spicyapi/skill は移植可能な Agent Skills 形式で、Codex 専用ではありません。
npm install @spicyapi/sdk
npx --yes --package=@spicyapi/cli spicyapi --help
npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx --yes --package=@spicyapi/skill spicyapi-skill installSkill の既定のインストール先は ~/.agents/skills/spicyapi です。別の Skills ディレクトリを使う Agent では、--target /正確な/パス/spicyapi を指定します。
コーディング Agent から使う
MCP サーバーはローカルで stdio 実行され、モデル一覧・見積もり・タスク作成・結果取得を Agent に渡します。課金される操作は必ず確認で止まり、Agent は飛ばせません。以下は各クライアントが現在推奨している形式です。設定の場所と書式はクライアント側が定めており、バージョンで変わるため、最終的には各社の公式ドキュメントを参照してください。
Claude Code
claude mcp add spicyapi \
-e SPICY_API_KEY=$SPICY_API_KEY \
-- npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx --yes --package=@spicyapi/skill spicyapi-skill install \
--target ~/.claude/skills/spicyapiCodex CLI
codex mcp add spicyapi \
--env SPICY_API_KEY=$SPICY_API_KEY \
-- npx --yes --package=@spicyapi/mcp spicyapi-mcp
npx --yes --package=@spicyapi/skill spicyapi-skill install \
--target ~/.codex/skills/spicyapiどちらのコマンドも、現在の shell の SPICY_API_KEY をクライアントのローカル設定へ書き込みます。キーを export 済みのターミナルで実行してください。キーは手元に残るだけで、コミットしてはいけません。
Cursor・Windsurf・Gemini CLI
設定ファイルはそれぞれ ~/.cursor/mcp.json、~/.codeium/windsurf/mcp_config.json、~/.gemini/settings.json で、書式は共通です。
{
"mcpServers": {
"spicyapi": {
"command": "npx",
"args": ["--yes", "--package=@spicyapi/mcp", "spicyapi-mcp"],
"env": { "SPICY_API_KEY": "YOUR_SERVER_SIDE_KEY" }
}
}
}いずれもリポジトリ外のユーザー設定ファイルです。YOUR_SERVER_SIDE_KEY を実際のキーに置き換えたあと、この内容をコミット対象のファイルへコピーしないでください。
VS Code
.vscode/mcp.json はリポジトリと一緒にコミットされるため、キーを書いてはいけません。初回起動時に VS Code へ入力を求めさせ、自身のシークレットストレージに保管します。
{
"inputs": [
{
"id": "spicyapi-key",
"type": "promptString",
"description": "SpicyAPI key",
"password": true
}
],
"servers": {
"spicyapi": {
"type": "stdio",
"command": "npx",
"args": ["--yes", "--package=@spicyapi/mcp", "spicyapi-mcp"],
"env": { "SPICY_API_KEY": "${input:spicyapi-key}" }
}
}
}つないだあと
実際の作業をそのまま頼めます。
SpicyAPI で呼び出せる画像モデルを一覧し、安いものを選んで夜景のポートレートを 1 枚生成し、完了したら結果のリンクを教えてください。
Agent は一覧を読み、そのモデルのスキーマを取得し、正確な見積もりを得たうえで、課金の前に必ず確認を求めます。Skill を入れておくと、同じ冪等キーを使い続け、繰り返しポーリングせずに準備済みの結果 URL を読むようになります。
本番ワークフロー
- モデルを解決します。 目的のモダリティに合うエンドポイントを選び、現在の入力 Schema で検証します。未知のフィールドを推測したり黙って削除したりしません。
- 一度だけ作成します。 論理的な生成単位ごとに安定した
Idempotency-Keyを作り、最初の送信前に保存します。再試行でも同じ値を使います。詳しくは冪等性を参照してください。 taskIdを即時保存します。 これはステータス照会、Webhook 照合、サポート、課金調査に共通する永続 ID です。同じ ID が返ってもローカルレコードを増やしません。- 上限付きで待ちます。 署名付き Webhook を優先します。ポーリングは約 2 秒から開始し 1.5 倍ずつ増やし、15 秒で上限、さらに全体の締切を設けます。
succeeded、failed、canceled、expiredは終端状態です。 - コールバックを検証します。
X-Webhook-Timestamp、生のリクエスト本文のダイジェスト、HMAC を検証し、配信request_idで重複排除します。すぐ 2xx を返し、後続処理はキューに渡します。詳細は Webhooks にあります。 - 成果物を退避します。 オブジェクトキーを署名付き URL に交換し、必要なファイルを自社ストレージへコピーします。URL は現在 20 分で失効します。保持期間についてはメディアとデータ保持を確認してください。
POST /api/v1/jobs/createTask
Authorization: Bearer $SPICY_API_KEY
Content-Type: application/json
Idempotency-Key: project-42-scene-07-v1const deadline = Date.now() + 10 * 60_000;
let delay = 2_000;
while (Date.now() < deadline) {
await sleep(delay);
const task = await recordInfo(taskId);
if (['succeeded', 'failed', 'canceled', 'expired'].includes(task.state)) return task;
delay = Math.min(Math.round(delay * 1.5), 15_000);
}
throw new Error(`task ${taskId} exceeded the polling deadline`);ローカルのタイムアウトは生成失敗の証明ではありません。taskId を保持し、後で照合します。また HTTP 200 だけで成功と判断せず、必ず data.state を読みます。
最小限の永続レコード
再起動後に安全に再開できるよう、localRequestId、idempotencyKey、taskId、model、state、lastCheckedAt、webhookDeliveryId、outputKeys を保存します。期限付きダウンロード URL を資産 ID として保存しないでください。
Mock と受け入れテスト
タスク、Webhooks、エラーのレスポンス形状を使ってローカル契約 Mock を作ります。最低限、次を試験します。
- queued → running → succeeded と、
code: 200でもdata.state: "failed"のケース - 重複作成が同じ
taskIdを返すこと - 正しい署名、不正署名、同じ Webhook の再配信
429、503、通信タイムアウト、ポーリング期限超過- 期限切れダウンロード URL の再発行
Mock は制御フローだけを検証します。公開前に、本番と同じモデルと入力形式で小さな実タスクも実行してください。
リリース判定チェックリスト
- シークレットはサーバー側の保管庫だけにあり、ログではマスクされます。
- 現在のモデル Schema を取得し、フィールドを推測していません。
- 一つの論理リクエストに一つの永続化済み
Idempotency-Keyがあります。 - 後続処理より先に
taskIdを保存し、再起動後も復元できます。 - ポーリングにバックオフ、最大間隔、全体締切があります。
- Webhook は時刻、生本文、HMAC を検証し、配信 ID で重複排除します。
- 成否は HTTP ステータスではなく
data.stateで判断します。 - URL・保持期限より前に出力をコピーし、オブジェクトキーを永続参照にします。
-
request_id、taskId、モデル、試行回数を記録しますが、シークレットと完全なプロンプトは記録しません。
Agent の完了報告には、選択したモデル、Schema の取得時刻、冪等化方針、ポーリング締切、Webhook 検証方法、完了済みチェックリストを含めさせてください。

