Lewati ke konten utama

Tutorial Claude Agent SDK: Buat Agen dengan Claude Sonnet 4.5

Pelajari cara kerja Claude Agent SDK dengan membangun tiga proyek, dari one-shot hingga agen dengan tool khusus.
Ā· 9 mnt Baca

Jelajahi bersama AI

Anthropic telah merilis Claude Sonnet 4.5, model coding mutakhir yang sudah memuncaki berbagai tolok ukur dan peringkat industri. Yang membuat rilis ini semakin menarik adalah integrasinya yang mulus di berbagai tool dan framework. Mulai dari ekstensi VS Code dan fitur penyuntingan konteks hingga memory tool, eksekusi kode, dan pembuatan file (spreadsheet, slide, dokumen). Bahkan meluas ke pengalaman baru lewat Claude for Chrome dan Imagine with Claude.

Namun sorotan utama rilis ini adalah Claude Agent SDK yang benar-benar baru, dibangun di atas Claude Code. SDK ini memperkenalkan kerangka kerja agentic yang kuat, memungkinkan pengembang membangun, menyesuaikan, dan memperluas kapabilitas Claude dengan cara-cara yang benar-benar baru.

Dalam tutorial ini, kita akan mengeksplorasi hal-hal baru di Claude 4.5, mempraktikkan Claude Agent SDK, menyiapkannya secara lokal, dan membangun tiga proyek sederhana untuk melihat potensinya secara langsung.

Apa yang baru di Claude 4.5?

Claude Sonnet 4.5 menghadirkan peningkatan kapabilitas besar. Ini adalah model coding terbaik di dunia, paling andal untuk membangun agen kompleks, dan paling unggul untuk tugas penggunaan komputer, dengan peningkatan signifikan dalam penalaran dan matematika. Model ini tercatat sebagai yang terdepan pada tolok ukur SWE-bench Verified dan teramati mampu mempertahankan fokus selama lebih dari 30 jam pada tugas kompleks multi-langkah.Ā 

Di papan peringkat OSWorld, performanya meningkat menjadi 61,4%, naik dari 42,2% hanya empat bulan lalu. Para ahli di bidang keuangan, hukum, kedokteran, dan STEM melaporkan peningkatan nyata dalam pengetahuan domain dan penalaran.

Sumber: Introducing Claude Sonnet 4.5 \ Anthropic

Selain itu, ini adalah model frontier paling selaras dari Anthropic hingga saat ini, menunjukkan penurunan sikofansi, penipuan, perilaku mencari kekuasaan, dan dorongan menuju delusi. Pertahanannya terhadap injeksi prompt juga diperkuat. Dirilis dengan pengamanan ASL-3, classifier yang ditingkatkan bertujuan menyaring konten berisiko tinggi sambil secara signifikan mengurangi positif palsu dibanding rilis sebelumnya. Kami juga melihat mode yang lebih kecil, yang dapat Anda baca dalam panduan Claude Haiku 4.5.

Memahami Claude Agent SDK

Claude Agent SDK, sebelumnya dikenal sebagai Claude Code SDK, menyediakan seperangkat alat yang dirancang untuk membantu Anda membangun agen andal serbaguna menggunakan kerangka kerja yang sama dengan yang menjalankan Claude Code.Ā 

Prinsip intinya sederhana: beri Claude akses ke komputer. Dengan akses terminal dan sistem berkas, agen dapat mencari, menulis, mengeksekusi, dan mengiterasi kode layaknya pengembang. Kapabilitas ini melampaui coding—mencakup riset mendalam, pembuatan video, pencatatan, analisis data, dan lainnya.Ā 

Claude Agent SDK merancang loop agen terstruktur dengan empat langkah kunci: mengumpulkan konteks, mengambil tindakan, memverifikasi kerja, dan mengulang.

