CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/API & SDK
API & SDK/2026-05-02中級

Claude API のストリーミングを途中で止める — AbortController の正しい使い方と請求の仕組み

Claude API のストリーミングを AbortController で止めたとき、実際に請求される出力トークンを100回計測しました。中断ドリフトの実測値、close 未配線が生む月18.7ドルの差、プロキシのバッファリング問題までを Node.js と Python の実装つきで扱います。

claude-api81streaming16abortcontrollercost-optimization25node-jspython22

プレミアム記事

「ユーザーが『止めて』ボタンを押した瞬間、Claude API のレスポンスを止めたい。でも、止めた分のトークンって課金されるの?」 — チャット UI を本番に出した直後、私が同僚から最初に受けた質問です。Anthropic SDK にはちゃんとキャンセル機構が用意されているのですが、ドキュメントを順に読むだけだと「で、結局いくら請求されるのか」までは見えにくいところがあります。

ここではストリーミング応答を AbortController で途中停止する実装と、キャンセル時の出力トークンが実際にどう課金されるかを、Node.js(TypeScript)と Python の両方で整理します。検証したのは Anthropic SDK の最新版(v0.30 系)と Claude Sonnet 4.6 の組み合わせです。

個人開発で運用している iOS アプリに相談チャットを載せたとき、私はこの「止めたときの請求」を確かめないまま本番に出しました。結果として痛い目を見たのは請求額ではなく、深夜に鳴ったアラートのほうでした。その顛末も含めて書きます。

結論を先に:キャンセルしても、生成済みの分は課金される

最初に押さえておきたいのはここだけです。

  • 入力トークン(プロンプト分)は、キャンセルしても全額課金されます。サーバーがリクエストを受け取って処理を開始した時点で確定します。
  • 出力トークンは、生成された分だけ課金されます。ストリームを途中で切れば、その地点までのトークンが請求対象になります。
  • AbortController で接続を切っても、サーバー側で「次の数トークン」が生成済みになっている可能性があります。請求書には数トークンの誤差が乗ることがあります。

つまり「止めたから 0 円」ではなく、「止めたところまでは払う」が正しい理解です。Anthropic の usage レスポンス(message_delta イベントの usage.output_tokens)は、キャンセルされてもストリーム内で送られていた分は返ってきます。後述するコードで、最後に届いた usage を必ず保存しておくと、コスト集計が正確になります。

実際の数字感としては、Sonnet 4.6 のチャットで 1 文字目が出始めた段階で止めると、入力トークン全額 + 出力 5〜30 トークン程度が請求されることが多いです。ヘビーユーザー向けに「キャンセルボタン」を提供するときは、UX 上のメリットの方が大きいので、課金面はあまり気にしなくて構いません。むしろ気をつけたいのは、サーバー側の同時接続が積み上がるパターンです(後述)。

Node.js(TypeScript)での実装

Anthropic SDK の messages.stream() は、AbortSignal を受け付けます。Express のリクエストハンドラから AbortController を渡すパターンが一番素直です。

import Anthropic from "@anthropic-ai/sdk";
import express from "express";
 
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! });
const app = express();
 
app.post("/api/chat/stream", express.json(), async (req, res) => {
  // クライアントが切断したらサーバー側でも止める
  const controller = new AbortController();
  req.on("close", () => controller.abort());
 
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache, no-transform");
  res.setHeader("Connection", "keep-alive");
 
  let outputTokens = 0;
  try {
    const stream = await client.messages.stream(
      {
        model: "claude-sonnet-4-6",
        max_tokens: 1024,
        messages: req.body.messages,
      },
      { signal: controller.signal },
    );
 
    for await (const event of stream) {
      if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
        res.write(`data: ${JSON.stringify({ text: event.delta.text })}\n\n`);
      } else if (event.type === "message_delta") {
        // 最後に届いた usage を保存(キャンセル時もここまでの分は届く)
        outputTokens = event.usage.output_tokens;
      }
    }
 
    res.write(`data: [DONE]\n\n`);
    res.end();
  } catch (err: any) {
    // AbortError は正常系として扱う(ユーザーが止めただけ)
    if (err.name === "AbortError" || controller.signal.aborted) {
      console.log(`Stream cancelled. Output tokens billed so far: ${outputTokens}`);
      return; // res は既に閉じている
    }
    console.error(err);
    res.write(`data: ${JSON.stringify({ error: "stream_failed" })}\n\n`);
    res.end();
  } finally {
    // 必要なら usage を DB / 集計サービスに送る
    await recordUsage({ outputTokens, cancelled: controller.signal.aborted });
  }
});
 
async function recordUsage(_: { outputTokens: number; cancelled: boolean }) {
  // ここで Postgres / DataDog 等に記録
}

ポイントは三つあります。一つ目は req.on("close", () => controller.abort()) の一行。これがないと、ユーザーがブラウザを閉じてもサーバー側はストリームを最後まで読み続けてしまい、無駄なトークンを消費します。二つ目は event.type === "message_delta" のタイミングで usage.output_tokens を毎回上書きしておくこと。三つ目は AbortError を握り潰すこと。これは「エラー」ではなく「ユーザーがキャンセルした」という正常系のシグナルなので、ログに error レベルで出すと運用ノイズになります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
キャンセル時に余分に生成される出力トークン(平均12・p95 27・最大34トークン)を100回計測した実データで、課金の実像を把握できます
close ハンドラを配線し忘れたときの月額差(約0.29ドル 対 約18.7ドル・64倍)と、その差が生まれる仕組みを追えます
ユーザー中断・タイムアウト・プロセス停止を AbortSignal.any で束ねつつ停止理由を復元し、usage を取りこぼさない計測レイヤーの実装を持ち帰れます
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

API & SDK2026-05-06
Claude API × Python 実践:ツール呼び出しとストリーミングを組み合わせてAIアシスタントを作る
Claude API の Tool Use とStreamingを同時に使うPython実装を解説。ツールを定義してリアルタイム応答するAIアシスタントの完成コードと、組み合わせ時に詰まりやすいポイントを丁寧に解説します。
API & SDK2026-03-24
Claude API Token Counting — 事前にトークン数を把握してコストを最適化する方法
Claude APIのToken Counting エンドポイントを活用して、メッセージ送信前にトークン数を正確に見積もる方法を解説。コスト管理、コンテキストウィンドウの最適化、本番環境での実装パターンまで網羅します。
API & SDK2026-07-13
Claude API の同時実行を束ねる — シングルフライトで重複推論とキャッシュ・スタンピードを防ぐ
同一プロンプトが同時に何度も Claude へ飛ぶ重複推論を、シングルフライト(request coalescing)で束ねる設計です。プロセス内・分散環境の実装、ジッター付きリトライ、負のキャッシュまで実測付きでまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →