Skip to main content
Agent にタスクを委任する

Sessions

Cloud Agent Session の作成、実行、確認、アーカイブ。

Session は Agent の実行ワークスペースです。Agent のスナップショットを Environment、オプションのリソース、オプションの Vault 認証情報にバインドします。新しい Session は idle で開始し、イベントを送信すると処理が始まります。

ランタイム設定の動的更新

既存の Session は固定されたランタイムスナップショットを使用します。Agent の更新や新しい Agent バージョンの公開では既存の Session は変更されず、数値バージョンに固定された Skill バインディングも新しい Skill バージョンの公開後もそのバージョンを使い続けます。モデル、システムプロンプト、ツール、MCP server、Skill バインディング、名前、説明の変更を適用するには、対応する agent フィールドを指定して Session の更新 を呼び出します。バージョンを省略した Skill バインディングまたは "latest" は、sandbox 準備時に最新の Skill バージョンに追従します。

Session の状態ライフサイクル

Session はステートマシンです。Session リソースの status フィールドは次のいずれかの値を取ります。
状態説明遷移先
idleSession はアイドルで、メッセージを受け取る準備ができているrunning、terminated
runningAgent がターンを処理中idle、rescheduling、terminated
reschedulingモデルリクエストで回復可能なエラーが発生し、サービスが自動的に再試行している。現在のターンは引き続きアクティブrunning、idle、terminated
terminatedSession は終了済み(終端状態)—
status フィールド以外に、さらに 2 つのライフサイクルマーカーが現れます。
  • アーカイブ済み(Archived): 非 null の archived_at タイムスタンプで示されます。status の値自体は archived には変わりません — Session は引き続き読み取れますが、新しいイベントは拒否されます。
  • cancel レスポンス: POST /api/v1/cloud/sessions/{id}/cancel エンドポイントは常に固定のリテラル "status": "canceling" を含むボディを返します。これはレスポンスの形であって Session の status ではありません — 永続化された status はターンが中断されると idle に戻ります。
1

作成 → idle

新しい Session は idle で開始し、入力を待ちます。
2

idle → running

user.message イベントを送信すると、Session は running に移行します。
3

running → idle

ターンが完了すると、Session は idle に戻ります。ターンごとにこれを繰り返します。
4

running → idle(cancel 後)

実行中の Session をキャンセルするとターンが中断され、Session は idle に戻ります。cancel レスポンスボディは、永続化された status に関わらず固定の "status": "canceling" リテラルを使用します。Session は引き続き再利用できます。
5

running → rescheduling → running / idle

モデルリクエストの自動再試行中、Session は一時的に rescheduling へ移行する場合があります。次の試行が始まると running に戻り、現在のターンが終了すると idle に戻ります。
6

archived / terminated(終端状態)

アーカイブ(archived_at 経由)または終了によって Session は恒久的に終了します — 再開はできません。

モデルリクエストの自動再試行

サービスがモデルリクエストのエラーを回復可能と判断すると、自動的に再試行し、Session または Thread が一時的に rescheduling へ移行する場合があります。これは現在のターンの一部です。クライアントが user.message を再送する必要はありません。イベントストリームを開いたままにし、状態が running または idle に戻るまで待機してください。モデルがレスポンスの一部を生成した後にエラーが発生した場合、出力やツール呼び出しの重複を避けるため、サービスはリクエストを再実行しません。 session.error を受信した場合は、error.retry_status.type でサービスが再試行するかを判断します。最終結果は、その後の Session/Thread 状態イベントを正としてください。

Cancel のセマンティクス

  • idle への cancel: no-op。HTTP 200 を返し、status は idle のままです。
  • アクティブなターンへの cancel: running と rescheduling のどちらにも適用されます。HTTP 202 を返し、レスポンスの status は canceling になります。ターンが中断されると Session は idle に戻ります。
  • cancel 後: Session は引き続き再利用できます — 次の user.message を送信すると新しいターンが開始します。
# 現在のターンをキャンセル
curl -s -X POST "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/cancel" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"
終端状態は archived と terminated のみです。キャンセルされた Session は常に idle に戻り、メッセージを受け取り続けられます。

ターン処理中の Session へのメッセージ送信(409 エラー)

