0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScript で AI agent を動かすなら、model 選びより先に timeout・approval・telemetry を決める

0
Posted at

publishPost が approval 待ちに入った。ところが画面は spinner のまま。ユーザーには「処理中」なのか「確認待ち」なのか分からない。

この状態で model を替えても、運用はあまり良くならない。approval 待ち、timeout、tool error は、次に取るべき操作がそれぞれ違うからだ。ひとつの isLoading に押し込むと、agent が賢くなるほど UI の説明が雑になる。

AI SDK 7 には tool 単位の approval、複数粒度の timeout、OpenTelemetry 連携が入った。全部を紹介するより、まず frontend と backend が共有する runtime contract を小さく決めたい。

side-effect contract : どの tool を人間が止めるか
time contract        : どこで何秒待つか
trace contract       : どの run / session を追うか

前提は Node.js 22 以上と ESM。ここからは、小さな social card 公開 agent を例にする。

approval_required は error ではない

tool を先に、副作用で分ける。

type ToolPolicy = {
  effect: 'read' | 'external'
  approval: 'none' | 'user'
}

const toolPolicies = {
  findUiReferences: { effect: 'read', approval: 'none' },
  publishPost: { effect: 'external', approval: 'user' },
} satisfies Record<string, ToolPolicy>

ToolLoopAgent などで tool ごとの approval policy を設定できるので、止めるのは publishPost だけでいい。read-only の検索まで毎回確認させると、安全性より先に確認疲れが来る。

画面側では、少なくとも state を分けておく。

type AgentRunState =
  | 'queued'
  | 'running'
  | 'approval_required'
  | 'resumed'
  | 'succeeded'
  | 'timed_out'
  | 'failed'

approval_required では tool 名、input の要約、approve / deny を表示する。deny は通信失敗ではない。ユーザーが選んだ正常な分岐だ。

再開時には、最初に見せた input と現在の input が同じか、policy が変わっていないかを再検証する。AI SDK 7 は approval の再開時に input と policy を検証でき、高リスクな操作では HMAC で input と approval token を結び付けられる。ただし approval は「この side effect を実行してよい」という判断材料であって、投稿内容の正しさや rollback まで保証する仕組みではない。

timeout を一個の数字にしない

timeout: 60_000 だけでは、どこが止まったのか分からない。run 全体、model の一段、stream の沈黙、tool 実行では、失敗後の扱いが違う。

以下は AI SDK の schema ではなく、team が repo で共有する policy の例だ。

const runtimePolicy = {
  timeoutMs: {
    total: 60_000,
    step: 10_000,
    chunk: 2_000,
    defaultTool: 5_000,
    tools: {
      publishPost: 8_000,
    },
  },
} as const
  • total: run が際限なく続くのを止める
  • step: model call や orchestration の一段を区切る
  • chunk: stream が黙ったままになるのを検出する
  • tool: 外部処理ごとの待ち時間を決める

AI SDK 7 では total、step、chunk、default tool、per-tool の timeout を持てる。TimeoutError と abort reason も stream / UI protocol に流せるので、画面で timed_out を普通の failed と分けられる。

timeout したからといって、外部処理が巻き戻るわけではない。publishPost が外部 API に届いた直後に client 側が timeout した可能性は残る。再試行できるかどうかは、tool の idempotency key や外部サービスの状態確認まで含めて決める必要がある。

runIdsessionId を画面にも出す

telemetry を入れても、画面のエラーと trace がつながらなければ調査は遅い。model 名より先に、run と session を共通キーにする。

type AgentRunEvent = {
  runId: string
  sessionId: string
  step: number
  tool?: string
  state:
    | 'running'
    | 'approval_required'
    | 'resumed'
    | 'succeeded'
    | 'timed_out'
    | 'failed'
  elapsedMs: number
  finishReason?: string
}

AI SDK 7 は registerTelemetry@ai-sdk/otel で model call、step、tool、agent execution を OpenTelemetry へ接続できる。lifecycle callback からは callId、step number、finish reason、usage、error、performance を拾える。

Vercel Sandbox では CPU、memory、data transfer などを Sandbox Session ID 単位で group 化できる。これは特定 runtime の例だが、「どの model を使ったか」だけでなく「どの session が resource を使ったか」を追う設計の分かりやすい参考になる。

context を丸ごと attribute に入れるのはまずい。prompt、token、投稿先 credential のような値は、必要な項目だけ明示的に telemetry へ渡す。

social card agent に失敗を注入する

success path を一度眺めるより、復旧方法の違う失敗を先に起こしたほうが contract の穴を見つけやすい。

今回の workflow 境界はこうする。agent tool ではない手動工程も、同じ図に入れておく。

findUiReferences   read-only             approval 不要
prepareImage       browser-local manual  approval 不要
publishPost        external side effect  user approval 必須

findUiReferences は UI パターンを探すだけの read-only step にする。MCP Apps UI、A2UI、AG-UI の資料を横断するときは、生成AI UIデザインのリソース集のような索引を人が参照する形でも足りる。agent integration が必要な処理ではない。

画像も同じだ。prepareImage という名前だからといって、pixel を agent backend に送る必要はない。Resize Image Forのように browser 内で resize と export を完結できる道具を手動工程に置けば、画像データを外へ送る tool 自体を増やさずに済む。

次の順で壊してみる。

  1. publishPost を approval 待ちにして、UI が approval_required へ移るか確認する。
  2. deny を選び、failedtimed_out と別の結果として記録できるか見る。
  3. tool を意図的に遅らせ、tool timeout と total timeout を別 event にできるか確かめる。
  4. tool error を返し、画面の runId / sessionId から同じ trace を引く。

process restart や deploy をまたいで approval を待つなら、memory 上の state だけでは足りない。AI SDK 7 の WorkflowAgent は step 間の state を durable storage に保存し、interrupt や遅延 approval から再開できる。どの workflow に durable resume が必要かは、この failure injection の段階で切り分ける。

repo に置く contract は小さくていい

実装ライブラリの設定とは別に、review で読める形を一枚置く。

# team-owned checklist。AI SDK の公式 schema ではない
agent_runtime:
  approval_tools:
    - publishPost
  timeout_ms:
    total: 60000
    step: 10000
    tool: 5000
  trace_keys:
    - runId
    - sessionId
  terminal_states:
    - succeeded
    - timed_out
    - failed

これがあると、「新しい model のほうが賢いか」という話を始める前に、同じ失敗を同じ state と trace で再現できる。地味な順番だけれど、agent の運用で先に固定したいのは model ranking よりこちらだ。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?