मुख्य सामग्री पर जाएँ

Claude Agent SDK ट्यूटोरियल: Claude Sonnet 4.5 के साथ एजेंट बनाएँ

तीन प्रोजेक्ट बनाकर जानें कि Claude Agent SDK कैसे काम करता है—वन‑शॉट से लेकर कस्टम‑टूल एजेंट्स तक।
· 9 मि॰ पढ़ें

AI के साथ खोजें

Anthropic ने Claude Sonnet 4.5 जारी किया है—एक अत्याधुनिक कोडिंग मॉडल जो पहले ही इंडस्ट्री चार्ट और बेंचमार्क्स में शीर्ष पर है। इस रिलीज़ की सबसे बड़ी खासियत है इसका टूल्स और फ्रेमवर्क्स में सहज इंटीग्रेशन। VS Code एक्सटेंशन और कॉन्टेक्स्ट एडिटिंग फीचर्स से लेकर मेमोरी टूल, कोड निष्पादन, और फ़ाइल निर्माण (स्प्रेडशीट, स्लाइड, डॉक्यूमेंट) तक। यह Chrome के लिए Claude और Imagine with Claude के साथ नए अनुभवों तक भी विस्तार करता है।

लेकिन इस रिलीज़ का मुख्य आकर्षण है बिल्कुल नया Claude Agent SDK, जो Claude Code के ऊपर बनाया गया है। यह SDK एक शक्तिशाली एजेंटिक फ्रेमवर्क पेश करता है, जो डेवलपर्स को Claude की क्षमताओं को बिल्ड, कस्टमाइज़ और पूरी तरह नए तरीकों से विस्तृत करने देता है।

इस ट्यूटोरियल में, हम Claude 4.5 में नया क्या है, उसे समझेंगे; Claude Agent SDK के साथ हैंड्स-ऑन करेंगे; इसे लोकल रूप से सेट अप करेंगे; और इसकी संभावनाओं को क्रिया में देखने के लिए तीन सरल प्रोजेक्ट बनाएँगे।

Claude 4.5 में नया क्या है?

Claude Sonnet 4.5 बड़ी क्षमता उन्नयन प्रदान करता है। यह विश्व का सर्वश्रेष्ठ कोडिंग मॉडल है, जटिल एजेंट बनाने के लिए सबसे मजबूत है, और कंप्यूटर-यूज़ कार्यों में सर्वश्रेष्ठ है, साथ ही तर्क और गणित में उल्लेखनीय प्रगति के साथ। यह मॉडल SWE-bench Verified बेंचमार्क पर अत्याधुनिक है और जटिल, बहु-चरण कार्यों पर 30 घंटे से अधिक तक ध्यान बनाए रखने का अवलोकन किया गया है। 

OSWorld लीडरबोर्ड पर, इसका प्रदर्शन 61.4% तक बढ़ गया है, जो चार महीने पहले 42.2% था। वित्त, क़ानून, चिकित्सा और STEM क्षेत्रों के विशेषज्ञों ने डोमेन ज्ञान और तर्क क्षमता में उल्लेखनीय सुधार की रिपोर्ट की है।

स्रोत: Introducing Claude Sonnet 4.5 \ Anthropic

इसके अलावा, यह अब तक का Anthropic का सबसे अधिक अलाइंड फ्रंटियर मॉडल है, जिसमें चापलूसी, छल, शक्ति-लोलुप व्यवहार और भ्रम को बढ़ावा देने में कमी दिखती है। इसमें प्रॉम्प्ट इंजेक्शन के खिलाफ सुरक्षा भी मज़बूत की गई है। ASL-3 सेफगार्ड्स के तहत जारी, उन्नत क्लासिफ़ायर्स का लक्ष्य उच्च-जोखिम सामग्री को फ़िल्टर करना है, जबकि पहले के संस्करणों की तुलना में फ़ॉल्स पॉज़िटिव्स को काफ़ी घटाना है। हमें एक नया छोटा मॉडल भी दिखा, जिसके बारे में आप हमारे Claude Haiku 4.5 गाइड में पढ़ सकते हैं।

Claude Agent SDK को समझना