Session がターンを処理している間(running または rescheduling)に新しい user.message を送信すると、API は HTTP 409 を返します。
{
  "type": "error",
  "request_id": "cb80235f-76a2-4ff3-9e28-5aa2da12dc14",
  "error": {
    "type": "invalid_request_error",
    "message": "Session is currently processing a turn. Cancel the current turn or wait for completion."
  }
}
これは新規ユーザーが最も陥りやすい落とし穴です。次のメッセージを送信する前に必ず session.status_idle を待つか、先に現在のターンをキャンセルしてください。

Session を作成する

既存の agent と environment_id を使って Session を作成します。
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": {"id": "agent_019e390add9f7bac9b6cc806db46fcbd", "type": "agent", "version": 2},
    "environment_id": "env_019e2590d33f711fabf42f2857cecd8a",
    "title": "Code review session",
    "metadata": {"purpose": "review"}
  }'
作成レスポンスは Session オブジェクトです。agent、environment_id、status、resources、vault_ids、deployment_id、outcome_evaluations、stats、usage、environment_variables、archived_at、created_at、updated_at を含みます。usage は累積の model_credits、sandbox_runtime_credits、total_credits を返します。各値は小数点以下 2 桁まで切り捨てられます。 environment_variables は文字列から文字列へのマップ形式で指定します。フィールド形式と検証ルールについては Session の作成を参照してください。

作成時にリソースをアタッチする

resources 配列でファイル、リポジトリ、Memory Store をアタッチします。
{
  "resources": [
    {
      "type": "file",
      "file_id": "file_019e5ce0bf307a1a8f952eb814aea3d5",
      "mount_path": "/data/input/spec.md"
    },
    {
      "type": "github_repository",
      "url": "https://github.com/your-org/your-repo",
      "mount_path": "/data/workspace/your-repo",
      "authorization_token": "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    },
    {
      "type": "memory_store",
      "memory_store_id": "memstore_019eed05b61e78cea61bfd366e072878",
      "access": "read_write",
      "instructions": "Use this memory for long-lived project context."
    }
  ]
}
作成後にファイルを追加するには、Session リソース追加 API を使用します。現在の CAS では、作成後の追加は file リソースのみサポートしています。resource の list/get/update/delete エンドポイントを使って、リソースの確認、GitHub トークンのローテーション、リソースの削除を行えます。

メッセージを送信する

Events API を通じて user.message イベントを送信します。content は空でない content block の配列でなければなりません。
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 '{
    "events": [
      {
        "type": "user.message",
        "content": [
          {"type": "text", "text": "Review this repository and summarize the risks."}
        ]
      }
    ]
  }'
send-events エンドポイントは HTTP 200 と {"data":[...]} を返します。受け付けるクライアントイベントタイプは次のとおりです: user.message、user.interrupt、user.tool_confirmation、user.tool_result、user.custom_tool_result、user.define_outcome、system.message。 ユーザーメッセージではテキストと画像を混在させることも、画像のみを送信することもできます。画像は Base64、外部 HTTPS URL、またはアップロード済みの File ID で指定できます。フィールドと制限はメッセージのコンテンツブロック、リクエストボディの例は画像メッセージを送信するを参照してください。

イベントを読み取る

ライブ更新にはイベントストリームを使用します。
curl -s -N "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/events/stream" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Accept: text/event-stream"
ストリームは id、event、data を含む Server-Sent Events を出力します。stream エンドポイントは再接続時のリプレイ用に Last-Event-ID ヘッダーをサポートします。イベントタイプの query filter は現在サポートされていません。 履歴とページネーションには list エンドポイントを使用します。
curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/events?limit=20&order=desc" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"
list レスポンスは data と next_page を使用します。

Session の読み取りと更新

# 単一 Session を取得
curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"

# Session 一覧
curl -s "https://api.qoder.com/api/v1/cloud/sessions?limit=20" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"

# title、metadata、または Agent 構成(tools、MCP servers)を更新
curl -s -X POST "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Updated title","metadata":{"priority":"high"}}'
Session list は page / next_page ページネーションを使用し、agent_id、agent_version、deployment_id、memory_store_id、statuses、created_at[...] などのフィルターをサポートします。

Threads

