Prasyarat

  • Python 3.10+
  • claude-code-sdk dari PyPI
  • Node.js 18+
  • @anthropic-ai/claude-code dari NPM

Untuk melihat kode sumber Python SDK, lihat repo claude-code-sdk.

Untuk pengembangan interaktif, gunakan IPython: pip install ipython

Instalasi

Instal claude-code-sdk dari PyPI dan @anthropic-ai/claude-code dari NPM:

pip install claude-code-sdk
npm install -g @anthropic-ai/claude-code  # Dependensi yang diperlukan

(Opsional) Instal IPython untuk pengembangan interaktif:

pip install ipython

Mulai cepat

Buat agen pertama Anda:

# legal-agent.py
import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def main():
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Anda adalah asisten hukum. Identifikasi risiko dan sarankan perbaikan.",
            max_turns=2
        )
    ) as client:
        # Kirim kueri
        await client.query(
            "Tinjau klausul kontrak ini untuk masalah potensial: 'Pihak setuju untuk tanggung jawab tidak terbatas...'"
        )

        # Stream respons
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                # Cetak konten streaming saat tiba
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

if __name__ == "__main__":
    asyncio.run(main())

Simpan kode di atas sebagai legal-agent.py, lalu jalankan:

python legal-agent.py

Untuk notebook IPython/Jupyter, Anda dapat menjalankan kode langsung di sel:

await main()

Contoh Python di halaman ini menggunakan asyncio, tetapi Anda juga dapat menggunakan anyio.

Penggunaan dasar

Python SDK menyediakan dua antarmuka utama:

1. Kelas ClaudeSDKClient (direkomendasikan)

Terbaik untuk respons streaming, percakapan multi-turn, dan aplikasi interaktif:

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def main():
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Anda adalah insinyur performa",
            allowed_tools=["Bash", "Read", "WebSearch"],
            max_turns=5
        )
    ) as client:
        await client.query("Analisis performa sistem")

        # Stream respons
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

# Jalankan sebagai skrip
asyncio.run(main())

# Atau di IPython/Jupyter: await main()

2. Fungsi query

Untuk kueri sederhana, satu kali:

from claude_code_sdk import query, ClaudeCodeOptions

async for message in query(
    prompt="Analisis performa sistem",
    options=ClaudeCodeOptions(system_prompt="Anda adalah insinyur performa")
):
    if type(message).__name__ == "ResultMessage":
        print(message.result)

Opsi konfigurasi

Python SDK menerima semua argumen yang didukung oleh command line melalui kelas ClaudeCodeOptions.

Parameter ClaudeCodeOptions

from claude_code_sdk import ClaudeCodeOptions

options = ClaudeCodeOptions(
    # Konfigurasi inti
    system_prompt="Anda adalah asisten yang membantu",
    append_system_prompt="Instruksi sistem tambahan",
    max_turns=5,
    model="claude-3-5-sonnet-20241022",
    max_thinking_tokens=8000,
    
    # Manajemen alat
    allowed_tools=["Bash", "Read", "Write"],
    disallowed_tools=["WebSearch"],
    
    # Manajemen sesi
    continue_conversation=False,
    resume="session-uuid",
    
    # Lingkungan
    cwd="/path/to/working/directory",
    add_dirs=["/additional/context/dir"],
    settings="/path/to/settings.json",
    
    # Izin
    permission_mode="acceptEdits",  # "default", "acceptEdits", "plan", "bypassPermissions"
    permission_prompt_tool_name="mcp__approval_tool",
    
    # Integrasi MCP
    mcp_servers={
        "my_server": {
            "command": "npx",
            "args": ["-y", "@modelcontextprotocol/server-example"],
            "env": {"API_KEY": "your-key"}
        }
    },
    
    # Lanjutan
    extra_args={"--verbose": None, "--custom-flag": "value"}
)