Claude Agent SDK, जिसे पहले Claude Code SDK के नाम से जाना जाता था, ऐसे टूल्स का सेट प्रदान करता है जो आपको उसी फ्रेमवर्क का उपयोग करके शक्तिशाली, जनरल-पर्पज़ एजेंट बनाने में मदद करता है जो Claude Code को संचालित करता है। 

इसका मूल सिद्धांत सीधा है: Claude को कंप्यूटर तक पहुँच दें। टर्मिनल और फ़ाइल-सिस्टम एक्सेस के साथ, एजेंट डेवलपर की तरह ही कोड खोज, लिख, निष्पादित और उस पर इटरेट कर सकते हैं। ये क्षमताएँ कोडिंग से आगे बढ़कर गहन रिसर्च, वीडियो निर्माण, नोट-टेकिंग, डेटा विश्लेषण, और बहुत कुछ तक फैली हैं। 

Claude Agent SDK चार मुख्य चरणों पर आधारित एक संरचित एजेंट लूप बताता है: संदर्भ एकत्र करना, कार्रवाई करना, कार्य का सत्यापन, और दोहराना.

व्यवहार में, संदर्भ के लिए agentic search से शुरू करें और जब गति चाहिए हो तो semantic search जोड़ें। कार्रवाइयों का फोकस उच्च‑सिग्नल टूल्स, bash स्क्रिप्ट्स, और Model Context Protocol के माध्यम से बाहरी सेवाओं के इंटीग्रेशंस पर होना चाहिए। 

वेरिफिकेशन में नियम‑आधारित जाँचें, दृश्य फीडबैक, और वैकल्पिक LLM सहायता का संयोजन होता है। सतत इटरेशन की सिफारिश की जाती है ताकि प्रदर्शन सुधारा जा सके, टूल्स का विस्तार हो, और जैसे‑जैसे फ़ीचर्स विकसित हों, सर्च क्षमताएँ बेहतर हों।

मुख्य फ़ीचर्स:

  1. SDKs: वेब/Node.js बैकएंड्स और डेटा साइंस के लिए TypeScript और Python, साझा अवधारणाओं के साथ ताकि टीमें अलग‑अलग स्टैक्स में पैटर्न को पुनः उपयोग कर सकें।
  2. मोड्स: इंटरएक्टिव, कम‑विलंबता UX के लिए स्ट्रीमिंग और बैच या निर्धारक रन के लिए सिंगल‑शॉट—गति और नियंत्रण के संतुलन हेतु कार्य के अनुसार चुनें।
  3. संदर्भ प्रबंधन: स्वतः संपीड़न और लंबे रन का संदर्भ नियंत्रण ताकि ओवरफ़्लो न हो और विस्तारित सेशंस के दौरान एजेंट ट्रैक पर बने रहें।
  4. टूलिंग: इनबिल्ट फ़ाइल ऑपरेशंस, कोड निष्पादन, और वेब सर्च, साथ ही MCP के माध्यम से बाहरी टूल्स और डेटा के लिए विस्तारशीलता।
  5. परमिशंस: सूक्ष्म क्षमता नियंत्रण (जैसे, प्रति‑टूल अनुमति/अस्वीकृति और नीति मोड्स) ताकि प्रोडक्शन में एजेंट क्या कर सकता है उस पर लगाम रहे।
  6. प्रोडक्शन‑रेडी: इनबिल्ट एरर हैंडलिंग, सेशन मैनेजमेंट, और मॉनिटरिंग ताकि आप पहले दिन से ही ऑब्ज़र्वेबिलिटी के साथ भरोसेमंद एजेंट तैनात कर सकें।
  7. Claude इंटीग्रेशन: स्वचालित प्रॉम्प्ट कैशिंग और परफ़ॉर्मेंस ऑप्टिमाइज़ेशन, जिससे थ्रूपुट बेहतर करते हुए लेटेंसी और लागत घटती है।
  8. प्रमाणीकरण: Claude API कुंजी का उपयोग करें या अपने डिप्लॉयमेंट वातावरण के अनुसार Amazon Bedrock और Google Vertex AI जैसे प्रोवाइडर्स के माध्यम से रूट करें।
  9. सिस्टम प्रॉम्प्ट्स: एजेंट के व्यवहार को कार्यों और सेशंस में समान रूप से ढालने हेतु भूमिका, विशेषज्ञता, और गार्डरेल्स परिभाषित करें।
  10. इंटीग्रेशंस (MCP): ओपन Model Context Protocol के ज़रिए कस्टम टूल्स, डेटाबेस, और APIs कनेक्ट करें—यह Anthropic द्वारा समर्थित मानक है, जिसके आधिकारिक TypeScript SDKs और बढ़ते इकोसिस्टम हैं।

Python में Claude Agent SDK के साथ शुरुआत करना

किसी भी प्रोजेक्ट पर काम शुरू करने से पहले, आपको कुछ पूर्वापेक्षाएँ सेट करनी होंगी, Claude Code CLI इंस्टॉल करना होगा, और Claude Agent SDK स्थापित करना होगा।

पूर्वापेक्षाएँ

  • सुनिश्चित करें कि आपके पास Python संस्करण 3.10 या उससे ऊपर है। 
  • Claude Code CLI का प्रभावी उपयोग करने के लिए, आपको Node.js संस्करण 18 या उससे ऊपर और NPM पैकेज भी इंस्टॉल करना होगा।

Claude Code CLI इंस्टॉल करें

Windows के लिए: 

PowerShell खोलें और Claude Code डाउनलोड व इंस्टॉल करने के लिए निम्न कमांड चलाएँ:

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

इंस्टॉलेशन के बाद, C:\Users\<user>\.local\bin को अपने सिस्टम के PATH में जोड़ें। PowerShell को फिर से शुरू करें, और आपको दिखेगा कि Claude चल रहा है।

अन्य प्लेटफ़ॉर्म्स के लिए:

यदि आपके पास Node.js और NPM इंस्टॉल हैं, तो Claude Code इंस्टॉल करने के लिए टर्मिनल में निम्न कमांड चलाने का प्रयास करें:

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

निर्देशों का पालन करें और अपने environment variables सेट करें, ताकि आप टर्मिनल में केवल “claude” टाइप करके Claude Code तक पहुँच सकें।

Claude Code सेट करना

Claude Code इंस्टॉल करने के बाद, टर्मिनल में “claude” टाइप कर के इसे खोलें और साइन इन करें। यदि आपके पास Claude Pro या Max प्लान है, तो “Log in with your subscription account” चुनें ताकि उपयोग आपके प्लान से कटे।

यदि आप pay-as-you-go पसंद करते हैं, तो इसके बजाय API कुंजी से प्रमाणीकरण करें; बिलिंग Anthropic Console के माध्यम से होगी। 

अंत में, अपना थीम और इंटरफ़ेस/CLI वरीयताएँ सेट करें ताकि पहले दिन से ही सब कुछ आपके वर्कफ़्लो के अनुरूप हो।

मैंने अपना Claude Code API कुंजी के साथ सेट कर लिया है। आप यह सेटअप यहाँ देख सकते हैं:

Claude Code सेटअप

Claude Agent SDK इंस्टॉल करें

सुनिश्चित करें कि Python इंस्टॉल है, फिर अपना टर्मिनल खोलें। Claude Agent SDK इंस्टॉल करने के लिए यह चलाएँ:

pip install claude-agent-sdk

नोट: यदि आपको CLINotFoundError मिलता है, तो सुनिश्चित करें कि आपने ऊपर CLI इंस्टॉल किया है और Claude आपके PATH में शामिल है।

Claude Agent SDK और Claude Sonnet 4.5 के साथ प्रोजेक्ट बनाना