Managed-agent Session は、コーディネータースレッドと子スレッドを持つことができます。Thread エンドポイントは公開の session_thread 形式を使用し、role、name、agent_id、agent_version、stop_reason などのレガシースレッドフィールドは含みません。
curl -s "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/threads" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"
子スレッドは POST /api/v1/cloud/sessions/{session_id}/threads/{thread_id}/archive でアーカイブできます。現在の CAS では、コーディネーター/メインスレッドのアーカイブを要求すると 409 を返します。

ライフサイクル

Session を今後使用しない場合はアーカイブします。
curl -s -X POST "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID/archive" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"
削除の確認が必要な場合は Session を削除します。
curl -s -X DELETE "https://api.qoder.com/api/v1/cloud/sessions/$SESSION_ID" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"
削除は次を返します。
{
  "id": "sess_019e3bb1e8c171fd9abbb1477ffb84cc",
  "type": "session_deleted"
}
cancel エンドポイントは {"id":"...","type":"session","status":"canceling"} を返します。キャンセル対象のアクティブなターンがある場合は 202 Accepted を、Session がすでに idle の場合は(no-op として)200 OK を返します。

マルチターン対話のワークフロー

Session はマルチターン対話をサポートします。推奨パターンは次のとおりです。
  1. user.message イベントを送信する。
  2. SSE ストリームで更新をリッスンする。
  3. session.status_idle イベントを待つ。
  4. 次の user.message を送信する。
#!/bin/bash
# マルチターン対話の例
BASE_URL="https://api.qoder.com/api/v1/cloud"
SESSION_ID="sess_019e5ce0bf9074b69c3481e93771a522"
HEADERS=(
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN"
)

# 第 1 ターン: 要件を提示
curl -s -X POST "$BASE_URL/sessions/$SESSION_ID/events" \
  "${HEADERS[@]}" \
  -H "Content-Type: application/json" \
  -d '{"events": [{"type": "user.message", "content": [{"type": "text", "text": "Scaffold a Python Flask project."}]}]}'

# 処理完了を待つ(ポーリングまたは SSE リッスン)
sleep 30

# 第 2 ターン: 追加要件
curl -s -X POST "$BASE_URL/sessions/$SESSION_ID/events" \
  "${HEADERS[@]}" \
  -H "Content-Type: application/json" \
  -d '{"events": [{"type": "user.message", "content": [{"type": "text", "text": "Add unit tests and a CI configuration to the project."}]}]}'
次のメッセージを送信する前に必ず session.status_idle を待ってください。Session がまだ running の間にメッセージを送信すると HTTP 409 を返します。

ベストプラクティス

  1. Agent バージョンを固定する — 本番環境では常に {"id": ..., "type": "agent", "version": ...} で Session を作成し、Agent の更新によって Session の挙動が予期せず変わらないようにします。
  2. metadata を活用する — トレーサビリティとデバッグのために、業務コンテキスト(タスク ID、トリガー元など)を metadata フィールドに記録します。
  3. 早めにキャンセルする — 不要になった Session はキャンセルして計算リソースを解放します。

よくある質問

Q: running 状態の Session にメッセージを送るとどうなりますか? A: API は HTTP 409 を返し、type: "invalid_request_error" とメッセージ "Session is currently processing a turn. Cancel the current turn or wait for completion." が含まれます。現在のターンをキャンセルするか、Session が idle に戻るのを待ってから次のメッセージを送信してください。 Q: キャンセル後も Session を使えますか? A: 使えます。cancel 後、Session は canceling から idle に戻ります。次の user.message を送信して対話を継続できます。終端状態は archived と terminated のみです。 Q: 完全な対話履歴を取得するには? A: GET /api/v1/cloud/sessions/{id}/events を使って、ユーザーメッセージと Agent 応答を含む Session のすべてのイベントを取得します。 Q: SSE が切断された後に再接続するには? A: SSE stream エンドポイントに再接続する際に Last-Event-ID ヘッダーを渡します。サーバーはその ID 以降のイベントをリプレイします。 Q: GET /api/v1/cloud/environments が空配列を返します。 A: PAT または SAT が対象ワークスペースに必要な権限を持っているか確認してください。Environment のアクセス範囲は認証主体の権限にスコープされます。

API リファレンス

Sessions

Events

Resources

Threads

Events