Dalam praktiknya, mulai dengan pencarian agentic untuk konteks dan lapisi dengan pencarian semantik saat Anda membutuhkan kecepatan. Tindakan sebaiknya berfokus pada tool bernilai sinyal tinggi, skrip bash, dan integrasi dengan layanan eksternal melalui Model Context Protocol.Ā 

Verifikasi menggabungkan pemeriksaan berbasis aturan, umpan balik visual, dan bantuan LLM opsional. Iterasi berkelanjutan direkomendasikan untuk memoles performa, memperluas tool, dan meningkatkan kapabilitas pencarian seiring berkembangnya fitur.

Fitur Utama:

  1. SDK: TypeScript dan Python untuk backend web/Node.js dan data science, dengan konsep bersama sehingga tim dapat memakai ulang pola lintas stack.
  2. Mode: Streaming untuk UX interaktif berlatensi rendah dan single-shot untuk proses batch atau deterministik—pilih per tugas untuk menyeimbangkan kecepatan dan kontrol.
  3. Manajemen konteks: Pemadatan otomatis dan kontrol konteks jangka panjang untuk mencegah overflow dan menjaga agen tetap pada jalurnya selama sesi panjang.
  4. Tooling: Operasi file bawaan, eksekusi kode, dan pencarian web, plus kemampuan diperluas untuk tool eksternal dan data via MCP.
  5. Perizinan: Kontrol kapabilitas terperinci (mis., allow/deny per tool dan mode kebijakan) untuk membatasi apa yang bisa dilakukan agen di produksi.
  6. Siap produksi: Penanganan error bawaan, manajemen sesi, dan monitoring sehingga Anda dapat menerapkan agen andal dengan observabilitas sejak hari pertama.
  7. Integrasi Claude: Caching prompt otomatis dan optimasi performa untuk mengurangi latensi dan biaya sambil meningkatkan throughput.
  8. Autentikasi: Gunakan kunci API Claude atau rute melalui penyedia seperti Amazon Bedrock dan Google Vertex AI agar sesuai dengan lingkungan deployment Anda.
  9. System prompt: Tetapkan peran, keahlian, dan guardrail untuk membentuk perilaku agen secara konsisten di berbagai tugas dan sesi.
  10. Integrasi (MCP): Sambungkan tool kustom, database, dan API melalui Model Context Protocol terbuka, standar yang didukung Anthropic dengan SDK TypeScript resmi dan ekosistem yang berkembang.

Mulai Menggunakan Claude Agent SDK di Python

Sebelum mulai membangun proyek apa pun, Anda perlu menyiapkan beberapa prasyarat, memasang Claude Code CLI, dan Claude Agent SDK.

Prasyarat

  • Pastikan Anda menggunakan Python versi 3.10 atau lebih tinggi.Ā 
  • Untuk menggunakan Claude Code CLI secara efektif, Anda juga perlu memasang Node.js versi 18 atau lebih tinggi dan paket NPM.

Pasang Claude Code CLI

Untuk Windows:Ā 

Buka PowerShell dan jalankan perintah berikut untuk mengunduh dan memasang Claude Code:

irm https://claude.ai/install.ps1 | iex

Setelah instalasi, tambahkan C:\Users\<user>\.local\bin ke PATH sistem Anda. Mulai ulang PowerShell, dan Anda akan melihat Claude berjalan.

Untuk platform lain:

Jika Anda telah memasang Node.js dan NPM, coba jalankan perintah berikut di terminal untuk memasang Claude Code:

npm i -g @anthropic-ai/claude-code

Ikuti instruksi untuk menyiapkan variabel lingkungan agar Anda bisa mengakses Claude Code hanya dengan mengetik ā€œclaudeā€ di terminal.

Menyiapkan Claude Code

Setelah memasang Claude Code, buka dengan mengetik ā€œclaudeā€ di terminal dan masuk. Jika Anda memiliki paket Claude Pro atau Max, pilih ā€œLog in with your subscription accountā€ agar penggunaan ditagihkan ke paket Anda.

Jika Anda lebih suka pay-as-you-go, autentikasi dengan kunci API; penagihan akan melalui Anthropic Console.Ā 

Terakhir, atur tema dan preferensi antarmuka/CLI agar sesuai alur kerja Anda sejak hari pertama.

Saya menyiapkan Claude Code dengan kunci API. Anda dapat melihat konfigurasinya di sini:

Claude Code set up

Pasang Claude Agent SDK

Pastikan Python terpasang, lalu buka terminal Anda. Untuk memasang Claude Agent SDK, jalankan:

pip install claude-agent-sdk

Catatan: Jika Anda menemui CLINotFoundError, pastikan Anda telah memasang CLI di atas dan Claude sudah termasuk dalam PATH Anda.

Membangun Proyek dengan Claude Agent SDK dan Claude Sonnet 4.5

Sekarang kita akan membangun tiga proyek sederhana menggunakan Claude Agent SDK sebagai kerangka, Claude Code untuk tool dan penggunaan komputer, serta Claude Sonnet 4.5 sebagai model AI kita.

  1. One-shot Blog Outline: Kueri one-shot sederhana yang menunjukkan penggunaan dasar Claude Agent SDK tanpa tool.
  2. InspireBot CLI: Proyek ini menggabungkan kapabilitas pencarian web dengan tool fallback kustom untuk kutipan motivasi.
  3. Aplikasi Multi-Tool NoteSmith: Aplikasi catatan komprehensif dengan banyak tool, hook keamanan, dan pelacakan penggunaan.

Seluruh kode sumber tersedia di repositori GitHub: kingabzpro/claude-agent-projects

1. One-shot blog outline

Pada proyek ini, kita menggunakan fungsi query() milik SDK dengan Claude Sonnet 4.5 untuk membuat outline blog. Ini adalah kueri one-shot yang lugas dan menampilkan penggunaan dasar Claude Agent SDK tanpa tool apa pun.

Kodenya terdiri dari:Ā 

  1. Streaming asinkron: Menggunakan asyncio dengan iterator async query() dari SDK untuk output non-blocking per token.
  2. Prompt & opsi: Mendefinisikan PROMPT outline blog dan mengonfigurasi model/persona melalui ClaudeAgentOptions.
  3. Alur pesan bertipe: Mengiterasi pesan; mengekstrak hanya konten AssistantMessage → TextBlock.
  4. Output waktu nyata: Mencetak teks saat tiba (end="") untuk tampilan konsol streaming yang rapi.
  5. Penanganan hasil: Mengabaikan ResultMessage, membiarkan stream selesai secara alami.
  6. Entry point: Menjalankan semuanya dengan asyncio.run(main()) saat skrip dieksekusi.
  7. Dapat disesuaikan & minimal: Mudah mengganti model/prompt; skrip ringan, ideal untuk demo atau pipeline.

oneshot_outline.py:

import asyncio
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    AssistantMessage,
    TextBlock,
    ResultMessage,
)

PROMPT = """Create a crisp markdown outline (H2/H3 bullets) for a 500-word blog post:
Title: Why Sovereign AI Compute Matters in 2026
Audience: CTOs and Heads of AI
Tone: pragmatic, non-hype
Include: 3 buyer pains, 3 evaluation criteria, 1 closing CTA
"""

async def main():
    options = ClaudeAgentOptions(
        model="sonnet", 
        system_prompt="You are a precise technical copy strategist."
    )

    async for msg in query(prompt=PROMPT, options=options):
        if isinstance(msg, AssistantMessage):
            for block in msg.content:
                if isinstance(block, TextBlock):
                    print(block.text, end="")  # only the outline
        elif isinstance(msg, ResultMessage):
            pass  # let the iterator end naturally

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

Kita akan menjalankan skrip dan kemudian menyimpan output sebagai file markdown.Ā 

python oneshot_outline.py > outline.md 

Anda dapat membuka file markdown dan melihat bahwa naskah teknisnya dibuat dengan baik.Ā 

Claude Agent SDK Blog Outline

Anda dapat kembali ke dasbor di https://console.anthropic.com/usage untuk memeriksa penggunaan Anda. Seperti yang terlihat, model yang digunakan adalah Claude Sonnet 4.5.

Claude Agent SDK Usage

2. InspireBot CLI

Pada proyek ini, kita membangun generator motivasi yang ramah terminal dan men-stream kutipan menggunakan Claude Sonnet 4.5. Ia mencoba WebSearch terlebih dahulu, lalu melakukan fallback ke tool inspire_me kustom yang mengembalikan kutipan acak.

Kodenya terdiri dari:

  • Tool fallback kustom: Mendefinisikan inspire_me dengan kutipan motivasi preset, didaftarkan melalui create_sdk_mcp_server.
  • Helper CLI: is_tty, typewrite, bold, faint menambahkan animasi mesin tik dan output bergaya di terminal.
  • Prompt & opsi: Dikonfigurasi dengan ClaudeAgentOptions, mengizinkan tool (WebSearch + inspire_me) dan persona sistem ā€œInspireBot.ā€
  • Panggilan tool streaming: Mengiterasi pesan, menampilkan penggunaan tool (ToolUseBlock), hasil (ToolResultBlock), dan output akhir (TextBlock).
  • Logika fallback: Jika tidak ada output yang dapat digunakan, default ke kutipan lokal acak.
  • UX interaktif: Menampilkan input/hasil tool secara streaming, lalu menganimasikan kalimat inspirasi akhir dengan efek mesin tik.

inspire_web.py:

import sys
import json
import asyncio
import random
import time
from typing import Any

from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    tool,
    create_sdk_mcp_server,
    AssistantMessage,
    TextBlock,
    ToolUseBlock,
    ToolResultBlock,
    ResultMessage,
)

# -------------------------
# Custom fallback tool
# -------------------------
QUOTES = [
    "Dream big, start small -- but start.",
    "Stay curious, stay humble, keep building.",
    "Every expert was once a beginner.",
    "Small wins stack into big victories.",
    "Consistency beats intensity when intensity is inconsistent.",
]

@tool("inspire_me", "Return a random motivational quote", {})
async def inspire_me(_: dict) -> dict:
    return {"content": [{"type": "text", "text": random.choice(QUOTES)}]}

UTILS = create_sdk_mcp_server("inspire_util", "1.0.0", [inspire_me])

# -------------------------
# Tiny terminal helpers
# -------------------------
def is_tty() -> bool:
    try:
        return sys.stdout.isatty()
    except Exception:
        return False

def typewrite(text: str, delay: float = 0.02) -> None:
    """Print with a typewriter effect if TTY; otherwise plain print."""
    if not is_tty():
        print(text)
        return
    for ch in text:
        print(ch, end="", flush=True)
        time.sleep(delay)
    print()

def faint(s: str) -> str:
    """Dim text if terminal supports ANSI."""
    return s if not is_tty() else f"\033[2m{s}\033[0m"

def bold(s: str) -> str:
    return s if not is_tty() else f"\033[1m{s}\033[0m"

# -------------------------
# Main
# -------------------------
async def main():
    topic = "engineering focus" if len(sys.argv) < 2 else " ".join(sys.argv[1:])

    options = ClaudeAgentOptions(
        model="sonnet",  # switch to "sonnet-4.5" if your CLI lists it
        system_prompt=(
            "You are InspireBot.\n"
            "- First, try WebSearch to find a short, uplifting quote relevant to the user's topic.\n"
            "- If WebSearch is unhelpful or no clear quote is found, call the custom 'inspire_me' tool.\n"
            "- Output ONE short line only. No preface, no commentary, <= 120 characters."
        ),
        allowed_tools=[
            "WebSearch",
            "mcp__inspire_util__inspire_me",
        ],
        mcp_servers={"inspire_util": UTILS},
    )

    prompt = (
        "Find a short, uplifting quote for today's inspiration. "
        f"Topic: {topic}. Prefer something crisp and modern.\n"
        "If search yields multiple options, pick the best single line."
    )

    final_line_parts: list[str] = []

    if is_tty():
        print(bold("🌐 InspireBot (WebSearch + fallback tool)"))
        print(faint("Tip: pass a custom topic:  python inspire_web_animated.py \"women in leadership\""))
        print()

    async for message in query(prompt=prompt, options=options):
        # Stream assistant messages for tool usage + final text
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, ToolUseBlock):
                    tool_name = block.name
                    tool_input = block.input or {}
                    print(f"{bold('šŸ› ļø  Tool used:')} {tool_name}")
                    print(f"{faint('   input:')} {json.dumps(tool_input, ensure_ascii=False)}")
                elif isinstance(block, ToolResultBlock):
                    # Show summarized tool result text if present
                    shown = False
                    if isinstance(block.content, list):
                        for part in block.content:
                            if isinstance(part, dict) and part.get("type") == "text":
                                text = (part.get("text") or "").strip()
                                if text:
                                    preview = text if len(text) <= 200 else (text[:197] + "...")
                                    print(f"{faint('   result:')} {preview}")
                                    shown = True
                                    break
                    if not shown:
                        print(f"{faint('   result:')} (no textual content)")
                elif isinstance(block, TextBlock):
                    # This should be the final "inspiration" line content
                    final_line_parts.append(block.text)

        elif isinstance(message, ResultMessage):
            # allow the iterator to finish naturally (no break)
            pass

    final_line = " ".join(part.strip() for part in final_line_parts).strip()
    if not final_line:
        final_line = random.choice(QUOTES)  # ultimate fallback, just in case

    # Animate the final line (typewriter), or plain if not a TTY
    typewrite(final_line, delay=0.02)

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

Kita akan menjalankan skrip dengan topik default menggunakan perintah berikut:Ā Ā 

python inspire_web.py

Seperti terlihat, ia menampilkan tool yang digunakan, input untuk tool tersebut, lalu mengeluarkan kutipan motivasi.Ā Ā 

Mari berikan skrip Python dengan topik kustom:Ā Ā 

python inspire_web.py "Sadness and Love"

Ini mengembalikan kutipan motivasi yang menyertakan kata kunci "love" dan "sadness."

3. Aplikasi multi-tool NoteSmith

Pada proyek ini, kita membangun asisten riset multi-tool yang menyimpan dan mencari catatan secara lokal, meringkas halaman web, dan men-stream hasil dengan Claude Sonnet 4.5. Ia menggabungkan tool MCP kustom, tool bawaan, dan safety hook untuk pengalaman CLI yang lebih kaya.

Kodenya terdiri dari:

  • Penyimpanan lokal: Menyimpan catatan ke disk dengan stempel waktu; mendukung pencarian tidak peka huruf besar-kecil menggunakan logika grep sederhana.
  • Tool MCP kustom: save_note (menyimpan teks) dan find_note (mencari catatan), didaftarkan dengan create_sdk_mcp_server.
  • Safety hook: block_dangerous_bash menolak perintah shell berbahaya (mis., rm -rf /) sebelum eksekusi tool.
  • System prompt & perintah: Mendefinisikan /summarize, /note, /find, /help, /exit; prompt mengarahkan penggunaan tool (WebFetch, save_note, find_note).
  • Interaksi streaming: Menggunakan ClaudeSDKClient untuk menangani AssistantMessage, ToolUseBlock, ToolResultBlock, mencetak teks dan hasil tool secara waktu nyata.
  • Pelacakan penggunaan: Mencetak footer dengan nama model, token, dan biaya ke stderr sambil menjaga output utama tetap bersih.
  • Antarmuka chat: Bekerja seperti REPL ringan tempat Anda mengetik perintah (/note, /find, /summarize) dan mendapat respons instan, terasa seperti mengobrol dengan asisten.