अब हम Claude Agent SDK को फ्रेमवर्क के रूप में, टूल्स और कंप्यूटर उपयोग के लिए Claude code, और अपने AI मॉडल के रूप में Claude Sonnet 4.5 का उपयोग कर तीन सरल प्रोजेक्ट बनाएँगे।

  1. वन‑शॉट ब्लॉग आउटलाइन: एक साधारण वन‑शॉट क्वेरी जो बिना टूल्स के Claude Agent SDK के बुनियादी उपयोग को दर्शाती है।
  2. InspireBot CLI: यह प्रोजेक्ट वेब सर्च क्षमताओं को प्रेरणादायक उद्धरणों के लिए एक कस्टम फ़ॉलबैक टूल के साथ जोड़ता है।
  3. NoteSmith मल्टी‑टूल ऐप: एक संपूर्ण नोट्स एप्लीकेशन जिसमें कई टूल्स, सेफ़्टी हुक्स, और उपयोग ट्रैकिंग शामिल हैं।

सारा सोर्स कोड GitHub रिपॉज़िटरी में उपलब्ध है: kingabzpro/claude-agent-projects

1. वन‑शॉट ब्लॉग आउटलाइन

इस प्रोजेक्ट में, हम SDK के query() फ़ंक्शन का Claude Sonnet 4.5 के साथ उपयोग कर एक ब्लॉग आउटलाइन बनाते हैं। यह एक सीधी‑सादी वन‑शॉट क्वेरी है जो बिना किसी टूल के Claude Agent SDK का बेसिक उपयोग दिखाती है।

कोड में शामिल हैं: 

  1. असिंक्रोनस स्ट्रीमिंग: नॉन‑ब्लॉकिंग, टोकन‑दर‑टोकन आउटपुट के लिए SDK के query() async इटरेटर के साथ asyncio का उपयोग।
  2. प्रॉम्प्ट और विकल्प: ब्लॉग आउटलाइन के लिए PROMPT परिभाषित करता है और ClaudeAgentOptions के माध्यम से मॉडल/पर्सोना कॉन्फ़िगर करता है।
  3. टाइप्ड मेसेज फ्लो: मैसेजेज़ पर इटरेट करता है; केवल AssistantMessage → TextBlock कंटेंट निकालता है।
  4. रियल‑टाइम आउटपुट: टेक्स्ट के आते ही प्रिंट करता है (end="") ताकि कंसोल में साफ़ स्ट्रीमिंग दृश्य मिले।
  5. रिज़ल्ट हैंडलिंग: ResultMessage को नज़रअंदाज़ करता है, स्ट्रीम को स्वाभाविक रूप से समाप्त होने देता है।
  6. एंट्री पॉइंट: स्क्रिप्ट निष्पादित होने पर सब कुछ asyncio.run(main()) से चलाता है।
  7. कस्टमाइज़ेबल और मिनिमल: मॉडल/प्रॉम्प्ट बदलना आसान; हल्की स्क्रिप्ट, डेमो या पाइपलाइनों के लिए उपयुक्त।

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())

हम स्क्रिप्ट चलाएँगे और फिर आउटपुट को एक markdown फ़ाइल के रूप में सेव करेंगे। 

python oneshot_outline.py > outline.md 

आप markdown फ़ाइल खोल सकते हैं और देख सकते हैं कि इसने उचित तकनीकी कॉपी जनरेट की है। 

Claude Agent SDK ब्लॉग आउटलाइन

आप अपने डैशबोर्ड पर वापस जाकर https://console.anthropic.com/usage पर अपनी उपयोगिता जाँच सकते हैं। जैसा कि आप देख सकते हैं, मॉडल Claude Sonnet 4.5 का उपयोग कर रहा है।

Claude Agent SDK उपयोग

2. InspireBot CLI

इस प्रोजेक्ट में, हम एक टर्मिनल‑अनुकूल मोटिवेशन जेनरेटर बनाते हैं जो Claude Sonnet 4.5 का उपयोग करके उद्धरण स्ट्रीम करता है। यह पहले WebSearch आज़माता है, फिर कस्टम inspire_me टूल पर फ़ॉलबैक करता है जो रैंडम उद्धरण देता है।

कोड में शामिल हैं:

  • कस्टम फ़ॉलबैक टूल: inspire_me को पूर्वनिर्धारित प्रेरक उद्धरणों के साथ परिभाषित करता है, जिसे create_sdk_mcp_server के माध्यम से रजिस्टर किया गया है।
  • CLI हेल्पर्स: is_tty, typewrite, bold, faint टर्मिनल में टाइपराइटर एनीमेशन और स्टाइल्ड आउटपुट जोड़ते हैं।
  • प्रॉम्प्ट और विकल्प: ClaudeAgentOptions के साथ कॉन्फ़िगर, जो टूल्स (WebSearch + inspire_me) और “InspireBot” नामक सिस्टम पर्सोना की अनुमति देता है।
  • स्ट्रीमिंग टूल कॉल्स: संदेशों पर इटरेट करता है, टूल उपयोग (ToolUseBlock), परिणाम (ToolResultBlock), और अंतिम आउटपुट (TextBlock) दिखाता है।
  • फ़ॉलबैक लॉजिक: यदि उपयोगी आउटपुट न दिखे, तो डिफ़ॉल्ट रूप से एक रैंडम लोकल उद्धरण देता है।
  • इंटरएक्टिव UX: स्ट्रीमिंग टूल इनपुट/परिणाम दिखाता है, फिर अंतिम प्रेरक पंक्ति को टाइपराइटर प्रभाव के साथ एनिमेट करता है।

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())

हम निम्न कमांड का उपयोग कर डिफ़ॉल्ट टॉपिक के साथ स्क्रिप्ट चलाएँगे:  

python inspire_web.py

जैसा कि हम देख सकते हैं, यह उपयोग किए गए टूल्स, उन टूल्स के इनपुट दिखाता है, और फिर एक प्रेरक उद्धरण आउटपुट करता है।  

आइए Python स्क्रिप्ट को एक कस्टम टॉपिक दें:  

python inspire_web.py "Sadness and Love"

यह एक प्रेरक उद्धरण लौटाता है जिसमें "love" और "sadness" कीवर्ड शामिल हैं।

3. NoteSmith मल्टी‑टूल ऐप

इस प्रोजेक्ट में, हम एक मल्टी‑टूल रिसर्च असिस्टेंट बनाते हैं जो स्थानीय रूप से नोट्स सेव और सर्च करता है, वेब पेजेज़ का सारांश बनाता है, और Claude Sonnet 4.5 के साथ परिणाम स्ट्रीम करता है। यह समृद्ध CLI अनुभव के लिए कस्टम MCP टूल्स, इनबिल्ट टूल्स, और एक सेफ़्टी हुक को जोड़ता है।

कोड में शामिल हैं:

  • लोकल स्टोरेज: टाइमस्टैम्प के साथ नोट्स डिस्क पर सेव करता है; साधारण grep लॉजिक से केस‑इनसेंसिटिव सर्च सपोर्ट करता है।
  • कस्टम MCP टूल्स: save_note (टेक्स्ट स्टोर करें) और find_note (नोट्स खोजें), जिन्हें create_sdk_mcp_server के साथ रजिस्टर किया गया है।
  • सेफ्टी हुक: block_dangerous_bash हानिकारक शेल कमांड्स (जैसे, rm -rf /) को टूल एक्सीक्यूशन से पहले अस्वीकार करता है।
  • सिस्टम प्रॉम्प्ट और कमांड्स: /summarize, /note, /find, /help, /exit को परिभाषित करता है; प्रॉम्प्ट टूल उपयोग को निर्देशित करता है (WebFetch, save_note, find_note)।
  • स्ट्रीमिंग इंटरैक्शन: ClaudeSDKClient का उपयोग AssistantMessage, ToolUseBlock, ToolResultBlock को हैंडल करने के लिए होता है, और टेक्स्ट व टूल परिणाम रियल‑टाइम में प्रिंट करता है।
  • उपयोग ट्रैकिंग: मॉडल नाम, टोकन और लागत के साथ एक फुटर stderr पर प्रिंट करता है, ताकि मुख्य आउटपुट साफ रहे।
  • चैट इंटरफ़ेस: एक हल्के REPL की तरह काम करता है, जहाँ आप कमांड्स टाइप करते हैं (/note, /find, /summarize) और तुरंत प्रतिक्रियाएँ मिलती हैं, जिससे यह किसी असिस्टेंट से चैट जैसा महसूस होता है।

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())

ऐप चलाने के लिए, टर्मिनल में निम्न कमांड टाइप करें:

