5 ファイル変更+35-27
この更新の概要
Python版SDKにおいて、ClaudeAgentOptionsクラスを使用した型安全なオプション指定方法が導入されました。メッセージの判定ロジックが文字列比較からisinstanceを用いたクラス判定やsubtypeのチェックに変更され、より堅牢な実装方法が示されています。TypeScript版ではSDKUserMessage型の明示的な指定やsession_idのオプショナル化が行われ、型の定義が強化されました。全体として、SDKの利用における型定義の厳密化とメッセージ処理の精度向上を目的とした修正が行われています。
Pythonでのプラグイン設定において、辞書形式の代わりにClaudeAgentOptionsクラスを使用する記述に変更され、SystemMessageクラスによる型判定が導入されました。
@@ -44,17 +44,17 @@ for await (const message of query({
```python Python theme={null}
import asyncio
from claude_agent_sdk import query
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
async for message in query(
prompt="Hello",
options={
"plugins": [
options=ClaudeAgentOptions(
plugins=[
{"type": "local", "path": "./my-plugin"},
{"type": "local", "path": "/absolute/path/to/another-plugin"},
]
},
),
):
# Plugin commands, agents, and other features are now available
pass
@@ -98,13 +98,16 @@ for await (const message of query({
```python Python theme={null}
import asyncio
from claude_agent_sdk import query
from claude_agent_sdk import query, ClaudeAgentOptions, SystemMessage
async def main():
async for message in query(
prompt="Hello", options={"plugins": [{"type": "local", "path": "./my-plugin"}]}
prompt="Hello",
options=ClaudeAgentOptions(
plugins=[{"type": "local", "path": "./my-plugin"}]
),
):
if message.type == "system" and message.subtype == "init":
if isinstance(message, SystemMessage) and message.subtype == "init":
# Check loaded plugins
print("Plugins:", message.data.get("plugins"))
# Example: [{"name": "my-plugin", "path": "./my-plugin"}]
@@ -139,13 +142,15 @@ for await (const message of query({
```python Python theme={null}
import asyncio
from claude_agent_sdk import query, AssistantMessage, TextBlock
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock
async def main():
# Load a plugin with a custom /greet skill
async for message in query(
prompt="/demo-plugin:greet", # Use plugin skill with namespace
options={"plugins": [{"type": "local", "path": "./plugins/demo-plugin"}]},
options=ClaudeAgentOptions(
plugins=[{"type": "local", "path": "./plugins/demo-plugin"}]
),
):
# Claude executes the custom greeting skill from the plugin
if isinstance(message, AssistantMessage):
@@ -201,6 +206,7 @@ import anyio
from claude_agent_sdk import (
AssistantMessage,
ClaudeAgentOptions,
SystemMessage,
TextBlock,
query,
)
@@ -219,7 +225,7 @@ async def run_with_plugin():
async for message in query(
prompt="What custom commands do you have available?", options=options
):
if message.type == "system" and message.subtype == "init":
if isinstance(message, SystemMessage) and message.subtype == "init":
print(f"Loaded plugins: {message.data.get('plugins')}")
print(f"Available commands: {message.data.get('slash_commands')}")
@@ -52,7 +52,7 @@ for await (const message of query({
prompt: "/compact",
options: { maxTurns: 1 }
})) {
if (message.type === "result") {
if (message.type === "result" && message.subtype === "success") {
console.log("Command executed:", message.result);
}
}
@@ -243,7 +243,7 @@ for await (const message of query({
options: { maxTurns: 5 }
})) {
// Command will process with $1="123" and $2="high"
if (message.type === "result") {
if (message.type === "result" && message.subtype === "success") {
console.log("Issue fixed:", message.result);
}
}
TypeScriptでのメッセージ生成においてSDKUserMessage型が明示され、メッセージオブジェクトにparent_tool_use_idプロパティが追加されました。
@@ -77,17 +77,18 @@ Maintain conversation context across multiple turns naturally
### Implementation Example
```typescript TypeScript theme={null}
import { query } from "@anthropic-ai/claude-agent-sdk";
import { query, type SDKUserMessage } from "@anthropic-ai/claude-agent-sdk";
import { readFile } from "fs/promises";
async function* generateMessages() {
async function* generateMessages(): AsyncGenerator<SDKUserMessage> {
// First message
yield {
type: "user" as const,
type: "user",
message: {
role: "user" as const,
role: "user",
content: "Analyze this codebase for security issues"
}
},
parent_tool_use_id: null
};
// Wait for conditions or user input
@@ -95,9 +96,9 @@ async function* generateMessages() {
// Follow-up with image
yield {
type: "user" as const,
type: "user",
message: {
role: "user" as const,
role: "user",
content: [
{
type: "text",
@@ -112,7 +113,8 @@ async function* generateMessages() {
}
}
]
}
},
parent_tool_use_id: null
};
}
@@ -124,7 +126,7 @@ for await (const message of query({
allowedTools: ["Read", "Grep"]
}
})) {
if (message.type === "result") {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
@@ -228,7 +230,7 @@ for await (const message of query({
allowedTools: ["Read", "Grep"]
}
})) {
if (message.type === "result") {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
@@ -241,7 +243,7 @@ for await (const message of query({
maxTurns: 1
}
})) {
if (message.type === "result") {
if (message.type === "result" && message.subtype === "success") {
console.log(message.result);
}
}
ツール使用の判定にToolUseBlockクラスを用いたisinstance判定が導入され、メッセージのフィルタリング条件がより厳密な型チェックに変更されました。
@@ -294,7 +294,7 @@ The message structure differs between SDKs. In Python, content blocks are access
```python Python theme={null}
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition
from claude_agent_sdk import query, ClaudeAgentOptions, AgentDefinition, ToolUseBlock
async def main():
async for message in query(
@@ -314,7 +314,7 @@ async def main():
# versions emitted "Task", current versions emit "Agent".
if hasattr(message, "content") and message.content:
for block in message.content:
if getattr(block, "type", None) == "tool_use" and block.name in (
if isinstance(block, ToolUseBlock) and block.name in (
"Task",
"Agent",
):
@@ -389,7 +389,7 @@ import { query, type SDKMessage } from "@anthropic-ai/claude-agent-sdk";
// Helper to extract agentId from message content
// Stringify to avoid traversing different block types (TextBlock, ToolResultBlock, etc.)
function extractAgentId(message: SDKMessage): string | undefined {
if (!("message" in message)) return undefined;
if (message.type !== "assistant" && message.type !== "user") return undefined;
// Stringify the content so we can search it without traversing nested blocks
const content = JSON.stringify(message.message.content);
const match = content.match(/agentId:\s*([a-f0-9-]+)/);
@@ -941,7 +941,7 @@ User input message.
type SDKUserMessage = {
type: "user";
uuid?: UUID;
session_id: string;
session_id?: string;
message: MessageParam; // From Anthropic SDK
parent_tool_use_id: string | null;
isSynthetic?: boolean;