Detail parameter

  • system_prompt: str | None - Prompt sistem kustom yang mendefinisikan peran agen
  • append_system_prompt: str | None - Teks tambahan yang ditambahkan ke prompt sistem
  • max_turns: int | None - Maksimum turn percakapan (tidak terbatas jika None)
  • model: str | None - Model Claude spesifik yang akan digunakan
  • max_thinking_tokens: int - Token maksimum untuk proses berpikir Claude (default: 8000)
  • allowed_tools: list[str] - Alat yang secara khusus diizinkan untuk digunakan
  • disallowed_tools: list[str] - Alat yang tidak boleh digunakan
  • continue_conversation: bool - Lanjutkan percakapan terbaru (default: False)
  • resume: str | None - UUID sesi untuk melanjutkan percakapan spesifik
  • cwd: str | Path | None - Direktori kerja untuk sesi
  • add_dirs: list[str | Path] - Direktori tambahan untuk disertakan dalam konteks
  • settings: str | None - Path ke file pengaturan atau string JSON pengaturan
  • permission_mode: str | None - Mode penanganan izin
  • permission_prompt_tool_name: str | None - Nama alat prompt izin kustom
  • mcp_servers: dict | str | Path - Konfigurasi server MCP
  • extra_args: dict[str, str | None] - Berikan flag CLI arbitrer ke Claude Code CLI yang mendasari

Mode izin

  • "default": CLI meminta untuk alat berbahaya (perilaku default)
  • "acceptEdits": Secara otomatis menerima edit file tanpa meminta
  • "plan": Mode Rencana - analisis tanpa membuat perubahan
  • "bypassPermissions": Izinkan semua alat tanpa meminta (gunakan dengan hati-hati)

Contoh konfigurasi lanjutan

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def advanced_agent():
    """Contoh yang menampilkan opsi konfigurasi lanjutan"""
    
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            # Direktori kerja kustom dan konteks tambahan
            cwd="/project/root",
            add_dirs=["/shared/libs", "/common/utils"],
            
            # Konfigurasi model dan berpikir
            model="claude-3-5-sonnet-20241022",
            max_thinking_tokens=12000,
            
            # Kontrol alat lanjutan
            allowed_tools=["Read", "Write", "Bash", "Grep"],
            disallowed_tools=["WebSearch", "Bash(rm*)"],
            
            # Pengaturan kustom dan args CLI
            settings='{"editor": "vim", "theme": "dark"}',
            extra_args={
                "--verbose": None,
                "--timeout": "300"
            }
        )
    ) as client:
        await client.query("Analisis struktur codebase")
        
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

asyncio.run(advanced_agent())

Pesan terstruktur dan input gambar

SDK mendukung passing pesan terstruktur dan input gambar:

from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async with ClaudeSDKClient() as client:
    # Pesan teks
    await client.query("Analisis kode ini untuk masalah keamanan")

    # Pesan dengan referensi gambar (gambar akan dibaca oleh alat Read Claude)
    await client.query("Jelaskan apa yang ditampilkan di screenshot.png")

    # Beberapa pesan berurutan
    messages = [
        "Pertama, analisis diagram arsitektur di diagram.png",
        "Sekarang sarankan perbaikan berdasarkan diagram",
        "Akhirnya, buat kode implementasi"
    ]

    for msg in messages:
        await client.query(msg)
        async for response in client.receive_response():
            # Proses setiap respons
            pass

# SDK menangani file gambar melalui alat Read bawaan Claude
# Format yang didukung: PNG, JPG, PDF, dan format umum lainnya

Percakapan multi-turn

Metode 1: Menggunakan ClaudeSDKClient untuk percakapan persisten

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions, query

# Metode 1: Menggunakan ClaudeSDKClient untuk percakapan persisten
async def multi_turn_conversation():
    async with ClaudeSDKClient() as client:
        # Kueri pertama
        await client.query("Mari refactor modul pembayaran")
        async for msg in client.receive_response():
            # Proses respons pertama
            pass

        # Lanjutkan di sesi yang sama
        await client.query("Sekarang tambahkan penanganan error yang komprehensif")
        async for msg in client.receive_response():
            # Proses kelanjutan
            pass

        # Konteks percakapan dipertahankan sepanjang waktu

# Metode 2: Menggunakan fungsi query dengan manajemen sesi
async def resume_session():
    # Lanjutkan percakapan terbaru
    async for message in query(
        prompt="Sekarang refactor ini untuk performa yang lebih baik",
        options=ClaudeCodeOptions(continue_conversation=True)
    ):
        if type(message).__name__ == "ResultMessage":
            print(message.result)

    # Lanjutkan sesi spesifik
    async for message in query(
        prompt="Perbarui tes",
        options=ClaudeCodeOptions(
            resume="550e8400-e29b-41d4-a716-446655440000",
            max_turns=3
        )
    ):
        if type(message).__name__ == "ResultMessage":
            print(message.result)