note_smith.py:

import sys
import json
import asyncio
from datetime import datetime
from pathlib import Path
from typing import Any

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    AssistantMessage,
    TextBlock,
    ToolUseBlock,
    ToolResultBlock,
    ResultMessage,
    tool,
    create_sdk_mcp_server,
    HookMatcher,
    HookContext,
)

# ----------------------------
# Storage (simple local notes)
# ----------------------------

NOTES_DIR = Path(__file__).parent / "notes"
NOTES_DIR.mkdir(exist_ok=True)

def _ts() -> str:
    return datetime.now().strftime("%Y-%m-%d_%H-%M-%S")

def save_note_to_disk(text: str) -> str:
    path = NOTES_DIR / f"note_{_ts()}.txt"
    path.write_text(text.strip() + "\n", encoding="utf-8")
    return str(path)

def grep_notes(pattern: str) -> list[str]:
    pat = pattern.lower()
    out: list[str] = []
    for p in NOTES_DIR.glob("*.txt"):
        for i, line in enumerate(p.read_text(encoding="utf-8").splitlines(), start=1):
            if pat in line.lower():
                out.append(f"{p.name}:{i}: {line}")
    return out

# ----------------------------
# Custom MCP tools
# ----------------------------

@tool("save_note", "Save a short note to local disk", {"text": str})
async def save_note(args: dict[str, Any]) -> dict[str, Any]:
    path = save_note_to_disk(args["text"])
    return {"content": [{"type": "text", "text": f"Saved note → {path}"}]}

@tool("find_note", "Find notes containing a pattern (case-insensitive)", {"pattern": str})
async def find_note(args: dict[str, Any]) -> dict[str, Any]:
    hits = grep_notes(args["pattern"])
    body = "\n".join(hits) if hits else "No matches."
    return {"content": [{"type": "text", "text": body}]}

UTILS_SERVER = create_sdk_mcp_server(
    name="notes_util",
    version="1.0.0",
    tools=[save_note, find_note],
)

# ----------------------------
# Optional safety hook (Bash)
# ----------------------------

async def block_dangerous_bash(
    input_data: dict[str, Any],
    tool_use_id: str | None,
    context: HookContext
):
    if input_data.get("tool_name") == "Bash":
        cmd = str(input_data.get("tool_input", {}).get("command", "")).strip().lower()
        if "rm -rf /" in cmd or "format c:" in cmd:
            return {
                "hookSpecificOutput": {
                    "hookEventName": "PreToolUse",
                    "permissionDecision": "deny",
                    "permissionDecisionReason": "Dangerous command blocked"
                }
            }
    return {}

# ----------------------------
# Prompts & UI
# ----------------------------

SYSTEM_PROMPT = """You are NoteSmith, a concise research assistant.
- Prefer bullet answers with crisp takeaways.
- When the user asks to /summarize <url>, use WebFetch to retrieve and then summarize 5 key points + a 1-line TL;DR.
- When the user types /note <text>, call the custom save_note tool.
- When the user types /find <pattern>, call the custom find_note tool.
- Keep answers short unless asked to expand.
"""

HELP = """Commands:
  /summarize <url>      Summarize a webpage (WebFetch)
  /note <text>          Save a note locally
  /find <pattern>       Search saved notes
  /help                 Show this help
  /exit                 Quit
"""

# Use the broadest model label for compatibility; switch to "sonnet-4.5" if your CLI lists it.
MODEL = "sonnet"

# ----------------------------
# Main app
# ----------------------------

