Claude Codeの仕組み講座(講師のためのエンジニア水準)
区分5 自分で作る(エンジニア水準)★★たとえ話にします。ふだんの Claude Code は、窓口に座ってお客さん(あなた)と話しながら進める営業スタイルです。会話なしで動かすのは、依頼書を事務所の受付に投げ込んでおくスタイルで、事務所の中は同じ人たちが同じ手順で働きます。違うのは、窓口で人が応対しているかどうかだけです。
この単元で出てくる言葉を、先に説明します。
claude -p ... はここで打ちます{"名前": "値"} のように、項目名と値が対になります。機械が読みやすい形式ですclaude -p "要約して" の "要約して" が引数です混ざりやすいので、先に分けます。
| 呼び名 | 何か | 誰がエージェントの繰り返しを動かすか |
|---|---|---|
| Claude Code(ふだんの画面) | 会話しながら使う | Claude Code |
claude -p |
会話せず1回だけ動かして終わる(-p は print、答えを出力して終わる、という意味) |
Claude Code |
| Agent SDK | Claude Code の仕組みを、自分の Python / TypeScript のプログラムから使う部品 | Claude Code(SDKの中に入っている) |
| Client SDK(API を直接呼ぶ) | モデルに言葉を送って返事をもらうだけの部品。API は、プログラムからAIを呼ぶための窓口です | 自分で繰り返しを書く(または補助機能を使う) |
見分けるポイントは1つで、エージェントの繰り返し(考える→道具を使う→結果を見る)を、誰が動かしているかです。最初の3つは Claude Code が動かし、Client SDK だけは自分で組みます。
claude -p "依頼文" と打つと、会話をせずに答え(と作業)を1回して終わります。中で動いているのは、ふだんの Claude Code と同じ繰り返しで、考える、道具を呼ぶ、結果を見る、また考える、を「もう道具を呼ばない」という返事が出るまで続けます(No.02)。-p は画面を取り外して、入口と出口を文字だけにしたものです。
入口と出口は、次の3つです。
cat 長い文章.txt | claude -p "要約して" のように標準入力(別の命令の出力をつなぐ入口)で渡すこれが「プログラムから呼べる」の正体です。ほかのプログラムは、終了コードを見て、次に進むか止まるかを決められます。
--bare を付けない -p は、ふだんの会話と同じ物を読み込みます。つまり CLAUDE.md・スキル・フック・MCP は -p でもふだんどおり効きます(公式)。これを止めて、どのMacでも同じ結果にしたい時が --bare です。
オプションは、命令の後ろに足して動き方を変える指定です。次の表は、「何のためか」が言えれば足ります。
| オプション | 何のためか |
|---|---|
--allowedTools "Read,Edit" |
聞かずに使ってよい道具を先に許可する。人がいないので、許可を聞かれると止まるため |
--tools "Read,Grep" |
そもそも使える道具をこれだけに絞る |
--permission-mode |
許可のモードを先に決める(acceptEdits・auto・dontAsk など。No.13) |
--permission-prompts none |
許可を聞く相手がいない時、聞かずに断る(下の補足) |
--max-turns 3 |
往復の回数に上限をつける。暴走を防ぐ |
--max-budget-usd 5 |
見積もりの費用が上限に届いたら止める |
--output-format json |
結果をJSONで受け取る(次の ③ ) |
--json-schema '{...}' |
返事の形を指定する(次の ③ ) |
--continue / --resume 会話ID |
前の会話の続きから動かす |
--bare |
CLAUDE.md・スキル・フック・MCPなどの自動読み込みを止めて、起動を速く、どのMacでも同じ結果にする |
--allowedTools と --tools は別物です。前者は「聞かずに使ってよい」、後者は「使える道具をこれだけに絞る」です。さらに、使わせたくない道具を名前で外す --disallowedTools もあります(公式の cli-reference)。
--max-turns が数えるのは、「道具を使って結果を受け取る往復」です。公式は、SDK の max_turns を「道具を使う往復だけを数える」と説明しています。最後の「道具を呼ばない返事」は数えません。たとえば、道具を3回使って最後に文章で答える作業なら、数えるのは3回です。上限に届くと、その場で止まって失敗として返ります。
許可の止め方は、2つあります。--permission-mode dontAsk は、許可の聞き方そのものを決めるモードで、聞かれる場面はすべて断ります。--permission-prompts none は、「聞く相手(SDK を動かす側のプログラムや、許可を判断する MCP の道具)に聞きに行かない」という指定です。相手に聞かずに断り、AIには「誰も承認できないので、同じことを繰り返さないで」と伝えます(公式。v2.1.259 以降)。どちらも、許可ルールやフックが先に判定し、それでも決まらない物だけが断られます。判定の順番は No.13、機能ごとの強さの比較は No.15 を見てください。
○ 実測(手元のMacで確認):claude -p "..." --max-turns 1 で、1往復では終わらない依頼をしたら、終了コードは 1、結果の subtype は error_max_turns になりました
○ --bare を付けた -p は、サブスクのログインを使わず、APIキーが前提です(この単元の最後の補足)
--output-format で出力の形を変えられます。
| 指定 | 出力 |
|---|---|
text(標準) |
文章だけ |
json |
結果に、会話ID・費用・往復数などの情報を添えた1つのJSON |
stream-json |
1行1イベントのJSONを、リアルタイムで流す |
json で返ってくるJSONの主な項目は、次のとおりです。
| 項目 | 意味 |
|---|---|
result |
AIの最終の返事(文章) |
subtype |
終わり方。成功は success、往復の上限は error_max_turns |
session_id |
会話のID。--resume で続きに使える |
total_cost_usd |
見積もりの費用(ドル)。公式は、請求額と違うことがある概算と書いています |
--json-schema で返事の形を指定すると、形に合った結果が structured_output という別の項目に入ります。長いコマンドは、行末の \ で折り返して書けます。
claude -p "果物を3つ挙げて" \
--output-format json \
--json-schema '{"type":"object","properties":{"fruits":{"type":"array","items":{"type":"string"}}},"required":["fruits"]}'
structured_output に {"fruits": ["りんご","バナナ","みかん"]} の形で入るので、文章をあとで解析せず、プログラムがそのまま使えます。jq(JSONから必要な項目だけ取り出す命令)と組み合わせるのが定番です(公式の例)。
claude -p "このフォルダを要約して" \
--output-format json | jq -r '.result'
claude -p = ふだんと同じエージェントを、画面なしで1回動かす。入口は依頼文、出口は標準出力と終了コード。JSONにすれば費用と会話IDも取れる。
公式の説明を平らに言うと、Claude Code と同じ道具・エージェントの繰り返し・コンテキスト管理を、Python と TypeScript のプログラムから使える部品です。claude -p はターミナルから命令として呼ぶ入口で、SDK は自分のプログラムの中から関数として呼ぶ入口です。どちらも中身は同じ Claude Code で、公式は、SDK のパッケージに Claude Code 本体の実行ファイルが同梱され、SDK がそれを動かす作りだと書いています。
受講生に聞かれたら、「SDK は別のAIではありません。Claude Code を、自分のプログラムの部品として動かす入口です」と答えられます。
準備は、公式の手順で次のとおりです。
# Python(uv を使う場合)
uv init
uv add claude-agent-sdk
# TypeScript
npm install @anthropic-ai/claude-agent-sdk
Python の最小の例です(公式の形に沿って短くしたもの)。allowed_tools は「聞かずに使ってよい道具」の一覧で、道具を絞る指定ではありません。ここでは、使わせたくない道具を disallowed_tools で外しています。
import asyncio
from claude_agent_sdk import (
query, ClaudeAgentOptions,
AssistantMessage, ResultMessage,
)
async def main():
async for message in query(
prompt="このフォルダのファイル名を3つだけ挙げて",
options=ClaudeAgentOptions(
allowed_tools=["Glob"],
disallowed_tools=["Bash", "Edit", "Write"],
max_turns=4,
),
):
if isinstance(message, AssistantMessage):
for block in message.content:
if hasattr(block, "text"):
print("返事:", block.text)
elif hasattr(block, "name"):
print("道具:", block.name)
elif isinstance(message, ResultMessage):
print("終わり:", message.subtype)
asyncio.run(main())
TypeScript では、同じことをこう書きます(公式の形)。
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "このフォルダのファイル名を3つだけ挙げて",
options: {
allowedTools: ["Glob"],
disallowedTools: ["Bash", "Edit", "Write"],
maxTurns: 4
}
})) {
if (message.type === "result") {
console.log(`終わり: ${message.subtype}`);
}
}
コードは読めなくて構いません。見てほしいのは、3つの部品だけです。
query(...):エージェントの繰り返しを動かす入口prompt:頼みたいこと(claude -p の依頼文と同じ)options:許可する道具・外す道具・往復の上限など(claude -p のオプションと対応しています)async for は、途中経過を1つずつ受け取る書き方です。AIが考えて、道具を呼んで、結果を受け取る。その1歩ごとにメッセージが1つ流れてきて、async for が1つずつ取り出します。isinstance(message, AssistantMessage) は「このメッセージはAIの発言か」を確かめる書き方で、メッセージの種類ごとに処理を分けるために使います。
コードを書くのはAIに任せてよい。頼み方の例:「Agent SDK(Python)で、このフォルダの README を読んで3行で要約するプログラムを作って。公式のクイックスタートの形で、1行ずつ何をしているか説明して」
繰り返しの途中では、AIの発言(AssistantMessage)、道具の実行結果(UserMessage)などのメッセージが1歩ごとに流れ、最後に1回だけ ResultMessage(最終の返事・費用・会話ID)が来ます(公式)。
終わり方は ResultMessage の subtype で分かります。
| subtype | 意味 |
|---|---|
| success | 普通に終わった |
| error_max_turns | 往復の上限に届いた |
| error_max_budget_usd | 費用の上限に届いた |
| error_during_execution | 途中でエラーが起きた |
○ 深追いしない 手元の実測で気づいた点:allowed_tools=["Glob"] と指定しただけだと、AIは Bash(コマンド実行)も呼びました。allowed_tools は「聞かずに使ってよい道具の一覧」で、「使える道具をこれだけに絞る」ではないからです。公式も「一覧にない道具も使える。承認が要る呼び出しは許可モードに回る」と書いています。道具を絞る時は、disallowed_tools(Python)/disallowedTools(TypeScript)で外します。外した道具は、他のどの設定よりも優先して使えなくなります(公式)
○ 深追いしない 失敗で終わった時、query() は最後の結果を返したあとで例外を出します(公式)。プログラムを止めたくなければ、try で囲みます。try は「この範囲でエラーが出たら、止まらずに別の処理へ回す」と書くための構文です
最後に、料金の枠に関わる補足を短く置きます。認証とは「誰の名前で、どの料金の枠でAIを使うか」の確認です。
ANTHROPIC_API_KEY に入れます)は、使った量に応じた従量課金です。環境変数は、プログラムに渡す設定の名前つきの値ですclaude -p は、ANTHROPIC_API_KEY が環境にあると、いつでもそのキーを使います(公式の認証の優先順位)。サブスクのつもりが従量課金になる事故は、ここで起きます--bare を付けるとログイン情報(サブスク)を読まず、APIキーなどを使います。スクリプトやCIから使う長期トークンは claude setup-token で作れますが、--bare はこれも読みません自分のMacで自分の仕事を自動化するのは、公式が書く通常の使い方の延長です。他人に配る製品に組み込む場合や、会社の共用の境目は、契約や規約で決まるので、断定せず公式の最新の規約と契約を確認するよう伝えるのが安全です。
○ 受講生によく聞かれる質問:「無人で動かしたら、勝手に危ない操作をしませんか?」
答え方:許可の判定は無人でも同じ順番で働きます(No.13)。--allowedTools で最小限だけ許可し、聞かれる場面は断る設定にするのが基本です
○ 関係する単元:No.02 繰り返し/No.10 フック/No.11 MCP/No.13 許可/No.15 設定(機能ごとの強さの比較)
Agent SDK = Claude Code を自分のプログラムの部品にする入口。中身は同じ。allowed_tools は「聞かずに許可」で、絞るなら別の指定で外す。-p ではAPIキーがあれば必ずそちらが使われる。
問1 受講生に「Agent SDK で動くエージェントは、Claude Code と別のAIですか」と聞かれました。仕組みから見て、いちばん合う答えは?
問2 夜中に claude -p を自動で動かしたら、途中で止まって何も進みませんでした。聞かれても答える人がいない場面で、まず確認することは?
問3 Agent SDK で allowed_tools=["Glob"] とだけ指定しました。AIが Bash も呼べてしまうのはなぜ?
問4 サブスク(Max)のログインで動かしているつもりの claude -p が、なぜか従量課金で動いていました。本文から考えられる原因は?
出典:Claude Code 公式ドキュメント(2026年10月時点)「Run Claude Code programmatically」(https://code.claude.com/docs/en/headless)「CLI reference」(https://code.claude.com/docs/en/cli-reference)「How the agent loop works」(https://code.claude.com/docs/en/agent-sdk/agent-loop)「Agent SDK Python reference」(https://code.claude.com/docs/en/agent-sdk/python)「Agent SDK quickstart」(https://code.claude.com/docs/en/agent-sdk/quickstart)「Authentication」(https://code.claude.com/docs/en/authentication)/手元のMacで claude -p(JSON出力・json-schema・max-turns)と Agent SDK(Python)を実際に動かして確認(2026-10-13)