# Jalankan contoh
asyncio.run(multi_turn_conversation())

Prompt sistem kustom

Prompt sistem mendefinisikan peran, keahlian, dan perilaku agen Anda:

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def specialized_agents():
    # Agen respons insiden SRE dengan streaming
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Anda adalah ahli SRE. Diagnosis masalah secara sistematis dan berikan solusi yang dapat ditindaklanjuti.",
            max_turns=3
        )
    ) as sre_agent:
        await sre_agent.query("API down, investigasi")

        # Stream proses diagnostik
        async for message in sre_agent.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

    # Agen tinjauan hukum dengan prompt kustom
    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            append_system_prompt="Selalu sertakan penanganan error yang komprehensif dan unit test.",
            max_turns=2
        )
    ) as dev_agent:
        await dev_agent.query("Refactor fungsi ini")

        # Kumpulkan respons lengkap
        full_response = []
        async for message in dev_agent.receive_response():
            if type(message).__name__ == "ResultMessage":
                print(message.result)

asyncio.run(specialized_agents())

Alat kustom melalui MCP

Model Context Protocol (MCP) memungkinkan Anda memberikan agen Anda alat dan kemampuan kustom:

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def mcp_enabled_agent():
    # Agen hukum dengan akses dokumen dan streaming
    # Catatan: Konfigurasi server MCP Anda sesuai kebutuhan
    mcp_servers = {
        # Contoh konfigurasi - uncomment dan konfigurasi sesuai kebutuhan:
        # "docusign": {
        #     "command": "npx",
        #     "args": ["-y", "@modelcontextprotocol/server-docusign"],
        #     "env": {"API_KEY": "your-key"}
        # }
    }

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            mcp_servers=mcp_servers,
            allowed_tools=["mcp__docusign", "mcp__compliance_db"],
            system_prompt="Anda adalah pengacara korporat yang mengkhususkan diri dalam tinjauan kontrak.",
            max_turns=4
        )
    ) as client:
        await client.query("Tinjau kontrak ini untuk risiko kepatuhan")

        # Monitor penggunaan alat dan respons
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'type'):
                        if block.type == 'tool_use':
                            print(f"\n[Menggunakan alat: {block.name}]\n")
                        elif hasattr(block, 'text'):
                            print(block.text, end='', flush=True)
                    elif hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

            if type(message).__name__ == "ResultMessage":
                print(f"\n\nTinjauan selesai. Total biaya: ${message.total_cost_usd:.4f}")

asyncio.run(mcp_enabled_agent())

Alat prompt izin kustom

Implementasikan penanganan izin kustom untuk panggilan alat:

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def use_permission_prompt():
    """Contoh menggunakan alat prompt izin kustom"""

    # Konfigurasi server MCP
    mcp_servers = {
        # Contoh konfigurasi - uncomment dan konfigurasi sesuai kebutuhan:
        # "security": {
        #     "command": "npx",
        #     "args": ["-y", "@modelcontextprotocol/server-security"],
        #     "env": {"API_KEY": "your-key"}
        # }
    }

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            permission_prompt_tool_name="mcp__security__approval_prompt",  # Diubah dari permission_prompt_tool
            mcp_servers=mcp_servers,
            allowed_tools=["Read", "Grep"],
            disallowed_tools=["Bash(rm*)", "Write"],
            system_prompt="Anda adalah auditor keamanan"
        )
    ) as client:
        await client.query("Analisis dan perbaiki masalah keamanan")

        # Monitor penggunaan alat dan izin
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'type'):  # Ditambahkan pengecekan atribut 'type'
                        if block.type == 'tool_use':
                            print(f"[Alat: {block.name}] ", end='')
                    if hasattr(block, 'text'):
                        print(block.text, end='', flush=True)

            # Periksa penolakan izin dalam pesan error
            if type(message).__name__ == "ErrorMessage":
                if hasattr(message, 'error') and "Permission denied" in str(message.error):
                    print(f"\n⚠️ Izin ditolak: {message.error}")

# Contoh implementasi server MCP (Python)
# Ini akan ada di kode server MCP Anda
async def approval_prompt(tool_name: str, input: dict, tool_use_id: str = None):
    """Handler prompt izin kustom"""
    # Logika kustom Anda di sini
    if "allow" in str(input):
        return json.dumps({
            "behavior": "allow",
            "updatedInput": input
        })
    else:
        return json.dumps({
            "behavior": "deny",
            "message": f"Izin ditolak untuk {tool_name}"
        })

