Skip to main content
ベストプラクティス

Outcome のベストプラクティス

Outcome の推奨される使い方:タスクと合格基準の記述、評価回数の選択、完了判定、成果物の取得。

このページでは Outcome の推奨される使い方を説明し、完全な例を示します。フィールドと仕組みは Outcome の評価を参照してください。

フロー概要

評価に合格する Outcome は以下の順序で実行されます。
  1. クライアントは description にタスク、rubric に合格基準を指定して user.define_outcome を送信します。
  2. Agent は description に従って作業し、Session は running になります。
  3. 評価スレッドが成果物を評価し、span.outcome_evaluation_start、span.outcome_evaluation_ongoing、span.outcome_evaluation_end が発行されます。
  4. span.outcome_evaluation_end.result が satisfied となり、Session オブジェクトの outcome_evaluations[].completed_at が設定されます。
  5. Agent が最終返信を書き、Session は idle に戻ります。

タスクと合格基準

description は Agent turn の入力で、rubric は評価スレッド専用です。互いに相手の内容を読むことはできません。
内容記述先読み取る側
タスク、成果物パス、出力形式、元データdescriptionAgent
合格基準、期待値、失敗条件rubric評価スレッド
  • タスクを rubric にしか記述しない場合、Agent はタスクを読めません。
  • 評価スレッドは description を読めません。基準が依存する期待値や元データは rubric に入れ、「タスク記述と照合」のような基準を避けてください。
合格基準の記述例:
種類例
成果物の場所/data/report.html が存在する
具体的な内容スループットとレイテンシの数値を含み、それぞれ 1 個以上のグラフがある
証拠各ボトルネックにコード位置または profiling データを添える
失敗条件サンドボックスにファイルがなく、Agent が完了不能と表明した場合は failed
各基準は 1 つのことだけを記述します。「完全」「実行可能」「証拠付き」を 1 つにまとめず、3 つに分けます。

評価回数

max_iterations は評価回数の上限です。各評価が credits を消費します。
値用途
1合否判定だけが必要。不合格の場合、Outcome は max_iterations_reached になります
2–3(デフォルト 3)判定に基づいて Agent に修正させたい場合。needs_revision の後に自動で修正 turn が始まります
3 より大きい値タスクの収束に複数回の修正が必要な場合
まず max_iterations: 1 で rubric を調整します。1 回で正しい判定が得られることを確認してから上限を増やします。

送信タイミング

user.define_outcome は単独のリクエストで、Session が idle かつ有効な Outcome がない場合にのみ送信します。
curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  | jq '{status, active_outcomes: [.outcome_evaluations[] | select(.completed_at == null)] | length}'
status が idle かつ active_outcomes が 0 の場合に送信できます。リクエスト制約を参照してください。

完了の判定

Outcome の実行中は Session が running のままです。目的に応じて条件を選びます。
目的条件
評価判定を読むoutcome_evaluations[].completed_at が null ではない
Agent の最終返信を読む、または次のイベントを送るSession の status が idle に戻る
result とともに explanation を読みます。explanation は基準ごとの評価説明を含み、ユーザーへの表示やログへの記録に使えます。 ストリーム上で stop_reason.type: requires_action の session.status_idle が発行された場合はツール確認待ちで、Outcome の終了ではありません。ツール確認を参照してください。

成果物の取得

rubric がファイルを求める場合、description に /data/ への書き込みと DeliverArtifacts による交付を指示します。成功すると、ストリームに agent.artifact_delivered が発行されます。
  • 修正 turn で再交付すると新しい File が作成されます。最後の agent.artifact_delivered の file_id で最終版を取得します。
  • 交付後、ファイル一覧への反映に数秒かかる場合があります。
  • Agent が返信に直接結果を返す場合もあります。クライアントは両方を処理してください。
エンドポイントは Session の成果物の交付と取得を参照してください。

例:注文の集計

この例では、注文 CSV から注文数、合計金額、購入金額が最大の顧客を計算し、/data/summary.json に書き込んで交付します。その後 Outcome が結果の正しさを評価します。

1. Agent の作成

評価スレッドは Agent のツール権限を継承します。評価に必要なツールを always_allow に設定し、手動確認なしで Outcome を実行できるようにします。
AGENT_ID=$(curl -s -X POST "https://api.qoder.com/api/v1/cloud/agents" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "order-summary-agent",
    "model": "auto",
    "system": "You are a data assistant. Produce exactly the files the user asks for.",
    "tools": [{
      "type": "agent_toolset_20260401",
      "enabled_tools": ["Bash", "Read", "Write", "Glob", "Grep", "DeliverArtifacts"],
      "configs": [
        {"name": "Bash",  "permission_policy": {"type": "always_allow"}},
        {"name": "Read",  "permission_policy": {"type": "always_allow"}},
        {"name": "Write", "permission_policy": {"type": "always_allow"}},
        {"name": "Glob",  "permission_policy": {"type": "always_allow"}},
        {"name": "Grep",  "permission_policy": {"type": "always_allow"}},
        {"name": "DeliverArtifacts", "permission_policy": {"type": "always_allow"}}
      ]
    }]
  }' | jq -r '.id')

2. Session の作成

SESSION_ID=$(curl -s -X POST "https://api.qoder.com/api/v1/cloud/sessions" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"agent\": \"$AGENT_ID\", \"environment_id\": \"$ENVIRONMENT_ID\", \"title\": \"order summary\"}" \
  | jq -r '.id')

3. Outcome の定義

タスクと元データは description、期待値は rubric に入れます。max_iterations は 2 で、判定に基づく 1 回の修正を許可します。
cat > define.json <<'EOF'
{
  "events": [{
    "type": "user.define_outcome",
    "description": "Below is an order CSV. Compute the number of orders, the total amount, and the customer with the highest spend, write them to /data/summary.json as {\"order_count\": <int>, \"total_amount\": <number>, \"top_customer\": <string>}, then deliver the file with DeliverArtifacts. Finish with a one-sentence reply.\n\norder_id,customer,amount\n1001,alice,120.50\n1002,bob,80.00\n1003,alice,35.25\n1004,carol,210.00\n1005,bob,60.00",
    "rubric": {
      "type": "text",
      "content": "# Order summary rubric\n\nThe expected values below were computed from the source data in advance.\n\n## Deliverable\n- /data/summary.json exists in the sandbox (read the file; do not rely on the Agent's reply)\n- Its content is valid JSON with exactly the fields order_count, total_amount, top_customer\n\n## Values\n- order_count == 5\n- total_amount == 505.75 (0.01 tolerance)\n- top_customer == \"carol\"\n\n## Verdict\n- Any criterion unmet: needs_revision, listing each gap and how to fix it\n- The file is absent from the sandbox and the Agent states it cannot finish: failed"
    },
    "max_iterations": 2
  }]
}
EOF

curl -s -X POST "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/events" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d @define.json

4. 評価結論の取得

until [ "$(curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  | jq -r '.outcome_evaluations[-1].completed_at // empty')" != "" ]; do sleep 3; done

curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  | jq '.outcome_evaluations[-1] | {result, iteration, explanation, completed_at}'
レスポンス例:
{
  "result": "satisfied",
  "iteration": 0,
  "explanation": "Read /data/summary.json directly. It is valid JSON with exactly three keys: order_count=5, total_amount=505.75, top_customer=\"carol\" — matching every rubric criterion. Agent reply values are consistent with the file but were not relied upon; the file itself is the evidence.",
  "completed_at": "2026-09-24T03:15:54.986863Z"
}

5. 最終返信の取得

completed_at が設定された時点では最後の turn が実行中の場合があります。Session が idle に戻るまで待ち、最後の agent.message を読みます。
until [ "$(curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" | jq -r '.status')" = "idle" ]; do sleep 2; done

curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/events?limit=100" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  | jq -r '[.data[] | select(.type == "agent.message")][-1].content[0].text'

6. 成果物の取得

FILE_ID=$(curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/events?limit=100" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  | jq -r '[.data[] | select(.type == "agent.artifact_delivered")][-1].file_id')

curl -s "https://api.qoder.com/api/v1/cloud/files/$FILE_ID/content" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" | jq -r '.url' | xargs curl -s
出力:
{"order_count": 5, "total_amount": 505.75, "top_customer": "carol"}

7. Session のアーカイブ

curl -s -X POST "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/archive" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"

イベントストリーム

初回評価で合格した場合の、この例のイベント順序です(span.model_request_* と agent.thinking は省略)。
session.status_running
user.define_outcome
agent.tool_use                     Write
agent.tool_use                     DeliverArtifacts
agent.artifact_delivered           summary.json
agent.message                      Agent turn reply
span.outcome_evaluation_start      iteration=0
span.outcome_evaluation_ongoing
span.outcome_evaluation_end        result=satisfied
agent.message                      final reply
session.status_idle                stop_reason.type=end_turn
初回の成果物が不合格の場合、span.outcome_evaluation_end.result は needs_revision となり、その後に修正 turn の agent.tool_use、新しい agent.artifact_delivered、iteration=1 の評価イベントが続きます。Session には 2 件の summary.json があり、最後の agent.artifact_delivered が最終版を指します。

チェックリスト

  • タスク、成果物パス、出力形式は description、合格基準は rubric に記述します。
  • rubric は description の内容に依存せず、期待値や元データが rubric に記述されています。
  • 各基準を独立して検証でき、失敗条件が明記されています。
  • 初回は max_iterations: 1 を使用し、1 回で正しい判定が得られることを確認します。
  • 評価に必要な読み取りツールを always_allow に設定するか、クライアントが requires_action を処理します。
  • user.define_outcome は Session が idle かつ有効な Outcome がない場合にのみ、単独リクエストで送信します。
  • 同じリクエストの再試行には Idempotency-Key を付けます。
  • Outcome の終了は completed_at で判断し、最終返信の取得や次のイベント送信は Session が idle に戻るまで待ちます。
  • explanation を読み、記録します。
  • 最後の agent.artifact_delivered の file_id で成果物を取得します。