Documentation Index
Fetch the complete documentation index at: https://adcp-docs-ja.pier1.co.jp/llms.txt
Use this file to discover all available pages before exploring further.
AdCP のオペレーションは秒から日までかかることがあります。本ガイドでは各タイプの扱い方と非同期前提の設計を説明します。
オペレーションの種類
AdCP のオペレーションは次の 3 種に分類されます:
1. 同期オペレーション
completed または failed で即時応答:
| Operation | Description |
|---|
get_adcp_capabilities | Agent capability discovery |
list_creative_formats | Format catalog |
外部システムを必要としない高速な処理です。
2. 対話的オペレーション
処理継続前に input-required を返す場合があります:
| Operation | Description |
|---|
get_products | When brief is vague or needs clarification |
create_media_buy | When approval is required |
進行にはユーザー入力が必要です。
3. 非同期オペレーション
working または submitted を返し、ポーリング/ストリーミングが必要:
| Operation | Description |
|---|
create_media_buy | Creates campaigns with external systems |
sync_creatives | Uploads and processes creative assets |
get_products | Complex inventory searches |
activate_signal | Activates audience segments |
外部システム連携や人の承認を伴う処理です。
タイムアウト設定
オペレーション種別に応じて妥当なタイムアウトを設定します:
const TIMEOUTS = {
sync: 30_000, // 30 seconds for immediate operations
interactive: 300_000, // 5 minutes for human input
working: 120_000, // 2 minutes for working tasks
submitted: 86_400_000 // 24 hours for submitted tasks
};
function getTimeout(status, operationType) {
// submitted tasks may take hours or days
if (status === 'submitted') {
return TIMEOUTS.submitted;
}
// working tasks should complete within 2 minutes
if (status === 'working') {
return TIMEOUTS.working;
}
// interactive operations wait for human input
if (status === 'input-required') {
return TIMEOUTS.interactive;
}
return TIMEOUTS.sync;
}
Human-in-the-Loop ワークフロー
設計原則
- デフォルトは任意 - 承認は実装ごとに設定
- 明確なメッセージ - 何を承認するかを明示
- 適切なタイムアウト - 人の入力で無期限にブロックしません
- 監査証跡 - 誰が何をいつ承認したか記録
承認パターン
async function handleApprovalWorkflow(response) {
if (response.status === 'input-required' && needsApproval(response)) {
// Show approval UI with context
const approval = await showApprovalUI({
title: "Campaign Approval Required",
message: response.message,
details: response, // Task fields are at top level
approver: getCurrentUser()
});
// Send approval decision
const decision = {
approved: approval.approved,
notes: approval.notes,
approver_id: approval.approver_id,
timestamp: new Date().toISOString()
};
return sendFollowUp(response.context_id, decision);
}
}
よくある承認トリガー
- 予算閾値: $100K 超のキャンペーン
- 新規広告主: 初回の購入者
- センシティブコンテンツ: 特定業界や話題
- 手動インベントリ: パブリッシャー承認が必要なプレミアム枠
進捗トラッキング
進捗更新
長時間処理では進捗情報が提供されることがあります:
{
"status": "working",
"message": "Processing creative assets...",
"task_id": "task-456",
"progress": 45,
"step": "transcoding_video",
"steps_completed": ["upload", "validation"],
"steps_remaining": ["transcoding_video", "thumbnail_generation", "cdn_distribution"]
}
進捗表示
function displayProgress(response) {
if (response.progress !== undefined) {
updateProgressBar(response.progress);
}
if (response.step) {
updateStatusText(`Step: ${response.step}`);
}
if (response.steps_completed) {
updateStepsList(response.steps_completed, response.steps_remaining);
}
// Always show the message
updateMessage(response.message);
}
プロトコル非依存パターン
これらのパターンは MCP/A2A どちらでも機能します。
確認フローを含む商品探索
async function discoverProducts(brief) {
let response = await adcp.send({
task: 'get_products',
brief: brief
});
// 確認ループを処理
while (response.status === 'input-required') {
const moreInfo = await promptUser(response.message);
response = await adcp.send({
context_id: response.context_id,
additional_info: moreInfo
});
}
if (response.status === 'completed') {
return response.products; // Task fields are at top level
} else if (response.status === 'failed') {
throw new Error(response.message);
}
}
承認フローを含むキャンペーン作成
async function createCampaign(packages, budget) {
let response = await adcp.send({
task: 'create_media_buy',
packages: packages,
total_budget: budget
});
// Handle approval if needed
if (response.status === 'input-required') {
const approved = await getApproval(response.message);
if (!approved) {
throw new Error('Campaign creation not approved');
}
response = await adcp.send({
context_id: response.context_id,
approved: true
});
}
// 非同期作成の処理
if (response.status === 'working') {
response = await waitForCompletion(response);
}
if (response.status === 'completed') {
return response.media_buy_id; // Task fields are at top level
} else {
throw new Error(response.message);
}
}
完了まで待機
async function waitForCompletion(initialResponse, options = {}) {
const { maxWait = 120000, pollInterval = 5000 } = options;
const startTime = Date.now();
let response = initialResponse;
while (response.status === 'working') {
if (Date.now() - startTime > maxWait) {
throw new Error('Operation timed out');
}
await sleep(pollInterval);
response = await adcp.call('tasks/get', {
task_id: response.task_id,
include_result: true
});
}
return response;
}
非同期前提の設計
状態を永続化します
非同期処理でメモリ状態に依存しない:
class AsyncOperationTracker {
constructor(db) {
this.db = db;
}
async startOperation(taskId, operationType, request) {
await this.db.operations.insert({
task_id: taskId,
type: operationType,
status: 'submitted',
request: request,
created_at: new Date(),
updated_at: new Date()
});
}
async updateStatus(taskId, status, result = null) {
await this.db.operations.update(
{ task_id: taskId },
{
status: status,
result: result,
updated_at: new Date()
}
);
}
async getPendingOperations() {
return this.db.operations.find({
status: { $in: ['submitted', 'working', 'input-required'] }
});
}
}
再起動に耐える
オーケストレーター再起動後に追跡を再開:
async function onStartup() {
const tracker = new AsyncOperationTracker(db);
const pending = await tracker.getPendingOperations();
for (const operation of pending) {
// Check current status on server
const response = await adcp.call('tasks/get', {
task_id: operation.task_id,
include_result: true
});
// Update local state
await tracker.updateStatus(operation.task_id, response.status, response);
// Resume polling if still pending
if (['submitted', 'working'].includes(response.status)) {
startPolling(operation.task_id);
}
}
}
ベストプラクティス
- 非同期前提で設計 - どの操作も時間がかかる前提
- 状態を永続化 - メモリだけに依存しません
- 再起動を考慮 - 起動時に追跡を再開
- タイムアウトを実装 - 無限に待たない
- 進捗を表示 - ユーザーに状況を伝える
- キャンセル対応 - 長時間処理をキャンセル可能に
- 監査証跡 - ステータス遷移をログ
次のステップ