asyncio.run(use_permission_prompt())

Format output

Output teks dengan streaming

# Output teks default dengan streaming
async with ClaudeSDKClient() as client:
    await client.query("Jelaskan file src/components/Header.tsx")

    # Stream teks saat tiba
    async for message in client.receive_response():
        if hasattr(message, 'content'):
            for block in message.content:
                if hasattr(block, 'text'):
                    print(block.text, end='', flush=True)
                    # Output stream secara real-time: Ini adalah komponen React yang menampilkan...

Output JSON dengan metadata

# Kumpulkan semua pesan dengan metadata
async with ClaudeSDKClient() as client:
    await client.query("Bagaimana cara kerja lapisan data?")

    messages = []
    result_data = None

    async for message in client.receive_messages():
        messages.append(message)

        # Tangkap pesan hasil dengan metadata
        if type(message).__name__ == "ResultMessage":
            result_data = {
                "result": message.result,
                "cost": message.total_cost_usd,
                "duration": message.duration_ms,
                "num_turns": message.num_turns,
                "session_id": message.session_id
            }
            break

    print(result_data)

Format input

import asyncio
from claude_code_sdk import ClaudeSDKClient

async def process_inputs():
    async with ClaudeSDKClient() as client:
        # Input teks
        await client.query("Jelaskan kode ini")
        async for message in client.receive_response():
            # Proses respons streaming
            pass

        # Input gambar (Claude akan menggunakan alat Read secara otomatis)
        await client.query("Apa yang ada di diagram ini? screenshot.png")
        async for message in client.receive_response():
            # Proses analisis gambar
            pass

        # Beberapa input dengan konten campuran
        inputs = [
            "Analisis arsitektur di diagram.png",
            "Bandingkan dengan praktik terbaik",
            "Buat versi yang diperbaiki"
        ]

        for prompt in inputs:
            await client.query(prompt)
            async for message in client.receive_response():
                # Proses setiap respons
                pass

asyncio.run(process_inputs())

Contoh integrasi agen

Agen respons insiden SRE

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def investigate_incident(incident_description: str, severity: str = "medium"):
    """Agen respons insiden otomatis dengan streaming real-time"""

    # Konfigurasi server MCP untuk alat monitoring
    mcp_servers = {
        # Contoh konfigurasi - uncomment dan konfigurasi sesuai kebutuhan:
        # "datadog": {
        #     "command": "npx",
        #     "args": ["-y", "@modelcontextprotocol/server-datadog"],
        #     "env": {"API_KEY": "your-datadog-key", "APP_KEY": "your-app-key"}
        # }
    }

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Anda adalah ahli SRE. Diagnosis masalah secara sistematis dan berikan solusi yang dapat ditindaklanjuti.",
            max_turns=6,
            allowed_tools=["Bash", "Read", "WebSearch", "mcp__datadog"],
            mcp_servers=mcp_servers
        )
    ) as client:
        # Kirim detail insiden
        prompt = f"Insiden: {incident_description} (Tingkat keparahan: {severity})"
        print(f"🚨 Menginvestigasi: {prompt}\n")
        await client.query(prompt)

        # Stream proses investigasi
        investigation_log = []
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'type'):
                        if block.type == 'tool_use':
                            print(f"[{block.name}] ", end='')
                    if hasattr(block, 'text'):
                        text = block.text
                        print(text, end='', flush=True)
                        investigation_log.append(text)

            # Tangkap hasil akhir
            if type(message).__name__ == "ResultMessage":
                return {
                    'analysis': ''.join(investigation_log),
                    'cost': message.total_cost_usd,
                    'duration_ms': message.duration_ms
                }

# Penggunaan
result = await investigate_incident("Payment API mengembalikan error 500", "high")
print(f"\n\nInvestigasi selesai. Biaya: ${result['cost']:.4f}")

Tinjauan keamanan otomatis