async def main():
    options = ClaudeAgentOptions(
        model=MODEL,
        system_prompt=SYSTEM_PROMPT,
        permission_mode="acceptEdits",
        allowed_tools=[
            # Built-ins (Claude may use these if relevant)
            "WebFetch", "Read", "Write", "Grep", "Glob",
            # Our MCP tools (SDK prefixes mcp__<alias>__<toolname>)
            "mcp__utils__save_note",
            "mcp__utils__find_note",
        ],
        mcp_servers={"utils": UTILS_SERVER},
        hooks={"PreToolUse": [HookMatcher(hooks=[block_dangerous_bash])]},
        setting_sources=None,  # no filesystem settings; everything is programmatic
    )

    print("šŸ’” NoteSmith (Claude Sonnet)\n")
    print(HELP)

    async with ClaudeSDKClient(options=options) as client:
        while True:
            user = input("\nYou: ").strip()
            if not user:
                continue
            if user.lower() in {"/exit", "exit", "quit"}:
                print("Bye!")
                break
            if user.lower() in {"/help", "help"}:
                print(HELP)
                continue

            # Lightweight command parsing (the system prompt also guides tool usage)
            if user.startswith("/summarize "):
                url = user.split(" ", 1)[1].strip()
                prompt = f"Summarize this URL using WebFetch and return 5 bullets + TL;DR:\n{url}"
            elif user.startswith("/note "):
                text = user.split(" ", 1)[1]
                prompt = f'Please call tool save_note with text="{text}"'
            elif user.startswith("/find "):
                patt = user.split(" ", 1)[1]
                prompt = f'Please call tool find_note with pattern="{patt}"'
            else:
                prompt = user

            await client.query(prompt)

            # -------- Response streaming with footer to STDERR --------
            model_used = None
            usage = None
            cost = None

            async for message in client.receive_response():
                if isinstance(message, AssistantMessage):
                    if model_used is None:
                        model_used = message.model  # e.g., "sonnet" or "sonnet-4.5"
                    for block in message.content:
                        if isinstance(block, TextBlock):
                            print(block.text, end="", flush=True)  # stdout
                        elif isinstance(block, ToolUseBlock):
                            print(f"\nšŸ› ļø  Using tool: {block.name} with input: {json.dumps(block.input)}")
                        elif isinstance(block, ToolResultBlock):
                            if isinstance(block.content, list):
                                for part in block.content:
                                    if isinstance(part, dict) and part.get("type") == "text":
                                        print(f"\nšŸ”Ž Tool says: {part.get('text')}")
                elif isinstance(message, ResultMessage):
                    usage = message.usage or {}
                    cost = message.total_cost_usd
                    # Do not break early; let stream end naturally

            # Footer (model + tokens + cost) → STDERR so normal output stays clean
            def _token_summary(u: dict) -> str:
                total = u.get("total_tokens")
                if total is None:
                    it, ot = u.get("input_tokens"), u.get("output_tokens")
                    if it is not None or ot is not None:
                        total = (it or 0) + (ot or 0)
                if total is None:
                    return "tokens=?"
                if "input_tokens" in u or "output_tokens" in u:
                    return f"tokens={total} (in={u.get('input_tokens','?')}, out={u.get('output_tokens','?')})"
                return f"tokens={total}"

            footer = (
                f"\n\n-- Turn done. model={(model_used or options.model)} "
                f"{_token_summary(usage or {})} cost={cost if cost is not None else '?'} --"
            )
            print(footer, file=sys.stderr)

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

Untuk menjalankan aplikasi, ketik perintah berikut di terminal:

python note_smith.py

Ini akan memulai antarmuka chat CLI dengan perintah-perintah yang membantu.

Pertama, mari merangkum halaman web. Saya memberikan URL situs portofolio saya:

/summarize abid.work

Pertama, agen akan menentukan tool mana yang digunakan, mengambil konten dari halaman web, mengekstrak lima poin kunci, dan menampilkannya di antarmuka chat. Di akhir, ia akan menampilkan laporan penggunaan yang mencakup nama model, penggunaan token, dan biaya.

I'll fetch and summarize the content from that URL for you.                                    
šŸ› ļø  Using tool: WebFetch with input: {"url": "https://abid.work", "prompt": "Extract the main content and key information from this page, including what the person does, their background, projects, and any notable achievements or areas of focus."}