python note_smith.py

यह सहायक कमांड्स के साथ CLI चैट इंटरफ़ेस शुरू कर देगा।

हम पहले वेबपेज का सारांश बनाएंगे। मैंने अपना पोर्टफोलियो वेबसाइट URL दिया है:

/summarize abid.work

पहले, एजेंट यह तय करेगा कि किन टूल्स का उपयोग करना है, वेबपेज से कंटेंट लाएगा, पाँच मुख्य बिंदु निकालेगा, और उन्हें चैट इंटरफ़ेस में दिखाएगा। अंत में, यह एक यूसेज रिपोर्ट दिखाएगा जिसमें मॉडल का नाम, टोकन उपयोग और लागत शामिल होगी।

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 --

अब एक नोट सेव करते हैं:

/note what is love

हमने इसे “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 --

अंत में, हम नोट में से एक कीवर्ड देकर उसे खोजेंगे:

/find love

जैसा कि आप देख सकते हैं, इसने फ़ाइल ढूँढ ली और उसका टेक्स्ट दिखा दिया।

🛠️  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 --

निष्कर्ष

Claude Agent SDK सेटअप करना सीधा‑सादा है, खासकर यदि आपके पास पहले से लोकली Claude Code इंस्टॉल है। आपको केवल SDK पैकेज इंस्टॉल करना होता है। 

Python SDK, Claude से इंटरैक्ट करने के दो प्रमुख तरीक़े देता है:

  • query() – एक सरल टेक्स्ट जनरेशन API जो हल्के उपयोग‑मामलों के लिए बेहतर है, हालांकि यह टूल्स सपोर्ट नहीं करता।
  • ClaudeSDKClient – एक पूर्ण‑विशेषताओं वाला एजेंटिक API, जो सेशन्स को रेज़्यूम करने, टूल्स इस्तेमाल करने, मैनुअल कंट्रोल बनाए रखने आदि की सुविधा देता है।

इस ट्यूटोरियल में, हमने Anthropic का नवीनतम मॉडल Claude Sonnet 4.5 देखा और नया Claude Agent SDK पेश किया। हमने इंस्टॉलेशन प्रक्रिया देखी और इसकी क्षमताएँ दिखाने के लिए तीन नमूना प्रोजेक्ट बनाए।

यदि आप एजेंटिक वर्कफ़्लोज़ के साथ प्रयोग करने में रुचि रखते हैं, तो मैं इस SDK को आज़माने की दृढ़ता से सलाह दूँगा।

Abid Ali Awan

लेखक

Abid Ali Awan

एक प्रमाणित डेटा साइंटिस्ट के रूप में, मैं अत्याधुनिक तकनीक का उपयोग करके नवाचारी मशीन लर्निंग अनुप्रयोग बनाने के लिए उत्साहित रहता/रहती हूँ। स्पीच रिकॉग्निशन, डेटा विश्लेषण और रिपोर्टिंग, MLOps, संवादात्मक AI और NLP में मजबूत पृष्ठभूमि के साथ, मैंने ऐसे बुद्धिमान सिस्टम विकसित करने में अपनी विशेषज्ञता निखारी है जो वास्तविक प्रभाव डाल सकें। तकनीकी दक्षता के अलावा, मैं जटिल अवधारणाओं को स्पष्ट और संक्षिप्त भाषा में प्रस्तुत करने में भी निपुण हूँ। परिणामस्वरूप, मैं डेटा साइंस पर एक मांग में रहने वाला/वाली ब्लॉगर बन गया/गई हूँ, और डेटा प्रोफेशनलों के बढ़ते समुदाय के साथ अपने अनुभव और विचार साझा करता/करती हूँ। वर्तमान में, मैं कंटेंट निर्माण और संपादन पर केंद्रित हूँ, बड़े भाषा मॉडलों के साथ काम करते हुए ऐसा प्रभावशाली और आकर्षक कंटेंट विकसित कर रहा/रही हूँ जो व्यवसायों और व्यक्तियों दोनों को अपने डेटा का अधिकतम लाभ उठाने में मदद कर सके।

विषय