import subprocess
import asyncio
import json
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def audit_pr(pr_number: int):
    """Agen audit keamanan untuk pull request dengan feedback streaming"""
    # Dapatkan diff PR
    pr_diff = subprocess.check_output(
        ["gh", "pr", "diff", str(pr_number)],
        text=True
    )

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Anda adalah insinyur keamanan. Tinjau PR ini untuk kerentanan, pola tidak aman, dan masalah kepatuhan.",
            max_turns=3,
            allowed_tools=["Read", "Grep", "WebSearch"]
        )
    ) as client:
        print(f"🔍 Mengaudit PR #{pr_number}\n")
        await client.query(pr_diff)

        findings = []
        async for message in client.receive_response():
            if hasattr(message, 'content'):
                for block in message.content:
                    if hasattr(block, 'text'):
                        # Stream temuan saat ditemukan
                        print(block.text, end='', flush=True)
                        findings.append(block.text)

            if type(message).__name__ == "ResultMessage":
                return {
                    'pr_number': pr_number,
                    'findings': ''.join(findings),
                    'metadata': {
                        'cost': message.total_cost_usd,
                        'duration': message.duration_ms,
                        'severity': 'high' if 'vulnerability' in ''.join(findings).lower() else 'medium'
                    }
                }

# Penggunaan
report = await audit_pr(123)
print(f"\n\nAudit selesai. Tingkat keparahan: {report['metadata']['severity']}")
print(json.dumps(report, indent=2))

Asisten hukum multi-turn

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

async def legal_review():
    """Tinjauan dokumen hukum dengan sesi persisten dan streaming"""

    async with ClaudeSDKClient(
        options=ClaudeCodeOptions(
            system_prompt="Anda adalah pengacara korporat. Berikan analisis hukum yang detail.",
            max_turns=2
        )
    ) as client:
        # Tinjauan multi-langkah dalam sesi yang sama
        steps = [
            "Tinjau contract.pdf untuk klausul tanggung jawab",
            "Periksa kepatuhan dengan persyaratan GDPR",
            "Buat ringkasan eksekutif risiko"
        ]

        review_results = []

        for step in steps:
            print(f"\n📋 {step}\n")
            await client.query(step)

            step_result = []
            async for message in client.receive_response():
                if hasattr(message, 'content'):
                    for block in message.content:
                        if hasattr(block, 'text'):
                            text = block.text
                            print(text, end='', flush=True)
                            step_result.append(text)

                if type(message).__name__ == "ResultMessage":
                    review_results.append({
                        'step': step,
                        'analysis': ''.join(step_result),
                        'cost': message.total_cost_usd
                    })

        # Ringkasan
        total_cost = sum(r['cost'] for r in review_results)
        print(f"\n\n✅ Tinjauan hukum selesai. Total biaya: ${total_cost:.4f}")
        return review_results

# Penggunaan
results = await legal_review()

Praktik terbaik khusus Python

Pola kunci

import asyncio
from claude_code_sdk import ClaudeSDKClient, ClaudeCodeOptions

# Selalu gunakan context manager
async with ClaudeSDKClient() as client:
    await client.query("Analisis kode ini")
    async for msg in client.receive_response():
        # Proses pesan streaming
        pass

# Jalankan beberapa agen secara bersamaan
async with ClaudeSDKClient() as reviewer, ClaudeSDKClient() as tester:
    await asyncio.gather(
        reviewer.query("Tinjau main.py"),
        tester.query("Tulis tes untuk main.py")
    )

# Penanganan error
from claude_code_sdk import CLINotFoundError, ProcessError

try:
    async with ClaudeSDKClient() as client:
        # Kode Anda di sini
        pass
except CLINotFoundError:
    print("Instal CLI: npm install -g @anthropic-ai/claude-code")
except ProcessError as e:
    print(f"Error proses: {e}")

# Kumpulkan respons lengkap dengan metadata
async def get_response(client, prompt):
    await client.query(prompt)
    text = []
    async for msg in client.receive_response():
        if hasattr(msg, 'content'):
            for block in msg.content:
                if hasattr(block, 'text'):
                    text.append(block.text)
        if type(msg).__name__ == "ResultMessage":
            return {'text': ''.join(text), 'cost': msg.total_cost_usd}

Tips IPython/Jupyter

# Di Jupyter, gunakan await langsung di sel
client = ClaudeSDKClient()
await client.connect()
await client.query("Analisis data.csv")
async for msg in client.receive_response():
    print(msg)
await client.disconnect()

# Buat fungsi helper yang dapat digunakan kembali
async def stream_print(client, prompt):
    await client.query(prompt)
    async for msg in client.receive_response():
        if hasattr(msg, 'content'):
            for block in msg.content:
                if hasattr(block, 'text'):
                    print(block.text, end='', flush=True)

Sumber daya terkait