**5 Key Points:**

• **Prolific Tech Educator** - Authored 500+ articles making data science & ML accessible through tutorials, cheat sheets, and practical guides

• **Certified Data Scientist** - Professional focus on building innovative machine learning solutions across NLP, computer vision, and MLOps

• **Multi-Domain Expertise** - Covers Python, SQL, AI, and end-to-end ML workflows with hands-on project demonstrations

• **Content-First Philosophy** - Maintains extensive portfolio including blogs, tutorials, book reviews, and career resources

• **Open Contributor** - Active on GitHub (kingabzpro) sharing code and projects with the community

**TL;DR:** Abid Ali Awan is a certified data scientist who's authored 500+ educational articles and tutorials, specializing in ML, NLP, and making complex tech concepts accessible to learners.

-- Turn done. model=claude-sonnet-4-5-20250929 tokens=326 (in=6, out=320) cost=0.062402849999999996 --

Selanjutnya, mari simpan sebuah catatan:

/note what is love

Kita instruksikan untuk menyimpan catatan dengan teks ā€œwhat is loveā€.

šŸ› ļø  Using tool: mcp__utils__save_note with input: {"text": "what is love"}


āœ“ Note saved: "what is love"

-- Turn done. model=claude-sonnet-4-5-20250929 tokens=81 (in=6, out=75) cost=0.07421549999999999 --

Terakhir, kita akan mencari catatan tersebut dengan memberikan kata kunci dari catatan:

/find love

Seperti yang terlihat, ia menemukan file dan menampilkan teks darinya.

šŸ› ļø  Using tool: mcp__utils__find_note with input: {"pattern": "love"}


**Found 1 note matching "love":**

• `note_2025-09-30_17-18-02.txt` - "what is love"

-- Turn done. model=claude-sonnet-4-5-20250929 tokens=105 (in=6, out=99) cost=0.08423339999999999 --

KesimpulanĀ 

Claude Agent SDK mudah disiapkan, terutama jika Anda sudah memasang Claude Code secara lokal. Yang dibutuhkan hanyalah menginstal paket SDK.Ā 

SDK Python menyediakan dua cara utama untuk berinteraksi dengan Claude:

  • query() – API generasi teks sederhana yang terbaik untuk use case ringan, meski tidak mendukung tool.
  • ClaudeSDKClient – API agentic lengkap yang memungkinkan Anda melanjutkan sesi, menggunakan tool, mempertahankan kontrol manual, dan lainnya.

Dalam tutorial ini, kita mengeksplorasi model terbaru Anthropic, Claude Sonnet 4.5, dan memperkenalkan Claude Agent SDK yang baru. Kita menelusuri proses instalasi dan membangun tiga proyek contoh untuk menunjukkan kemampuannya.

Jika Anda tertarik bereksperimen dengan alur kerja agentic, saya sangat merekomendasikan mencoba SDK ini.

Abid Ali Awan

Penulis

Abid Ali Awan

Sebagai data scientist tersertifikasi, saya bersemangat memanfaatkan teknologi mutakhir untuk menciptakan aplikasi machine learning yang inovatif. Dengan latar belakang kuat di pengenalan ucapan, analisis dan pelaporan data, MLOps, conversational AI, dan NLP, saya mengasah keterampilan dalam mengembangkan sistem cerdas yang berdampak nyata. Selain keahlian teknis, saya juga komunikator andal yang mampu menyederhanakan konsep kompleks menjadi bahasa yang jelas dan ringkas. Karena itu, saya menjadi blogger yang dicari di bidang data science, membagikan wawasan dan pengalaman kepada komunitas profesional data yang terus berkembang. Saat ini, saya berfokus pada pembuatan dan penyuntingan konten, bekerja dengan large language model untuk mengembangkan konten yang kuat dan menarik agar membantu bisnis dan individu memaksimalkan data mereka.

Topik

Terkait

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

blogs

Tutorial Korelasi di R