[Go to site: main page, start]

Skip to main content

Command Palette

Search for a command to run...

SDK

Cursor Python SDK

cursor-sdk पैकेज आपको अपने Python कोड से Cursor के एजेंट को कॉल करने देता है। Cursor IDE, CLI और वेब ऐप में चलने वाले उसी एजेंट को Python से सिंक और async क्लाइंट्स, टाइप्ड डेटाक्लास, तथा स्ट्रीम और पृष्ठों के लिए सामान्य iteration के साथ स्क्रिप्ट किया जा सकता है। शुरू करने के लिए Cursor में /sdk कौशल चलाएँ।

REST API के लिए Cloud Agents API देखें। अन्य भाषाओं के लिए SDK ब्रिज देखें।

अवलोकन

SDK स्थानीय और क्लाउड रनटाइम्स को एक ही इंटरफ़ेस के पीछे उपलब्ध कराता है। एजेंट कहीं भी चले, आप वही कोड लिखते हैं।

रनटाइमयह क्या करता हैकब उपयोग करें
स्थानीयडिस्क पर मौजूद स्थानीय फ़ाइलों के साथ एजेंट चलाता है।वर्किंग ट्री पर डेवलपमेंट स्क्रिप्ट्स और CI जाँच के लिए।
क्लाउड (Cursor-होस्टेड)आपके रेपो को क्लोन करके पृथक VM में एजेंट चलाता है। VMs को Cursor चलाता है।जब कॉलर के पास रेपो न हो, कई एजेंट समानांतर में चलाने हों, या कॉलर के डिस्कनेक्ट होने के बाद भी रन जारी रहने चाहिए हों।

Agent.create() को local या cloud पास करके रनटाइम सेट करें।

प्रमाणीकरण

एजेंट बनाने से पहले CURSOR_API_KEY सेट करें या api_key पास करें।

SDK स्थानीय और क्लाउड रन्स, दोनों के लिए उपयोगकर्ता API कुंजियाँ और सर्विस अकाउंट API कुंजियाँ स्वीकार करता है। टीम Admin API कुंजियाँ अभी समर्थित नहीं हैं।

export CURSOR_API_KEY="your-key"

उपयोग और बिलिंग

SDK रन, IDE और क्लाउड एजेंट्स के रनों की तरह ही मूल्य निर्धारण, अनुरोध पूल और गोपनीयता मोड के नियमों का पालन करते हैं। खर्च आपकी टीम के उपयोग डैशबोर्ड में SDK टैग के अंतर्गत दिखता है।

कोड में प्रति-रन टोकन संख्या जानने के लिए, टोकन उपयोग देखें। किसी एजेंट के रनों का बिल किया गया उपयोग और डॉलर लागत प्राप्त करने के लिए, agent.get_usage() देखें।

मुख्य अवधारणाएँ

अवधारणाविवरण
एजेंटबातचीत की स्थिति, कार्यस्थान कॉन्फ़िगरेशन, मॉडल चयन और सेटिंग्स रखने वाला स्थायी हैंडल। कई प्रॉम्प्ट्स तक बना रहता है।
चलाएँएक प्रॉम्प्ट सबमिशन। इसकी अपनी स्ट्रीम, स्थिति, परिणाम, बातचीत और रद्द करने की सुविधा होती है।
SDKMessageरन के दौरान प्राप्त होने वाला typed स्ट्रीम संदेश। स्थानीय और क्लाउड रनटाइम्स में इसका स्वरूप समान रहता है।
CursorClientजीवनचक्र नियंत्रण, कस्टम HTTP विकल्पों या एक ही process में कई कार्यस्थानों के लिए स्पष्ट क्लाइंट। Client इसका उपनाम है।
AsyncClientAsync-मिरर क्लाइंट। सभी async operations के लिए आवश्यक।

स्थापना

pip install cursor-sdk

Python 3.10 या बाद का संस्करण आवश्यक है।

त्वरित शुरुआत

import osfrom cursor_sdk import Agent, LocalAgentOptionswith Agent.create(    model="composer-2.5",    api_key="crsr_key",    local=LocalAgentOptions(cwd=os.getcwd()),) as agent:    print(agent.send("Summarize what this repository does").text())

स्ट्रीम इवेंट्स में सहायक टेक्स्ट निकालने, टूल कॉल्स हैंडल करने और रन की स्थिति पढ़ने का तरीका बताया गया है। एक-बार वाले प्रॉम्प्ट (बनाएं, चलाएँ, समाप्त करें) के लिए Agent.prompt() देखें।

क्लाउड त्वरित शुरुआत

Python SDK में Cursor के क्लाउड एजेंट्स के लिए अंतर्निहित सहायता है। आप कनेक्ट की गई रिपॉजिटरीज़ की सूची देख सकते हैं, उनमें से किसी एक के लिए एजेंट शुरू कर सकते हैं, रन पूरा होने की प्रतीक्षा कर सकते हैं और अंतिम परिणाम की समीक्षा कर सकते हैं।

from cursor_sdk import Agent, CloudAgentOptions, CloudRepositorywith Agent.create(    model="composer-2.5",    api_key="crsr_key",    cloud=CloudAgentOptions(        repos=[CloudRepository(url="https://github.com/your-org/your-repo", starting_ref="main")],        auto_create_pr=True,    ),) as agent:    print(agent.send("Add structured logging to the auth middleware").text())

SDK द्वारा शुरू किए गए क्लाउड एजेंट्स डिफ़ॉल्ट एजेंट सूची में नहीं दिखते। उन्हें Cursor Web या Cursor एजेंट्स विंडो में देखने के लिए, फ़िल्टर > स्रोत > SDK पर क्लिक करें।

Async उपयोग

async क्लाइंट, सिंक स्रोत इंटरफ़ेस के अनुरूप है और सर्वर, बॉट और समवर्ती एजेंट ऑर्केस्ट्रेशन के लिए अनुशंसित है। AsyncAgent, AsyncClient, AsyncRun और AsyncCursor को cursor_sdk और cursor_sdk.asyncio दोनों से एक्सपोर्ट किया जाता है।

import asyncioimport osfrom cursor_sdk import AsyncClient, LocalAgentOptionsasync def main():    async with await AsyncClient.launch_bridge(workspace=os.getcwd()) as client:        async with await client.agents.create(            model="composer-2.5",            api_key="crsr_key",            local=LocalAgentOptions(cwd=os.getcwd()),        ) as agent:            run = await agent.send("Summarize what this repository does")            print(await run.text())asyncio.run(main())

कोई वैश्विक async डिफ़ॉल्ट क्लाइंट नहीं है। AsyncClient को स्पष्ट रूप से इंस्टैंशिएट करें या AsyncClient.launch_bridge(...) को async संदर्भ प्रबंधक के रूप में उपयोग करें, ताकि हर इवेंट लूप का अपना क्लाइंट हो। एक ही कोड पाथ में सिंक और async क्लाइंट का मिश्रण न करें।

प्रत्यक्ष AsyncAgent क्लास मेथड में client= आवश्यक है। उपयोग करें await client.agents.create(...) या await AsyncAgent.create(..., client=client)

सिंकAsync
CursorClient / ClientAsyncClient / AsyncCursorClient
AgentAsyncAgent
RunAsyncRun
CursorAsyncCursor
ListResultAsyncListResult
DefaultHttpxClientDefaultAsyncHttpxClient

एजेंट बनाना

Agent.create() विकल्पों को सत्यापित करता है और तुरंत एक हैंडल लौटाता है। रनटाइम चुनने के लिए local या cloud में से किसी एक को पास करें।

from cursor_sdk import Agent, CloudAgentOptions, CloudRepository, LocalAgentOptionsagent = Agent.create(    model="composer-2.5",    local=LocalAgentOptions(cwd="."),)cloud_agent = Agent.create(    model="composer-2.5",    cloud=CloudAgentOptions(        repos=[CloudRepository(url="https://github.com/your-org/your-repo", starting_ref="main")],        auto_create_pr=True,    ),)

agent.agent_id तुरंत सेट हो जाता है। स्थानीय एजेंट्स को agent-<uuid> ID मिलती है, जबकि क्लाउड एजेंट्स को bc-<uuid> ID मिलती है। agent.model एक टाइप्ड ModelSelection है, इसलिए agent.model.id और agent.model.params सीधे इस्तेमाल किए जा सकते हैं।

सत्र एनवायरनमेंट वेरिएबल्स

क्लाउड एजेंट्स के लिए, जब किसी रन को अल्पकालिक क्रेडेंशियल या ऐसे अन्य मान चाहिए हों जो केवल उस एजेंट तक सीमित रहें, तो env_vars पास करें।

import osagent = Agent.create(    model="composer-2.5",    cloud=CloudAgentOptions(        repos=[CloudRepository(url="https://github.com/your-org/your-repo")],        env_vars={            "STAGING_API_TOKEN": os.environ["STAGING_API_TOKEN"],        },    ),)

ये मान स्थिर अवस्था में एन्क्रिप्ट रहते हैं, क्लाउड एजेंट के shell में इंजेक्ट किए जाते हैं और एजेंट के हटने पर मिटा दिए जाते हैं। कॉलर द्वारा दिए गए agent_id के साथ env_vars का उपयोग नहीं किया जा सकता; agent_id छोड़ दें और सर्वर द्वारा बनाया गया ID agent.agent_id से पढ़ें। वेरिएबल नाम CURSOR_ से शुरू नहीं हो सकते।

जो मान केवल एक ही run के दौरान मौजूद रहने चाहिए, उन्हें इसके बजाय agent.send() में पास करें। प्रति-चलाएँ एनवायरनमेंट वेरिएबल्स देखें।

एजेंट मेटाडेटा

क्लाउड एजेंट बनाते समय उसमें अपने पहचानकर्ता संलग्न करें। मेटाडेटा किसी एजेंट को आपके सिस्टम के उपयोगकर्ता, टेनेंट, कार्यप्रवाह या टिकट से लिंक कर सकता है। इसे client.agents.get() और client.agents.list() के माध्यम से SDKAgentInfo.metadata में वापस प्राप्त किया जा सकता है।

from cursor_sdk import Agent, CloudAgentOptions, CloudRepositorywith Agent.create(    model="composer-2.5",    cloud=CloudAgentOptions(        repos=[CloudRepository(url="https://github.com/your-org/your-repo")],        metadata={            "end_user_id": "user-123",            "ticket_id": "ENG-456",        },    ),) as agent:    print(agent.agent_id)

क्लाउड एजेंट्स के लिए एजेंट बनाते समय मेटाडेटा उपलब्ध होता है। आप अधिकतम 50 कुंजी-मान युग्म संलग्न कर सकते हैं। कुंजियाँ खाली नहीं होनी चाहिए और 255 वर्णों से अधिक लंबी नहीं होनी चाहिए। मान स्ट्रिंग होने चाहिए और 4096 बाइट्स से बड़े नहीं होने चाहिए। खाली स्ट्रिंग मानों की अनुमति है और खाली मैपिंग को मेटाडेटा न होने के समान माना जाता है।

मॉडल पैरामीटर

तर्क प्रयास या Cursor Router के optimize_for जैसे मॉडल-विशिष्ट विकल्प पास करने के लिए ModelSelection.params का उपयोग करें। पैरामीटर ID और मान मॉडल के अनुसार अलग-अलग होते हैं। अपने खाते के लिए समर्थित पैरामीटर और प्रीसेट वैरिएंट्स जानने के लिए Cursor.models.list() का उपयोग करें।

from cursor_sdk import Agent, LocalAgentOptions, ModelParameterValue, ModelSelectionagent = Agent.create(    model=ModelSelection(        id="composer-2.5",        params=[ModelParameterValue(id="fast", value="true")],    ),    local=LocalAgentOptions(cwd="."),)

किसी मॉडल के पैरामीटर IDs और प्रीसेट वैरिएंट्स जानने के लिए Cursor.models.list() का उपयोग करें। auto-smart चयन कॉन्ट्रैक्ट के लिए Cursor Router देखें।

Cursor Router

Cursor Router हर स्वचालित अनुरोध के लिए एक मॉडल चुनता है। SDK में, Router optimize_for पैरामीटर वाला auto-smart मॉडल है। यह टीमों और एंटरप्राइज़ के लिए उपलब्ध है। auto-smart के कैटलॉग में दिखने से पहले एंटरप्राइज़ प्रशासकों को टीम के लिए Router सक्षम करना होगा।

Cursor SDK एक एजेंट SDK है, न कि एक स्वतंत्र मॉडल-इन्फ़रेंस या चैट-पूर्णता API। Router, Cursor एजेंट रन के लिए मॉडल चुनता है, जो कार्यस्थान को समझ सकते हैं, उपकरणों को कॉल कर सकते हैं, कमांड चला सकते हैं और फ़ाइलें संपादित कर सकते हैं। Cursor फ़िलहाल मनमाने मॉडल कॉल के लिए किसी raw Router endpoint का दस्तावेज़ीकरण नहीं करता।

लागत, संतुलन या Intelligence चुनें

auto-smart पास करें और optimize_for को स्पष्ट रूप से सेट करें:

उत्पाद labelSDK मान
लागतcost
संतुलनbalanced
Intelligenceintelligence

उत्पाद कॉपी में संतुलन का उपयोग करें। balanced का उपयोग केवल SDK वायर मान के रूप में करें।

import osfrom cursor_sdk import Agent, LocalAgentOptions, ModelParameterValue, ModelSelectionwith Agent.create(    model=ModelSelection(        id="auto-smart",        params=[ModelParameterValue(id="optimize_for", value="balanced")],    ),    local=LocalAgentOptions(cwd=os.getcwd()),) as agent:    run = agent.send("Find and fix the failing authentication test")    result = run.wait()    print(result.status)

हमेशा optimize_for भेजें। इसे न छोड़ें और लीगेसी default मान न भेजें; कैटलॉग के ज़रिए डिस्कवरी ही समर्थित कॉन्ट्रैक्ट है।

मॉडल कैटलॉग में Router खोजें

Cursor.models.list() API key के वर्तमान खाता और टीम के लिए उपलब्ध मॉडल, पैरामीटर की परिभाषाएँ और प्रीसेट वैरिएंट्स लौटाता है। Router उपलब्ध होने पर Cursor Router auto-smart के रूप में दिखाई देता है। टीम व्यवस्थापक Router को अक्षम कर सकते हैं या सदस्यों द्वारा चुने जा सकने वाले ऑप्टिमाइज़ेशन मोड सीमित कर सकते हैं।

किसी विकल्प को हार्ड-कोड करने से पहले कैटलॉग को सत्य का स्रोत मानें:

from cursor_sdk import Cursor, ModelParameterValue, ModelSelectionmodels = Cursor.models.list()router = next((model for model in models if model.id == "auto-smart"), None)optimize_for = next(    (        parameter        for parameter in (router.parameters if router else [])        if parameter.id == "optimize_for"    ),    None,)if router is None or optimize_for is None:    raise RuntimeError(        "Cursor Router is not available for this API key. "        "Verify that Router is enabled for the key's team."    )requested_mode = "balanced"allowed_values = {entry.value for entry in optimize_for.values}if requested_mode not in allowed_values:    raise RuntimeError(        f'Router mode "{requested_mode}" is not enabled for this team.'    )model = ModelSelection(    id=router.id,    params=[ModelParameterValue(id=optimize_for.id, value=requested_mode)],)

हर रन के लिए मोड बदलें

किसी रन के लिए राउटर मोड बदलने हेतु agent.send() में मॉडल ओवरराइड करें:

from cursor_sdk import ModelParameterValue, ModelSelection, SendOptionsrun = agent.send(    "Handle this complex migration",    SendOptions(        model=ModelSelection(            id="auto-smart",            params=[ModelParameterValue(id="optimize_for", value="intelligence")],        ),    ),)

हर रन के मॉडल ओवरराइड स्टिकी होते हैं। बिना ओवरराइड के बाद के send नए चयन का उपयोग करते रहेंगे। हर रन का मॉडल ओवरराइड देखें।

मॉडल ID: auto-smart, auto, और default

चयनअर्थ
optimize_for के साथ auto-smartCursor Router। इसका उपयोग तब करें जब आपको लागत, संतुलन या इंटेलिजेंस चाहिए।
ModelSelection(id="auto")कैटलॉग में कोई विशिष्ट मॉडल न होने पर सर्वर द्वारा चुना गया स्वचालित फॉलबैक। जब आपको स्पष्ट Router मोड चाहिए, तो auto-smart को प्राथमिकता दें।
optimize_for छोड़ना या default भेजनायह समर्थित Router कॉन्ट्रैक्ट नहीं है। हमेशा अनुमत मान खोजें और cost, balanced या intelligence पास करें।

बिलिंग और रूटिंग पूल

  • लागत क्लासिक स्वचालित व्यवहार और बंडल किए गए स्वचालित मूल्य निर्धारण के अनुसार होती है।
  • संतुलन और इंटेलिजेंस Cursor Router का उपयोग करते हैं और आपके प्लान या कॉन्ट्रैक्ट के तहत रूट किए गए मॉडल की दर से बिल किए जाते हैं।
  • अंतर्निहित मॉडल अलग-अलग अनुरोधों के बीच बदल सकता है। दोहराई जा सकने वाली तुलनाओं के लिए, निर्धारित मॉडल ID को प्राथमिकता दें।
  • एंटरप्राइज़ मॉडल अनुमति सूचियाँ रूटिंग पूल को निर्धारित करती हैं। आवश्यक मॉडलों को ब्लॉक करने से Router अक्षम हो सकता है।

वर्तमान दरों और रूटिंग पूल के लिए, Cursor Router और मॉडल और कीमतें देखें।

अनुपलब्ध Router का समस्या निवारण

अगर auto-smart उपलब्ध नहीं है या किसी ऑप्टिमाइज़ेशन मोड को अस्वीकार कर दिया जाता है:

  1. Cursor.models.list() कॉल करें।
  2. पुष्टि करें कि परिणाम में auto-smart मौजूद है।
  3. पुष्टि करें कि optimize_for में आपका इच्छित मान शामिल है (cost, balanced या intelligence)।
  4. पुष्टि करें कि API key से संबद्ध टीम के लिए Router सक्षम है।
  5. अगर आप एक से अधिक टीमों के सदस्य हैं, तो पुष्टि करें कि कुंजी अपेक्षित टीम संदर्भ में काम कर रही है।
  6. अगर Router उपलब्ध नहीं है या कोई मान्य अंतर्निहित मॉडल नहीं चुन सकता, तो टीम की मॉडल एक्सेस नीति जांचें।

Raw डिक्शनरी

एप्लिकेशन कोड के लिए टाइप्ड डेटाक्लास बेहतर हैं, क्योंकि IDE ऑटोकम्प्लीट और टाइप चेकिंग अधिक प्रभावी ढंग से काम करते हैं। SDK छोटी स्क्रिप्ट्स या बाहरी रूप से दिए गए JSON के लिए सामान्य डिक्शनरी भी स्वीकार करता है। स्नेक-केस कुंजियों को सामान्यीकृत किया जाता है।

from cursor_sdk import Agentwith Agent.create(    {        "api_key": "crsr_key",        "model": {"id": "composer-2.5"},        "local": {"cwd": "."},    }) as agent:    ...

एजेंट

Agent.create(), Agent.resume(), client.agents.create() और client.agents.resume() से प्राप्त हैंडल।

class Agent:    agent_id: str    model: ModelSelection | None    client: CursorClient    def send(        self,        message: str | Mapping[str, Any] | UserMessage,        options: SendOptions | Mapping[str, Any] | None = None,        *,        idempotency_key: str | None = None,    ) -> Run: ...    def reload(self) -> None: ...    def close(self) -> None: ...    def list_messages(        self, options: Mapping[str, Any] | None = None    ) -> list[AgentMessage]: ...    def list_artifacts(self) -> list[SDKArtifact]: ...    def download_artifact(self, path: str) -> bytes: ...    def get_usage(self, *, run_id: str | None = None) -> AgentUsage: ...    def archive(self, options: Mapping[str, Any] | None = None) -> None: ...    def unarchive(self, options: Mapping[str, Any] | None = None) -> None: ...    def delete(self, options: Mapping[str, Any] | None = None) -> None: ...
सदस्यविवरण
agent_idस्थायी एजेंट पहचानकर्ता। स्थानीय के लिए agent-<uuid>, क्लाउड के लिए bc-<uuid>
modelवर्तमान टाइप किया गया मॉडल चयन। मॉडल ओवरराइड के साथ सफलतापूर्वक भेजने के बाद अपडेट होता है।
sendदिए गए प्रॉम्प्ट के साथ नया रन शुरू करें। Run हैंडल लौटाता है।
reloadमुक्त किए बिना फाइलसिस्टम कॉन्फ़िगरेशन (हुक्स, प्रोजेक्ट MCP, उप-एजेंट्स) फिर से पढ़ें।
closeएजेंट बंद करें और संसाधन मुक्त करें।
list_messagesएजेंट के संदेश इतिहास की सूची दें।
list_artifactsएजेंट द्वारा बनाई गई फ़ाइलों की सूची दें (केवल क्लाउड; स्थानीय में खाली लौटाता है)।
download_artifactपाथ के आधार पर फ़ाइल डाउनलोड करें (केवल क्लाउड; स्थानीय में त्रुटि होती है)।
get_usageएजेंट के लिए बिल किए गए टोकन उपयोग और डॉलर लागत प्राप्त करें।
archive / unarchive / deleteक्लाउड एजेंट का जीवनचक्र प्रबंधित करें।

स्वचालित क्लीनअप के लिए context manager का उपयोग करें:

with Agent.create(model="composer-2.5", local=LocalAgentOptions(cwd=".")) as agent:    print(agent.send("Explain this repository").text())

जब आप client= दिए बिना सिंक Agent.* या Cursor.* हेल्पर्स का उपयोग करते हैं, तो SDK मॉड्यूल-स्तरीय डिफ़ॉल्ट क्लाइंट शुरू करता है या उसका पुन: उपयोग करता है। प्रोसेस से बाहर निकलते समय यह अपने-आप बंद हो जाता है, और आप इसे स्पष्ट रूप से भी बंद कर सकते हैं:

from cursor_sdk import close_default_clientclose_default_client()

Agent.prompt()

Agent.prompt(    message: str | Mapping[str, Any] | UserMessage,    options: AgentOptions | Mapping[str, Any] | None = None,    *,    client: CursorClient | None = None,) -> RunResult

वन-शॉट सुविधा: एक एजेंट बनाती है, एकल प्रॉम्प्ट भेजती है, रन पूरा होने तक प्रतीक्षा करती है और संसाधन मुक्त करती है।

from cursor_sdk import Agent, AgentOptions, LocalAgentOptionsresult = Agent.prompt(    "What does the auth middleware do?",    AgentOptions(model="composer-2.5", local=LocalAgentOptions(cwd=".")),)print(result.result)

असिंक्रोनस समकक्ष (मानकर कि आपके पास पहले से एक AsyncClient खुला है):

from cursor_sdk import AgentOptions, AsyncAgent, LocalAgentOptionsresult = await AsyncAgent.prompt(    "What does the auth middleware do?",    AgentOptions(model="composer-2.5", local=LocalAgentOptions(cwd=".")),    client=client,)

CursorClient

स्पष्ट जीवनचक्र नियंत्रण, कस्टम ब्रिज endpoint, कस्टम HTTP विकल्प या एक ही process में कई कार्यस्थान के लिए CursorClient का उपयोग करें। Client उपनाम के रूप में भी उपलब्ध है।

from cursor_sdk import CursorClient, LocalAgentOptionswith CursorClient.launch_bridge(workspace=".") as client:    with client.agents.create(        model="composer-2.5",        api_key="crsr_key",        local=LocalAgentOptions(cwd="."),    ) as agent:        print(agent.send("Summarize what this repository does").text())

संसाधन

स्पष्ट क्लाइंट संसाधन नेमस्पेस उपलब्ध कराते हैं:

संसाधनसिंक मेथड के उदाहरणएसिंक मेथड के उदाहरण
agentsclient.agents.create(...), client.agents.list(...), client.agents.get(...)await client.agents.create(...), await client.agents.list(...)
modelsclient.models.list()await client.models.list()
repositoriesclient.repositories.list()await client.repositories.list()

client.create_agent(...) और client.list_agents(...) जैसी शीर्ष-स्तर मेथड भी उपलब्ध हैं, लेकिन एप्लिकेशन कोड के लिए संसाधन नेमस्पेस का उपयोग करना बेहतर है।

कस्टम HTTP क्लाइंट

सिंक और async, दोनों क्लाइंट प्रॉक्सी, ट्रांसपोर्ट और अन्य उन्नत HTTP कॉन्फ़िगरेशन के लिए कस्टम httpx क्लाइंट स्वीकार करते हैं:

from cursor_sdk import CursorClient, DefaultHttpxClientwith CursorClient.launch_bridge(    workspace=".",    http_client=DefaultHttpxClient(proxy="http://proxy.example.com"),) as client:    ...
from cursor_sdk import AsyncClient, DefaultAsyncHttpxClientasync with await AsyncClient.launch_bridge(    workspace=".",    http_client=DefaultAsyncHttpxClient(proxy="http://proxy.example.com"),) as client:    ...

DefaultHttpxClient और DefaultAsyncHttpxClient SDK के डिफ़ॉल्ट टाइमआउट और रीडायरेक्ट व्यवहार को बनाए रखते हैं। इसके बजाय, सामान्य httpx.Client और httpx.AsyncClient httpx के डिफ़ॉल्ट्स का उपयोग करते हैं।

टाइमआउट और पुनः प्रयास कॉन्फ़िगर करना

दोनों क्लाइंट with_options(...) उपलब्ध कराते हैं, जो कनेक्शन सेटिंग्स साझा करने वाली एक शैलो कॉपी लौटाता है और डिफ़ॉल्ट्स को override करता है। सभी अनुरोधों के लिए timeout का उपयोग करें, या unary_timeout और stream_timeout को अलग-अलग सेट करें। max_retries क्लाइंट पुनः प्रयासों को नियंत्रित करता है:

short = client.with_options(timeout=5.0, max_retries=2)agent = short.agents.create(model="composer-2.5", local=LocalAgentOptions(cwd="."))

असिंक्रोनस समकक्ष:

short_async = async_client.with_options(timeout=5.0, max_retries=2)agent = await short_async.agents.create(model="composer-2.5", local=LocalAgentOptions(cwd="."))

संदेश भेजना

हर agent.send() एक Run लौटाता है। हर await async_agent.send() एक AsyncRun लौटाता है। एजेंट अलग-अलग रन के दौरान बातचीत का संदर्भ बनाए रखता है; रन किसी एक प्रॉम्प्ट के कार्य की इकाई है।

print(agent.send("Find the bug in src/auth.py").text())# उसी एजेंट के लिए बातचीत का पूरा संदर्भ बना रहता है।print(agent.send("Fix it and add a regression test").text())

असिंक्रोनस समकक्ष:

run = await agent.send("Find the bug in src/auth.py")print(await run.text())run = await agent.send("Fix it and add a regression test")print(await run.text())

टेक्स्ट के साथ छवियाँ भेजने के लिए:

run = agent.send(    {        "text": "What's in this screenshot?",        "images": [{"data": base64_png, "mime_type": "image/png"}],    })

आप सहायक डेटाक्लास का भी उपयोग कर सकते हैं। SDKImage.from_file(path) डिस्क से पढ़ता है और आपके लिए base64 एन्कोडिंग करता है:

from cursor_sdk import SDKImage, UserMessagerun = agent.send(    UserMessage(        text="What's in this screenshot?",        images=[SDKImage.from_file("screenshot.png")],    ))

SDKImage.data_image(base64_data, mime_type) और SDKImage.url_image(url) उन कॉलर के लिए भी उपलब्ध हैं जिनके पास पहले से एन्कोडेड बाइट्स या रिमोट URL मौजूद है।

चलाएँ

class Run:    id: str    agent_id: str    status: str  # "running" | "finished" | "error" | "cancelled" | "expired"    result: str    model: ModelSelection | None    duration_ms: int    git: RunGitInfo | None    created_at: str | None    usage: TokenUsage | None  # संचयी; लाइव हैंडल की Property    def stream(self) -> Iterator[SDKMessage]: ...    def messages(self) -> Iterator[SDKMessage]: ...    def events(self) -> Iterator[RunStreamEvent]: ...    def iter_text(self) -> Iterator[str]: ...    def text(self) -> str: ...    def wait(self) -> RunResult: ...    def cancel(self) -> None: ...    def conversation(self) -> list[ConversationTurn]: ...    def conversation_json(self) -> str: ...    def observe(self, *, after_offset: str | None = None) -> Iterator[RunStreamEvent]: ...    def supports(self, operation: str) -> bool: ...    def unsupported_reason(self, operation: str) -> str | None: ...    def on_did_change_status(        self, listener: Callable[[str], None]    ) -> Callable[[], None]: ...

run.stream() , run.messages() का उपनाम है। run को सीधे इटरेट करने पर run.events() की तरह ही RunStreamEvent एनवेलप्स मिलते हैं।

AsyncRun में usage सहित वही स्टेट फ़ील्ड उपलब्ध हैं। I/O करने वाले मेथड async हैं: async for message in run.stream(), async for message in run.messages(), async for event in run.events(), async for text in run.iter_text(), await run.text(), await run.wait(), await run.cancel(), await run.conversation(), await run.conversation_json(), और async for event in run.observe()

स्ट्रीमिंग

run = agent.send("Find the bug in src/auth.py")for message in run.messages():    if message.type == "assistant":        for block in message.message.content:            if block.type == "text":                print(block.text, end="")    elif message.type == "thinking":        print(message.text, end="")    elif message.type == "tool_call":        print(f"[tool] {message.name}: {message.status}")    elif message.type == "status":        print(f"[status] {message.status}")    elif message.type == "usage":        print(f"[usage] turn total={message.usage.total_tokens}")

रन स्ट्रीम का उपभोग केवल एक बार किया जा सकता है। run.messages(), run.events() और run.iter_text() सभी उसी अंतर्निहित स्ट्रीम से डेटा लेते हैं और उसे आगे बढ़ाते हैं। स्ट्रीम पूरी होने पर, रन में अंतिम परिणाम (run.result, run.status, run.usage, run.git, ...) उपलब्ध होता है। बचे हुए ईवेंट्स को पूरा पढ़ने और typed RunResult लौटाने के लिए run.wait() कॉल करें।

बिना स्ट्रीमिंग के प्रतीक्षा

result = run.wait()print(result.status)       # "finished" | "error" | "cancelled" | "expired"print(result.result)       # उपलब्ध होने पर, अंतिम सहायक टेक्स्टprint(result.model)        # इस रन के लिए उपयोग किया गया resolved ModelSelectionprint(result.duration_ms)print(result.usage)        # संचयी TokenUsage, या उपलब्ध न होने पर Noneprint(result.git)          # क्लाउड पर RunGitInfo

Async समकक्ष:

result = await run.wait()

टोकन उपयोग

रनटाइम उपलब्ध कराने पर रन टोकन उपयोग की रिपोर्ट करते हैं। लाइव हैंडल पर run.usage से संचयी कुल पढ़ें (स्ट्रीमिंग के दौरान या wait() के बाद), या run.wait() से लौटे RunResult पर result.usage से। दोनों में उपयोग रिपोर्ट करने वाले हर टर्न का कुल TokenUsage होता है और यदि किसी टर्न ने उपयोग रिपोर्ट नहीं किया हो, तो दोनों None होते हैं—जैसे ऐसा रद्द किया गया रन जिसने कोई टर्न पूरा नहीं किया, ऐसा रनटाइम जो उपयोग उपलब्ध नहीं कराता, या अलग किया गया क्लाउड स्नैपशॉट जिसका उपयोग अभी तक समायोजित नहीं हुआ है।

@dataclass(frozen=True)class TokenUsage:    input_tokens: int    output_tokens: int    cache_read_tokens: int    cache_write_tokens: int    total_tokens: int    reasoning_tokens: int | None = None
फ़ील्डविवरण
input_tokensमॉडल को भेजे गए प्रॉम्प्ट टोकन।
output_tokensमॉडल द्वारा जनरेट किए गए टोकन।
cache_read_tokensप्रॉम्प्ट कैश से प्राप्त टोकन।
cache_write_tokensप्रॉम्प्ट कैश में लिखे गए टोकन।
total_tokensinput_tokens + output_tokens + cache_read_tokens + cache_write_tokens। इसमें reasoning_tokens शामिल नहीं हैं।
reasoning_tokensतर्क टोकन, जो output_tokens का एक उपसमूह हैं। मॉडल या रनटाइम द्वारा रिपोर्ट न किए जाने पर None
result = run.wait()if result.usage is not None:    print(f"total: {result.usage.total_tokens}")    print(f"in: {result.usage.input_tokens}, out: {result.usage.output_tokens}")    print(        f"cache read/write: {result.usage.cache_read_tokens}/{result.usage.cache_write_tokens}"    )else:    print("no usage reported for this run")

reasoning_tokens पहले से ही output_tokens में शामिल होते हैं, इसलिए दोहरी गणना से बचने के लिए total_tokens में इन्हें शामिल नहीं किया जाता।

स्ट्रीमिंग के दौरान हर टर्न के आंकड़ों के लिए, usage स्ट्रीम इवेंट (SDKUsageMessage) को हैंडल करें। यह उपयोग की रिपोर्ट करने वाले हर टर्न के अंत में एक बार ट्रिगर होता है और उस टर्न का TokenUsage प्रदान करता है। run.usage और result.usage पूरे रन में संचयी रहते हैं। स्ट्रीम टर्न के बाद, हैंडल इन जोड़े गए कुलों को प्राथमिकता देता है; अन्यथा, ब्रिज द्वारा उपलब्ध कराए जाने पर यह wait() या get_run / list_runs स्नैपशॉट से उपयोग की जानकारी लेता है।

for message in run.messages():    if message.type == "usage":        print(f"turn used {message.usage.total_tokens} tokens")# या wait के बाद / संदेशों को स्वयं पढ़े बिना:result = run.wait()print(run.usage, result.usage)

Async समकक्ष: async for message in run.messages() और await run.wait()run.usage, AsyncRun पर अब भी एक सिंक Property है।

TokenUsage को cursor_sdk से एक्सपोर्ट किया जाता है (उन्नत कॉलरों के लिए to_token_usage / sum_token_usage भी उपलब्ध हैं)। वायर JSON में camelCase (inputTokens, …) का उपयोग होता है; Python डेटाक्लास snake_case का उपयोग करती हैं।

टोकन की संख्या रनटाइम द्वारा रिपोर्ट की गई संख्या होती है; इनका लागत से कोई संबंध नहीं है। बिल किए गए उपयोग और किसी एजेंट के रन की डॉलर लागत के लिए, agent.get_usage() को कॉल करें।

टेक्स्ट आउटपुट पढ़ना

iter_text() स्ट्रीमिंग के दौरान सहायक टेक्स्ट देता है। text() अंतिम टर्मिनल टेक्स्ट लौटाता है और रन के अभी भी चल रहे होने पर wait() का इंतज़ार करता है।

for chunk in run.iter_text():    print(chunk, end="")final_text = run.text()

असिंक्रोनस समकक्ष:

async for chunk in run.iter_text():    print(chunk, end="")final_text = await run.text()

रन रद्द करना

run.cancel()

असिंक्रोनस समकक्ष:

await run.cancel()

run.cancel() सक्रिय रन को रद्द करने का अनुरोध करता है। स्थिति "cancelled" हो जाती है, लाइव स्ट्रीम रुक जाती है, चल रहे टूल कॉल्स रुक जाते हैं, और run.wait() status: "cancelled" के साथ पूरा होता है। आंशिक आउटपुट (अब तक लिखा गया सहायक टेक्स्ट) Run ऑब्जेक्ट में बना रहता है।

पहले से ही समाप्त हो चुके रन ("finished", "error", "cancelled", "expired") को रद्द करने पर UnsupportedRunOperationError उत्पन्न होता है। संदेह होने पर run.status से जाँच करें:

if run.status == "running":    run.cancel()

रन की स्थिति पढ़ना

print(run.id)print(run.status)  # "running" | "finished" | "error" | "cancelled" | "expired"stop = run.on_did_change_status(lambda status: print(f"status changed to {status}"))stop()  # लिस्नर हटाएँturns = run.conversation()

run.conversation() एक typed list[ConversationTurn] लौटाता है। लाइव स्ट्रीम को subscribe किए बिना structured history को render या persist करने के लिए इसका उपयोग करें। run.conversation_json() raw JSON string लौटाता है।

async runs के लिए, await run.conversation() और await run.conversation_json() का उपयोग करें।

प्रति-रन मॉडल ओवरराइड

agent.send() को दिया गया model उस रन के लिए एजेंट के चयन को override करता है और फिर स्टिकी हो जाता है: override के बिना बाद के send नए मॉडल का उपयोग करते रहते हैं। वापस स्विच करने के लिए, कोई दूसरा model override दें या agent.model से मौजूदा चयन पढ़ें।

from cursor_sdk import ModelParameterValue, ModelSelection, SendOptionsrun = agent.send(    "Plan the refactor",    SendOptions(        model=ModelSelection(            id="composer-2.5",            params=[ModelParameterValue(id="fast", value="true")],        ),    ),)

run.model और result.model इस रन में उपयोग किए गए चयन को दर्शाते हैं और रन शुरू होने के बाद इन्हें बदला नहीं जा सकता।

प्रति-रन एनवायरनमेंट वेरिएबल्स

क्लाउड एजेंट्स एक रन के लिए एनवायरनमेंट वेरिएबल्स भी स्वीकार कर सकते हैं। SendOptions में cloud.env_vars पास करें। ये मान केवल उस रन के लिए एजेंट के shell में इंजेक्ट किए जाते हैं — रन समाप्त होने पर इन्हें VM से हटा दिया जाता है और अगला रन इन्हें नहीं देखता। यह उन क्रेडेंशियल्स के लिए उपयुक्त है जो टर्न के बीच बदलते रहते हैं, जैसे कोई अल्पकालिक deploy टोकन जिसे आप एजेंट से उपयोग करने के लिए कहने से ठीक पहले बनाते हैं।

from cursor_sdk import CloudSendOptions, SendOptionsrun = agent.send(    "Deploy the preview environment",    SendOptions(        cloud=CloudSendOptions(env_vars={"DEPLOY_TOKEN": mint_short_lived_token()}),    ),)

अगर किसी रन-स्कोप्ड वेरिएबल का नाम CloudAgentOptions के env_vars में मौजूद एजेंट-स्कोप्ड वेरिएबल के नाम जैसा है, तो उस रन में रन-स्कोप्ड मान लागू होगा और अगले रन में एजेंट-स्कोप्ड मान फिर से लागू हो जाएगा।

प्रति-रन वेरिएबल पहले send पर भी काम करते हैं। SDK इन्हें एजेंट बनाते समय, शुरुआती रन के स्कोप में भेजता है, इसलिए ये एजेंट पर persist नहीं होते। एजेंट-स्कोप्ड वेरिएबल्स की तरह, ये स्थिर अवस्था में एन्क्रिप्टेड होते हैं और इनके नाम CURSOR_ से शुरू नहीं हो सकते।

प्रति-रन एनवायरनमेंट वेरिएबल्स सिर्फ़ क्लाउड एजेंट्स के लिए हैं और सार्वजनिक रिपॉज़िटरीज़ पर चल रहे एजेंटों के लिए उपलब्ध नहीं हैं। स्थानीय एजेंटों के लिए, एजेंट process आपके परिवेश को इनहेरिट करता है, इसलिए send() कॉल करने से पहले process पर वेरिएबल सेट करें।

बातचीत मोड

यह नियंत्रित करने के लिए कि रन पहले एक्सप्लोर करके योजना बनाए या सीधे परिवर्तन लागू करे, mode="plan" या mode="agent" पास करें। उत्पाद में योजना मोड कैसे काम करता है, यह जानने के लिए योजना मोड देखें।

पहला रन शुरू करने के लिए Agent.create() को पास किए गए AgentOptions में mode सेट करें। फॉलो-अप agent.send() कॉल में, बातचीत का मौजूदा मोड बनाए रखने के लिए mode छोड़ दें या केवल उस रन के लिए मोड बदलने हेतु mode पास करें।

from cursor_sdk import Agent, AgentOptions, CloudAgentOptions, CloudRepository, SendOptionswith Agent.create(    AgentOptions(        model="composer-2.5",        mode="plan",        cloud=CloudAgentOptions(            repos=[CloudRepository(url="https://github.com/your-org/your-repo")],        ),    )) as agent:    agent.send("Design the auth refactor").wait()    agent.send(        "Looks good, start building",        SendOptions(mode="agent"),    ).wait()

raw डेल्टा स्ट्रीमिंग

निम्न-स्तरीय अपडेट के लिए SendOptions में on_delta और on_step कॉलबैक पास करें। सिंक कॉलबैक इनलाइन कॉल किए जाते हैं। async कॉलबैक सिंक या async हो सकते हैं; अगले इवेंट को संसाधित करने से पहले awaitable रिटर्न मानों की प्रतीक्षा की जाती है।

from cursor_sdk import SendOptionsdef on_delta(update):    if update.type in ("text-delta", "thinking-delta"):        print(update.text, end="")run = agent.send(    "Refactor the utils module",    SendOptions(on_delta=on_delta, on_step=lambda step: print(f"[step] {step.type}")),)run.wait()

विशिष्ट अपडेट और चरण उपवर्ग cursor_sdk.events में हैं:

from cursor_sdk.events import TextDeltaUpdate, ToolCallStartedUpdateif isinstance(update, TextDeltaUpdate):    print(update.text)

पश्चगामी संगतता के लिए इन्हें cursor_sdk से अब भी आयात किया जा सकता है, लेकिन नए कोड में इन्हें cursor_sdk.events से आयात करना चाहिए।

SendOptions

Propertyप्रकारविवरण
modelstr | ModelSelection | Mapping[str, Any]हर भेजे जाने वाले संदेश के लिए मॉडल override। छोड़े जाने पर agent.model का उपयोग होता है। सफलतापूर्वक संदेश भेजने के बाद स्टिकी रहता है।
mode"agent" | "plan"हर भेजे जाने वाले संदेश के लिए बातचीत मोड override। फ़ॉलो-अप में छोड़े जाने पर बातचीत का मौजूदा मोड बना रहता है।
mcp_serversMapping[str, McpServerConfig]इनलाइन MCP सर्वर परिभाषाएँ। इस रन के लिए निर्माण के समय के सर्वरों को पूरी तरह बदल देता है।
cloud.env_varsMapping[str, str]केवल क्लाउड एजेंट्स के लिए। इस रन में इंजेक्ट किए गए प्रति-चलाएँ एनवायरनमेंट वेरिएबल्स, जो रन समाप्त होने पर हटा दिए जाते हैं। केवल इस रन के लिए नाम के आधार पर एजेंट-स्कोप्ड env_vars को override करता है।
local.forceboolकेवल स्थानीय एजेंट्स के लिए। डिफ़ॉल्ट None (अनसेट) है। यह संदेश शुरू करने से पहले अटके हुए सक्रिय रन को समाप्त करने के लिए True सेट करें। क्लाउड सर्वर-साइड 409 agent_busy लौटाता है, इसलिए इसके समकक्ष की आवश्यकता नहीं है।
idempotency_keystrसंदेश भेजने के लिए वैकल्पिक क्लाइंट-जनित आइडेम्पोटेंसी कुंजी।
on_stepCallable[[ConversationStep], Any]हर पूर्ण बातचीत चरण (टेक्स्ट, सोच या टूल बैच) के बाद कॉलबैक।
on_deltaCallable[[InteractionUpdate], Any]हर रॉ InteractionUpdate के लिए कॉलबैक।

अगले तीन अनुभाग SDKMessage, InteractionUpdate और ConversationTurn के विस्तृत संदर्भ हैं। पहली बार पढ़ते समय इन्हें सरसरी तौर पर देखें या छोड़ दें; एजेंट फिर से शुरू करना आगे की जानकारी देता है।

स्ट्रीम ईवेंट्स

run.messages() टाइप किए गए SDK संदेश डेटाक्लास देता है। message.type के आधार पर प्रकार पहचानें। रनटाइम द्वारा उपलब्ध होने पर, सभी संदेशों में agent_id और run_id शामिल होते हैं।

SDKMessage = (    SDKSystemMessage    | SDKUserMessageEvent    | SDKAssistantMessage    | SDKThinkingMessage    | SDKToolUseMessage    | SDKStatusMessage    | SDKTaskMessage    | SDKRequestMessage    | SDKUsageMessage    | Mapping[str, Any])
typeDataclassमुख्य फ़ील्ड
"system"SDKSystemMessagesubtype, model, tools
"user"SDKUserMessageEventmessage.content
"assistant"SDKAssistantMessageTextBlock और ToolUseBlock मानों वाला message.content
"thinking"SDKThinkingMessagetext, thinking_duration_ms
"tool_call"SDKToolUseMessagecall_id, name, status, args, result, truncated
"status"SDKStatusMessagestatus, message
"task"SDKTaskMessagestatus, text
"request"SDKRequestMessagerequest_id
"usage"SDKUsageMessageusage (TokenUsage)

अधिकांश टूल कॉल्स के लिए SDKToolUseMessage दो बार उत्सर्जित होता है: पहली बार status="running" और भरे हुए args के साथ, फिर पूर्ण होने पर status="completed" (या "error") और भरे हुए result के साथ। truncated बताता है कि पेलोड बहुत बड़ा होने पर SDK ने args या result को काट-छाँट किया है या नहीं।

टोकन उपयोग की रिपोर्ट करने वाले हर टर्न के अंत में SDKUsageMessage एक बार उत्सर्जित होता है और उसमें उस टर्न का TokenUsage होता है। सभी टर्न का संचयी कुल run.usage और result.usage में रहता है। टोकन उपयोग देखें।

@dataclass(frozen=True)class SDKUsageMessage:    type: Literal["usage"]    agent_id: str    run_id: str    usage: TokenUsage

परिणाम डेटा (अंतिम टेक्स्ट, मॉडल, अवधि, कुल टोकन उपयोग, git मेटाडेटा) स्ट्रीम पूरी होने के बाद Run ऑब्जेक्ट पर उपलब्ध होता है। इसे पढ़ने के लिए run.wait() का उपयोग करें। रनटाइम द्वारा रिपोर्ट किए जाने पर इसमें result.usage भी शामिल होता है।

टूल कॉल स्कीमा स्थिर नहीं है। tool_call इवेंट्स के args और result पेलोड हर उपकरण की आंतरिक संरचना को दर्शाते हैं और उपकरणों के विकसित होने के साथ बदल सकते हैं। उपकरणों के नाम भी बदले या प्रतिस्थापित किए जा सकते हैं। args और result को टाइप-रहित डेटा मानें और सावधानी से पार्स करें। इवेंट एनवेलप (type, call_id, name, status) स्थिर है।

run.events() निम्न-स्तरीय RunStreamEvent एनवेलप देता है। ऑफ़सेट, टर्मिनल परिणाम एनवेलप या raw इंटरैक्शन अपडेट की ज़रूरत होने पर इसका उपयोग करें:

for event in run.events():    print(event.kind, event.offset)

इंटरैक्शन अपडेट

InteractionUpdate, agent.send() में on_delta कॉलबैक को भेजा जाने वाला raw डेल्टा प्रकार है। ये अपडेट SDKMessage ईवेंट्स से अधिक सूक्ष्म होते हैं: टेक्स्ट टोकन-दर-टोकन स्ट्रीम होता है और args जुड़ने के साथ टूल कॉल्स अपनी आंशिक स्थिति रिपोर्ट करते हैं।

InteractionUpdate = (    TextDeltaUpdate    | ThinkingDeltaUpdate    | ThinkingCompletedUpdate    | ToolCallStartedUpdate    | ToolCallCompletedUpdate    | PartialToolCallUpdate    | TokenDeltaUpdate    | StepStartedUpdate    | StepCompletedUpdate    | TurnEndedUpdate    | UserMessageAppendedUpdate    | SummaryUpdate    | SummaryStartedUpdate    | SummaryCompletedUpdate    | ShellOutputDeltaUpdate    | UnknownInteractionUpdate    | Mapping[str, Any])

PartialToolCallUpdate मॉडल द्वारा कमिट किए जाने से पहले टूल कॉल में आर्ग्युमेंट्स स्ट्रीम करते समय उत्सर्जित होता है। SDKToolUseMessage.args पर लागू वही स्थिरता अस्वीकरण यहाँ भी लागू होता है।

बातचीत के प्रकार

रन का संरचित प्रति-टर्न दृश्य, जो run.conversation() से लौटता है। हर आइटम एक रैपर है, जिसमें टर्न का type डिस्क्रिमिनेटर और turn में टाइप किया गया पेलोड होता है।

@dataclass(frozen=True)class ConversationTurn:    type: str  # "agentConversationTurn" | "shellConversationTurn"    turn: AgentConversationTurn | ShellConversationTurn | Mapping[str, Any]@dataclass(frozen=True)class AgentConversationTurn:    user_message: Mapping[str, Any] | None = None    steps: Sequence[ConversationStep] = ()@dataclass(frozen=True)class ShellConversationTurn:    shell_command: ShellCommand | None = None    shell_output: ShellOutput | None = NoneConversationStep = (    AssistantConversationStep    | ToolCallConversationStep    | ThinkingConversationStep    | Mapping[str, Any])

turn.type के आधार पर अंतर करें और turn.turn से पेलोड पढ़ें:

for turn in run.conversation():    if turn.type == "agentConversationTurn":        for step in turn.turn.steps:            print(step.type)    elif turn.type == "shellConversationTurn":        print(turn.turn.shell_command, turn.turn.shell_output)

on_step कॉलबैक में run.conversation() हर ConversationStep पर ट्रिगर होता है, हर टर्न पर नहीं। टूल-कॉल वाले बातचीत चरणों में Mapping[str, Any] पेलोड होता है। टूल-कॉल पेलोड के विवरण को टाइप-रहित डेटा मानें; स्ट्रीम ईवेंट्स के अंतर्गत स्थिरता संबंधी नोट देखें।

एजेंट फिर से शुरू करना

Agent.resume(    agent_id: str,    options: AgentOptions | Mapping[str, Any] | None = None,    *,    client: CursorClient | None = None,) -> Agent

ID के ज़रिए किसी मौजूदा एजेंट से फिर से जुड़ने के लिए Agent.resume() या client.agents.resume() का उपयोग करें। सामान्य स्थितियाँ: पहले शुरू किए गए लंबे समय तक चलने वाले क्लाउड एजेंट से पुनः कनेक्ट करना या स्थानीय प्रक्रिया के पुनः आरंभ होने के बाद बातचीत जारी रखना। रनटाइम का पता ID प्रीफ़िक्स से स्वचालित रूप से लगाया जाता है (bc- क्लाउड है, अन्य सभी स्थानीय हैं)।

agent = Agent.resume("bc-abc123")run = agent.send("Also update the changelog")run.wait()

असिंक्रोनस समकक्ष:

agent = await client.agents.resume("bc-abc123")run = await agent.send("Also update the changelog")await run.wait()

फिर से शुरू करने पर agent.model का मान None होता है, जब तक कि आप model को दोबारा पास न करें। इनलाइन MCP सर्वर फिर से शुरू करने पर सहेजे नहीं जाते; उनमें अक्सर सीक्रेट्स होते हैं और वे केवल मेमोरी में रहते हैं। फिर से शुरू करने पर उन्हें दोबारा पास करें, या उन सर्वरों के लिए फ़ाइल-आधारित MCP कॉन्फ़िगरेशन (.cursor/mcp.json और local.setting_sources) का उपयोग करें जिन्हें बने रहना चाहिए।

स्थानीय संग्रहण

स्थानीय एजेंट ब्रिज के माध्यम से बातचीत की स्थिति और रन मेटाडेटा को सहेजते हैं, इसलिए फ़ॉलो-अप्स और Agent.resume() प्रक्रिया के पुनः आरंभ के बाद भी बने रहते हैं। ब्रिज डिफ़ॉल्ट रूप से इन्हें डिस्क पर हर कार्यस्थान के लिए अलग स्टेट रूट में रखता है। क्लाउड एजेंट सर्वर-साइड डेटा सहेजते हैं, इसलिए कहीं से भी किसी क्लाउड एजेंट को फिर से शुरू करने पर वही बातचीत मिलती है।

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

from cursor_sdk import CursorClientwith CursorClient.launch_bridge(workspace="/path/to/repo") as client:    agents = client.agents.list(runtime="local", cwd="/path/to/repo")    info = client.agents.get(agents.items[0].agent_id, cwd="/path/to/repo")

एजेंट और रन की जाँच

सूची, प्राप्त करने और पेजिनेशन API के लिए CursorClient का उपयोग करें।

from cursor_sdk import CursorClientwith CursorClient.launch_bridge(workspace=".") as client:    agents = client.agents.list(runtime="local", cwd=".")    for agent_info in agents.auto_paging_iter():        print(agent_info.agent_id)    info = client.agents.get(agents.items[0].agent_id)    runs = client.agents.list_runs(info.agent_id)    run = client.agents.get_run(runs.items[0].id)

असिंक्रोनस समकक्ष:

agents = await client.agents.list(runtime="local", cwd=".")async for agent_info in agents.auto_paging_iter():    print(agent_info.agent_id)info = await client.agents.get(agents.items[0].agent_id)runs = await client.agents.list_runs(info.agent_id)run = await client.agents.get_run(runs.items[0].id)

संदेश इतिहास पढ़ने के लिए एजेंट हैंडल पर agent.list_messages() का उपयोग करें। जब आपके पास केवल ID हो, तो उसी कॉल के लिए Agent.messages.list(agent_id) typed-attribute सुविधा प्रदान करता है।

एजेंट हैंडल के बिना रन प्राप्त करने के लिए Agent.get_run(run_id) या client.agents.get_run(run_id) का उपयोग करें। इसे रद्द करने के लिए Agent.cancel_run(run_id, agent_id=...) या client.agents.cancel_run(run_id, agent_id=...) का उपयोग करें। असिंक्रोनस क्लाइंट मेथड्स await किए जा सकते हैं और उन्हीं आर्ग्युमेंट्स का उपयोग करते हैं।

AgentMessage, स्ट्रीम किए गए SDKMessage से अलग है:

@dataclass(frozen=True)class AgentMessage:    type: str    uuid: str    agent_id: str    message: Any = None

सूची एंडपॉइंट्स ListResult[T] लौटाते हैं। .items और .next_cursor का सीधे उपयोग करें, for item in page से मौजूदा पृष्ठ के आइटम पर लूप करें या .auto_paging_iter() से सभी पृष्ठों के आइटम पर लूप करें। Async सूची एंडपॉइंट्स AsyncListResult[T] लौटाते हैं; async for item in page मौजूदा पृष्ठ के आइटम पर लूप करता है और async for item in page.auto_paging_iter() परिणाम सेट के हर पृष्ठ के आइटम पर लूप करता है।

SDKAgentInfo

Agent.list(), Agent.get(), client.agents.list() और client.agents.get() से लौटाए गए मेटाडेटा का स्वरूप।

@dataclass(frozen=True)class SDKAgentInfo:    agent_id: str    name: str    summary: str    last_modified: str | None = None    status: str | None = None  # "running" | "finished" | "error"    created_at: str | None = None    archived: bool = False    runtime: Literal["local", "cloud"] | None = None    cwd: str = ""    env: CloudEnvironment | None = None    repos: Sequence[str] = ()    metadata: Mapping[str, str] = {}  # CloudAgentOptions.metadata से; स्थानीय एजेंट के लिए रिक्त

क्लाउड एजेंट जीवनचक्र

क्लाउड एजेंट्स आपकी टीम के कार्यस्थान में तब तक रहते हैं, जब तक आप उन्हें आर्काइव या डिलीट नहीं करते। client.agents.list(runtime="cloud") डिफ़ॉल्ट रूप से आर्काइव किए गए एजेंट्स को छिपाता है; उन्हें देखने के लिए include_archived=True पास करें। किसी विशिष्ट पुल रिक्वेस्ट को खोलने वाले एजेंट को खोजने के लिए pr_url से फ़िल्टर करें।

# ID से, एजेंट हैंडल की आवश्यकता नहीं:Agent.archive(agent_id)Agent.unarchive(agent_id)Agent.delete(agent_id)# स्पष्ट रूप से दिए गए क्लाइंट के माध्यम से:client.agents.archive(agent_id)client.agents.unarchive(agent_id)client.agents.delete(agent_id)# मौजूदा एजेंट हैंडल पर:agent.archive()agent.unarchive()agent.delete()

archive एजेंट को सॉफ्ट-डिलीट करता है, ताकि प्रतिलेख पढ़ने योग्य बना रहे। unarchive उसे पुनर्स्थापित करता है। delete स्थायी है; इसके बाद किए गए रीड NotFoundError लौटाते हैं।

Async जीवनचक्र मेथड के नाम वही होते हैं और उन्हें await किया जा सकता है।

agent.get_usage()

किसी एजेंट के रन के लिए बिल किया गया टोकन उपयोग और डॉलर लागत प्राप्त करें। क्लाउड एजेंट्स प्रति-रन विवरण देते हैं; स्थानीय एजेंट प्रति-टर्न विवरण देते हैं। परिणाम को एक प्रविष्टि तक सीमित करने के लिए run_id पास करें: क्लाउड एजेंट्स के लिए run-<uuid> रन ID और स्थानीय एजेंट्स के लिए पिछले get_usage().runs[].run_id की ID।

usage = agent.get_usage()print(f"tokens: {usage.usage.total_tokens}")if usage.cost is not None:    print(f"charged: ${usage.cost.charged_cents / 100:.2f}")for run in usage.runs:    print(run.run_id, run.usage.total_tokens)
@dataclass(frozen=True)class AgentUsage:    usage: TokenUsage              # सभी `runs` का कुल योग    runs: Sequence[RunUsage] = ()    cost: UsageCost | None = None  # सभी `runs` का कुल योग@dataclass(frozen=True)class RunUsage:    run_id: str    usage: TokenUsage    cost: UsageCost | None = None@dataclass(frozen=True)class UsageCost:    raw_cost_cents: float  # बिना छूट के मॉडल टोकन की लागत; अनुरोध-आधारित कीमत वाले उपयोग के लिए 0    charged_cents: float   # वसूली गई राशि, जिसमें छूट और Cursor टोकन दर शामिल है

लागत में छूट शामिल होती है और रन समाप्त होने के बाद इसे अपडेट होने में कुछ समय लग सकता है; तब तक cost का मान None रहता है। प्लान में शामिल, BYOK (अपनी कुंजी लाएँ), और क्रेडिट-अनुदान उपयोग के लिए charged_cents का मान 0.0 होता है।

यह टोकन उपयोग से अलग दृश्य है: run.usage किसी एक रन की लाइव टोकन संख्या है, जबकि get_usage() एजेंट के सभी रन का बिल किया गया रिकॉर्ड है। async एजेंटों के लिए, await agent.get_usage() भी यही रिकॉर्ड देता है। AgentUsage, RunUsage, और UsageCost को cursor_sdk से एक्सपोर्ट किया जाता है।

Cursor नेमस्पेस

खाता-स्तर और कैटलॉग पढ़ने के लिए। सिंक मेथड वैकल्पिक api_key लेते हैं; अन्यथा CURSOR_API_KEY का उपयोग करते हैं।

from cursor_sdk import Cursorme = Cursor.me()models = Cursor.models.list()repositories = Cursor.repositories.list()

स्पष्ट क्लाइंट का समकक्ष:

me = client.me()models = client.models.list()repositories = client.repositories.list()

असिंक्रोनस समकक्ष:

from cursor_sdk import AsyncCursorme = await AsyncCursor.me(client=client)models = await AsyncCursor.models.list(client=client)repositories = await AsyncCursor.repositories.list(client=client)

Cursor.me() api_key_name, created_at और वैकल्पिक user_id, user_email, user_first_name और user_last_name फ़ील्ड वाला एक SDKUser लौटाता है।

Agent.create() या agent.send() को कॉल करने से पहले मान्य मॉडल ID और मॉडल-विशिष्ट पैरामीटर जानने के लिए Cursor.models.list() का उपयोग करें। पैरामीटर हर मॉडल के लिए अलग होते हैं। सामान्य उदाहरणों में तर्क प्रयास और auto-smart पर Cursor Router का optimize_for शामिल हैं।

कैटलॉग खाता और टीम के अनुसार अलग होता है। Cursor Router केवल auto-smart के रूप में दिखाई देता है, जब Router API key वाली टीम के लिए उपलब्ध हो। Cursor Router देखें।

models = Cursor.models.list()composer = next((model for model in models if model.id == "composer-2.5"), None)print(composer.parameters if composer else [])# [#   ModelParameterDefinition(#       id="fast",#       display_name="Fast",#       values=(#           ModelParameterDefinitionValue(value="false"),#           ModelParameterDefinitionValue(value="true", display_name="Fast"),#       ),#   ),# ]

हर SDKModel के प्रीसेट variants में पहले से मान्य params होते हैं, इसलिए आप उन्हें ModelSelection में कॉपी कर सकते हैं।

अगर कोई लक्ष्य मॉडल उपलब्ध नहीं है और आपको लागत, संतुलन या इंटेलिजेंस चाहिए, तो स्पष्ट Router चयन (auto-smart + optimize_for) को प्राथमिकता दें। ModelSelection(id="auto") का सहारा केवल तब लें, जब Router मोड चुने बिना सर्वर-चयनित स्वचालित चाहिए। Cursor Router के लिए, optimize_for हमेशा स्पष्ट रूप से पास करें।

Cursor.repositories.list() कॉल करने वाले खाते या टीम के क्लाउड एजेंट्स के लिए उपलब्ध SCM रिपॉजिटरी (GitHub, GitLab, Bitbucket, Azure DevOps—जो भी कनेक्ट है) लौटाता है। हर आइटम एक url प्रदान करता है। इन्हें CloudAgentOptions.repos में भरने के लिए उपयोग करें।

MCP सर्वर

रनटाइम के आधार पर एजेंट इनलाइन परिभाषाओं, प्रोजेक्ट/उपयोगकर्ता सेटिंग्स, प्लगइन्स और डैशबोर्ड-प्रबंधित कॉन्फ़िगरेशन से MCP सर्वर ले सकते हैं।

from cursor_sdk import (    Agent,    AgentOptions,    HttpMcpServerConfig,    LocalAgentOptions,    McpAuth,    StdioMcpServerConfig,)agent = Agent.create(    AgentOptions(        model="composer-2.5",        local=LocalAgentOptions(cwd="."),        mcp_servers={            "docs": HttpMcpServerConfig(                url="https://example.com/mcp",                auth=McpAuth(client_id="client-id", scopes=["read", "write"]),            ),            "filesystem": StdioMcpServerConfig(                command="npx",                args=["-y", "@modelcontextprotocol/server-filesystem", "."],            ),        },    ))

त्वरित स्क्रिप्टिंग की सुविधा के लिए फ़्लैट डिक्शनरी ({"type": "http", "url": ...} और {"type": "stdio", "command": ...}) भी स्वीकार की जाती हैं।

क्या लोड किया जाता है

स्थानीय एजेंट अधिकतम पाँच स्रोतों से सर्वर लोड करते हैं। नामों में टकराव होने पर पहले मिले स्रोत को प्राथमिकता मिलती है:

  1. agent.send() में mcp_servers। उस रन के लिए निर्माण के समय के सर्वरों को पूरी तरह बदल देता है (मर्ज नहीं होते)।
  2. Agent.create() में mcp_servers। प्रति-send override न दिए जाने पर उपयोग होता है।
  3. प्लगइन सर्वर, अगर local.setting_sources में "plugins" शामिल है।
  4. .cursor/mcp.json के प्रोजेक्ट सर्वर, अगर local.setting_sources में "project" शामिल है।
  5. ~/.cursor/mcp.json के उपयोगकर्ता सर्वर, अगर local.setting_sources में "user" शामिल है।

local.setting_sources के बिना, केवल इनलाइन सर्वर लोड होते हैं। अगर किसी स्थानीय MCP सर्वर के लिए OAuth login आवश्यक है, तो SDK Cursor ऐप में सहेजे गए login का पुनः उपयोग कर सकता है, लेकिन आपको साइन इन कराने के लिए ब्राउज़र नहीं खोल सकता।

क्लाउड एजेंट्स इन स्रोतों से सर्वर लोड करते हैं:

  1. agent.send() में mcp_servers। उस रन के लिए निर्माण के समय के सर्वरों को पूरी तरह बदल देता है (मर्ज नहीं होते)।
  2. Agent.create() में mcp_servers। प्रति-send override न दिए जाने पर उपयोग होता है।
  3. cursor.com/agents पर आपके उपयोगकर्ता और टीम MCP सर्वर।

अगर किसी इनलाइन सर्वर में auth या headers शामिल नहीं हैं और आपने पहले cursor.com/agents पर उस सर्वर URL को अधिकृत किया है, तो व्यक्तिगत API टोकन से प्रमाणित रन उन OAuth टोकन का स्वचालित रूप से पुनः उपयोग करते हैं। सर्विस अकाउंट API कुंजियाँ उपयोगकर्ता auth पर वापस नहीं जा सकतीं, क्योंकि वे किसी उपयोगकर्ता से संबद्ध नहीं होतीं।

local.setting_sources क्लाउड एजेंट्स पर लागू नहीं होता।

क्लाउड

क्लाउड एजेंट इनलाइन प्रमाणित MCP कॉन्फ़िगरेशन भी स्वीकार करते हैं। क्लाउड MCP, HTTP और stdio ट्रांसपोर्ट का समर्थन करता है। स्थिर API कुंजियों या Bearer टोकन के लिए HTTP headers का उपयोग करें। OAuth-सुरक्षित सर्वर के लिए HTTP auth का उपयोग करें। जब सर्वर क्लाउड VM में चलता है और एनवायरनमेंट वेरिएबल्स से क्रेडेंशियल पढ़ता है, तो stdio env का उपयोग करें।

from cursor_sdk import (    Agent,    AgentOptions,    CloudAgentOptions,    CloudRepository,    HttpMcpServerConfig,    StdioMcpServerConfig,)agent = Agent.create(    AgentOptions(        model="composer-2.5",        cloud=CloudAgentOptions(            repos=[CloudRepository(url="https://github.com/your-org/your-repo")],        ),        mcp_servers={            "linear": HttpMcpServerConfig(                url="https://mcp.linear.app/mcp",                headers={"Authorization": "Bearer linear_pat_xxx"},            ),            "github": StdioMcpServerConfig(                command="npx",                args=["-y", "@modelcontextprotocol/server-github"],                env={"GITHUB_TOKEN": "ghp_xxx"},            ),        },    ))
  • HTTP headers और auth को Cursor's बैकएंड संभालता है। संवेदनशील फ़ील्ड गोपित कर दिए जाते हैं और VM तक नहीं पहुँचते।
  • Stdio env मान VM में भेजे जाते हैं, क्योंकि सर्वर वहीं चलता है। इन्हें किसी भी अन्य रनटाइम सीक्रेट की तरह संभालें।
  • cursor.com/agents पर कॉन्फ़िगर किए गए MCP सर्वर के लिए OAuth, टीम-स्तरीय सर्वर होने पर भी, प्रति-उपयोगकर्ता रहता है।

पूर्ण कॉन्फ़िगरेशन प्रारूप के लिए MCP और क्लाउड-विशिष्ट व्यवहार के लिए Cloud Agent क्षमताएँ देखें।

उप-एजेंट्स

नामित उप-एजेंट परिभाषित करें, जिन्हें मुख्य एजेंट Agent उपकरण के ज़रिए उत्पन्न कर सकता है। इन्हें इनलाइन पास करें:

from cursor_sdk import Agent, AgentDefinition, AgentOptions, LocalAgentOptionsagent = Agent.create(    AgentOptions(        model="composer-2.5",        local=LocalAgentOptions(cwd="."),        agents={            "code-reviewer": AgentDefinition(                description="Expert code reviewer for quality and security.",                prompt="Review code for bugs, security issues, and proven approaches.",                model="inherit",            ),            "test-writer": AgentDefinition(                description="Writes tests for code changes.",                prompt="Write comprehensive tests for the given code.",            ),        },    ))

रेपो में .cursor/agents/*.md पर कमिट किए गए उप-एजेंट (जिनमें name, description और वैकल्पिक model फ्रंटमैटर होते हैं) भी शामिल किए जाते हैं। समान नाम वाली इनलाइन परिभाषाएँ फ़ाइल-आधारित परिभाषाओं को override करती हैं।

नेस्टेड उप-एजेंट

उप-एजेंट नेस्टिंग सीमा के भीतर अपने उप-एजेंट उत्पन्न कर सकते हैं। जब कोई उप-एजेंट Agent उपकरण का उपयोग करता है, तो उसे वही उप-एजेंट एक्ज़ीक्यूटर मिलता है जो उसके पैरेंट को मिलता है। इसलिए पैरेंट किसी ऐसे उप-एजेंट को कार्य सौंप सकता है, जो उसे आगे सौंप सके। हर स्तर पर नामित उप-एजेंट्स का एक ही सेट उपलब्ध होता है। शीर्ष-स्तर एजेंट और उसके प्रत्यक्ष उप-एजेंट उप-एजेंट शुरू कर सकते हैं, लेकिन किसी दूसरे उप-एजेंट द्वारा शुरू किया गया उप-एजेंट आगे उप-एजेंट शुरू नहीं कर सकता।

टूलसेट को सीमित करना

tools मॉडल के लिए उपलब्ध बिल्ट-इन उपकरणों की अनुमति सूची तय करता है; disallowed_tools उपकरणों को हटाता है और बाकी सभी को रखता है, जिनमें आपके SDK संस्करण के रिलीज़ होने के बाद प्लेटफ़ॉर्म में जोड़े गए उपकरण भी शामिल हैं। फ़िलहाल दोनों केवल स्थानीय एजेंट के लिए हैं और इनमें से कोई भी एजेंट पर सहेजा नहीं जाता: प्रतिबंध बनाए रखने के लिए फिर से शुरू करते समय इन्हें दोबारा पास करें।

from cursor_sdk import Agent, AgentOptions, LocalAgentOptions# केवल-पठन एजेंट: इसे केवल ये उपकरण उपलब्ध हैं।reader = Agent.create(    AgentOptions(        model="composer-2.5",        tools=["read", "grep", "glob", "ls"],        local=LocalAgentOptions(cwd="."),    ))# shell पहुंच को छोड़कर सब कुछ।no_shell = Agent.create(    AgentOptions(        model="composer-2.5",        disallowed_tools=["shell"],        local=LocalAgentOptions(cwd="."),    ))
  • tools न देने पर चुने गए मॉडल के लिए Standard टूलसेट उपलब्ध होता है; tools=[] देने पर कोई बिल्ट-इन उपकरण उपलब्ध नहीं होता, इसलिए मॉडल केवल टेक्स्ट में जवाब दे सकता है।
  • दोनों फ़ील्ड सार्वजनिक नामों ("read", "edit", "task", "webSearch", ...) और क्षमता समूहों "shell" और "mcp" को स्वीकार करते हैं। अज्ञात नाम होने पर निर्माण के समय BadRequestError मिलता है।
  • अस्वीकार करने को प्राथमिकता मिलती है: किसी उपकरण के उपलब्ध होने के लिए उसका tools में होना (यदि सेट किया गया हो) और disallowed_tools में न होना ज़रूरी है।
  • "mcp" को अस्वीकार करने से कस्टम उपकरण भी हट जाते हैं। "task" को अस्वीकार करने से उप-एजेंट्स नहीं बनाए जा सकते; अन्यथा उप-एजेंट अपने चुने हुए टूलसेट बनाए रखते हैं।

कस्टम उपकरण

कस्टम उपकरण आपको अलग MCP सर्वर स्थापित किए बिना स्थानीय एजेंटों को Python फ़ंक्शन उपलब्ध कराने देते हैं। इन्हें LocalAgentOptions.custom_tools में पास करें।

from cursor_sdk import Agent, CustomTool, CustomToolContext, LocalAgentOptionsdef get_deployment_status(args, context: CustomToolContext):    service = args["service"]    return f"Service {service} is healthy."with Agent.create(    model="composer-2.5",    local=LocalAgentOptions(        cwd=".",        custom_tools={            "get_deployment_status": CustomTool(                description="Look up the current deployment status for a service.",                input_schema={                    "type": "object",                    "properties": {                        "service": {"type": "string", "description": "Service name"},                    },                    "required": ["service"],                },                execute=get_deployment_status,            ),        },    ),) as agent:    agent.send("Is the checkout service healthy?").wait()

execute को पार्स किए गए आर्ग्युमेंट्स और, उपलब्ध होने पर, tool_call_id सहित CustomToolContext मिलता है। यह string, JSON-संगत मान या content सूची वाली मैपिंग लौटा सकता है। कस्टम उपकरण केवल स्थानीय एजेंट के लिए हैं।

हुक्स

हुक्स केवल फ़ाइल-आधारित होते हैं। इनमें कोई प्रोग्रामेटिक हुक कॉलबैक नहीं होता। हुक्स प्रोजेक्ट की नीति-सीमा हैं, हर रन के लिए अलग से बदला जाने वाला नियंत्रण नहीं।

  • स्थानीय: local.cwd में दिए गए रेपो में .cursor/hooks.json जोड़ें, या उपयोगकर्ता-स्तरीय हुक्स के लिए ~/.cursor/hooks.json जोड़ें।
  • क्लाउड: .cursor/hooks.json और उसकी स्क्रिप्ट्स को cloud.repos में दिए गए रेपो में कमिट करें। SDK से बनाए गए क्लाउड एजेंट प्रोजेक्ट हुक्स को स्वचालित रूप से लोड करते हैं। एंटरप्राइज़ प्लान पर, वे टीम हुक्स और एंटरप्राइज़-प्रबंधित हुक्स भी चलाते हैं।

कॉन्फ़िगरेशन प्रारूप के लिए हुक्स और क्लाउड व्यवहार के लिए क्लाउड एजेंट्स के हुक्स की सहायता देखें।

आर्टिफैक्ट्स

एजेंट के कार्यस्थान से फ़ाइलों की सूची देखें और डाउनलोड करें।

@dataclass(frozen=True)class SDKArtifact:    path: str    size_bytes: int = 0    updated_at: str = ""
from pathlib import Pathartifacts = agent.list_artifacts()for artifact in artifacts:    print(artifact.path, artifact.size_bytes)# एक आर्टिफैक्ट को डिस्क पर डाउनलोड करें।content = agent.download_artifact(artifacts[0].path)Path("review.md").write_bytes(content)

Async एजेंट await agent.list_artifacts() और await agent.download_artifact(path) उपलब्ध कराते हैं।

आर्टिफैक्ट की सहायता रनटाइम पर निर्भर करती है। स्थानीय SDK एजेंट list_artifacts() से खाली सूची लौटाते हैं और download_artifact() त्रुटि उत्पन्न करता है।

संसाधन प्रबंधन

काम पूरा होने पर एजेंट को हमेशा बंद करें। सबसे उपयुक्त सिंक पैटर्न संदर्भ प्रबंधक का उपयोग करना है:

from cursor_sdk import Agent, LocalAgentOptionswith Agent.create(model="composer-2.5", local=LocalAgentOptions(cwd=".")) as agent:    agent.send("Summarize the repository").wait()

स्पष्ट रूप से मुक्त करने के लिए:

agent.close()

एसिंक्रोनस एजेंट और क्लाइंट एसिंक्रोनस संदर्भ प्रबंधकों और await के साथ क्लीनअप का समर्थन करते हैं:

from cursor_sdk import AsyncClient, LocalAgentOptionsasync with await AsyncClient.launch_bridge(workspace=".") as client:    async with await client.agents.create(        model="composer-2.5",        local=LocalAgentOptions(cwd="."),    ) as agent:        run = await agent.send("Summarize the repository")        await run.wait()

स्पष्ट रूप से मुक्त करने के लिए:

await agent.close()await client.aclose()

मॉड्यूल-स्तरीय सिंक डिफ़ॉल्ट क्लाइंट प्रक्रिया समाप्त होने पर स्वचालित रूप से बंद हो जाता है। लंबे समय तक चलने वाली प्रक्रियाएँ इसे स्पष्ट रूप से बंद और रीसेट कर सकती हैं:

from cursor_sdk import close_default_clientclose_default_client()

कॉन्फ़िगरेशन संदर्भ

Python SDK हेल्पर डेटाक्लास और raw डिक्शनरी स्वीकार करता है। डेटाक्लास में Python के snake_case फ़ील्ड होते हैं और एप्लिकेशन कोड के लिए इन्हें प्राथमिकता दी जाती है।

AgentOptions

Propertyप्रकारडिफ़ॉल्टविवरण
modelstr | ModelSelection | Mapping[str, Any]स्थानीय के लिए आवश्यक; क्लाउड में सर्वर द्वारा तय डिफ़ॉल्ट का उपयोग होता हैउपयोग किया जाने वाला मॉडल। ModelSelection देखें।
api_keystrCURSOR_API_KEY envउपयोगकर्ता API key या सेवा खाता कुंजी। टीम एडमिन कुंजियाँ अभी समर्थित नहीं हैं।
namestrस्वचालित रूप से जनरेट किया गयाclient.agents.list() / client.agents.get() में दिखने वाला मानव-पठनीय एजेंट नाम।
localLocalAgentOptions | Mapping[str, Any]Noneस्थानीय एजेंट कॉन्फ़िगरेशन। स्थानीय एजेंट बनाने के लिए दें।
cloudCloudAgentOptions | Mapping[str, Any]Noneक्लाउड एजेंट कॉन्फ़िगरेशन। क्लाउड एजेंट बनाने के लिए दें।
mcp_serversMapping[str, McpServerConfig]Noneइनलाइन MCP सर्वर परिभाषाएँ।
agentsMapping[str, AgentDefinition | Mapping[str, Any]]Noneउप-एजेंट परिभाषाएँ।
toolsSequence[str]डिफ़ॉल्ट टूलसेटमॉडल को केवल सूचीबद्ध बिल्ट-इन उपकरण उपलब्ध कराए जाते हैं। [] का अर्थ है कोई बिल्ट-इन उपकरण नहीं; मॉडल केवल टेक्स्ट से जवाब दे सकता है। केवल स्थानीय एजेंट के लिए।
disallowed_toolsSequence[str]Noneसूचीबद्ध बिल्ट-इन उपकरण हटा देता है; बाकी सभी उपलब्ध रहते हैं। tools के साथ उपयोग करने पर अस्वीकार को प्राथमिकता मिलती है। केवल स्थानीय एजेंट के लिए।
agent_idstrस्वचालित रूप से जनरेट किया गयास्थायी एजेंट ID। इनवोकेशन के बीच स्थिर ID बनाए रखने के लिए दें।
idempotency_keystrक्लाउड के लिए स्वचालित रूप से जनरेट किया गयावैकल्पिक क्लाइंट-जनरेटेड आइडेम्पोटेंसी कुंजी। केवल क्लाउड के लिए।
mode"agent" | "plan"Noneएजेंट के पहले रन के लिए प्रारंभिक बातचीत मोड। छोड़े जाने पर, सर्वर एजेंट मोड में शुरू होता है। बातचीत मोड देखें।

LocalAgentOptions

Propertyप्रकारडिफ़ॉल्टविवरण
cwdstr | os.PathLikeNoneमुख्य वर्किंग डायरेक्टरी। एकाधिक एंट्री वाली सूचियाँ स्वीकार नहीं हैं; मल्टी-रूट के लिए dirs का उपयोग करें।
dirsSequence[str | os.PathLike]Noneमल्टी-रूट सेटअप के लिए अतिरिक्त कार्यस्थान फ़ोल्डर। cwd के साथ मर्ज किया जाता है, ताकि नियम, कौशल और कार्यस्थान संदर्भ हर पाथ से लोड हो सकें।
setting_sourcesSequence[SettingSource]Noneपरिवेशीय सेटिंग्स लेयर्स: "project", "user", "team", "mdm", "plugins", या "all"
sandbox_optionsSandboxOptions | Mapping[str, Any]Noneस्थानीय सैंडबॉक्स विकल्प।
storeLocalAgentStoreConfig | Mapping[str, Any]Noneब्रिज को भेजा जाने वाला स्थानीय स्टोर कॉन्फ़िगरेशन।
auto_reviewboolNoneकनेक्ट किया हुआ बैकएंड समर्थन करने पर स्थानीय टूल कॉल्स को ऑटो-रिव्यू के माध्यम से रूट करें।
custom_toolsMapping[str, CustomTool | Mapping[str, Any]]Noneस्थानीय एजेंटों के लिए उपलब्ध कस्टम उपकरण

CloudAgentOptions

Propertyप्रकारडिफ़ॉल्टविवरण
envCloudEnvironment | Mapping[str, Any]Noneनिष्पादन परिवेश। न दिए जाने पर सर्वर Cursor-होस्टेड क्लाउड VMs का उपयोग करता है। pool और machine आपके द्वारा चलाए जा रहे स्व-होस्टेड वर्कर्स को लक्षित करते हैं।
reposSequence[CloudRepository | Mapping[str, Any]]NoneVM में क्लोन करने के लिए रिपॉज़िटरी। खाली कार्यस्थान वाले बिना-रेपो एजेंट के लिए repos और env दोनों न दें। एजेंट को किसी मौजूदा PR से संलग्न करने के लिए रेपो में pr_url पास करें।
work_on_current_branchboolNoneनई ब्रांच के बजाय मौजूदा ब्रांच पर कमिट्स पुश करें। सर्वर न दिए गए मान को False मानता है।
auto_create_prboolNoneरन समाप्त होने पर PR खोलें। सर्वर न दिए गए मान को False मानता है।
open_as_cursor_github_appboolसेवा-खाता कुंजियों के लिए True, उपयोगकर्ता कुंजियों के लिए FalseAPI key के मालिक के बजाय Cursor GitHub ऐप के रूप में PR खोलें। रिज़ॉल्व किया गया मान create, get और list में लौटाया जाता है।
skip_reviewer_requestboolNoneकॉल करने वाले उपयोगकर्ता को PR के समीक्षक के रूप में अनुरोध करना छोड़ें। सर्वर न दिए गए मान को False मानता है।
env_varsMapping[str, str]Noneक्लाउड एजेंट्स के लिए सत्र-स्कोप्ड एनवायरनमेंट वेरिएबल्स।
metadataMapping[str, str]Noneक्लाउड एजेंट पर पर्सिस्ट किए गए कॉलर-स्वामित्व वाले string टैग। एजेंट मेटाडेटा देखें।

AgentDefinition

Propertyप्रकारडिफ़ॉल्टविवरण
descriptionstrआवश्यकइस उप-एजेंट का उपयोग कब करना है। पैरेंट एजेंट को यह बताया जाता है कि इसे कब उत्पन्न करना है।
promptstrआवश्यकउप-एजेंट के लिए सिस्टम प्रॉम्प्ट।
modelstr | ModelSelection | Mapping[str, Any] | "inherit"Noneमॉडल ओवरराइड। None और "inherit" दोनों पैरेंट के चयन का उपयोग करते हैं।
mcp_serversSequence[str | AgentDefinitionMcpServer | Mapping[str, Any]]Noneइस उप-एजेंट के लिए उपलब्ध MCP सर्वर। नाम पैरेंट के mcp_servers में मौजूद सर्वरों को संदर्भित करते हैं।

कस्टम उपकरण

@dataclassclass CustomTool:    execute: Callable[[Mapping[str, Any], CustomToolContext], Any]    description: str | None = None    input_schema: Mapping[str, Any] | None = Noneclass CustomToolContext:    tool_call_id: str | None = None

ModelSelection

@dataclass(frozen=True)class ModelSelection:    id: str    params: Sequence[ModelParameterValue] = ()@dataclass(frozen=True)class ModelParameterValue:    id: str    value: str

id मॉडल पहचानकर्ता है (उदाहरण के लिए, "composer-2.5" या "auto-smart")। params में मॉडल-विशिष्ट पैरामीटर होते हैं, जैसे तर्क प्रयास या Router का optimize_for। अपने खाते के लिए मान्य IDs, पैरामीटर की परिभाषाएँ और प्रीसेट वैरिएंट्स जानने के लिए Cursor.models.list() का उपयोग करें। Router चयन अनुबंध के लिए Cursor Router देखें।

McpServerConfig

from cursor_sdk.types import McpServerConfig@dataclass(frozen=True)class HttpMcpServerConfig:    url: str    type: Literal["http", "sse"] | str = "http"    headers: Mapping[str, str] | None = None    auth: McpAuth | Mapping[str, Any] | None = None@dataclass(frozen=True)class SseMcpServerConfig(HttpMcpServerConfig):    type: Literal["sse"] = "sse"@dataclass(frozen=True)class StdioMcpServerConfig:    command: str    args: Sequence[str] | None = None    env: Mapping[str, str] | None = None    cwd: str | os.PathLike | None = None  # केवल स्थानीय; क्लाउड इस फ़ील्ड को स्वीकार नहीं करता@dataclass(frozen=True)class McpAuth:    client_id: str    client_secret: str | None = None    scopes: Sequence[str] = ()

क्लाउड में चल रहे HTTP सर्वरों के लिए, headers और auth को Cursor का बैकएंड संभालता है। संवेदनशील फ़ील्ड VM तक पहुँचने से पहले गोपित कर दिए जाते हैं। क्लाउड में stdio सर्वरों के लिए, env मान VM को भेजे जाते हैं (उन्हें किसी भी रनटाइम सीक्रेट की तरह संभालें)।

UserMessage

@dataclass(frozen=True)class UserMessage:    text: str    images: Sequence[SDKImage | Mapping[str, Any]] | None = None

agent.send() के संदेश आर्ग्युमेंट का संरचित रूप। टेक्स्ट के साथ छवियाँ भेजने के लिए इसका उपयोग करें।

SDKImage

@dataclass(frozen=True)class SDKImage:    url: str | None = None    data: str | None = None    mime_type: str | None = None    dimension: SDKImageDimension | Mapping[str, Any] | None = None    @classmethod    def from_url(cls, url: str, dimension=None) -> SDKImage: ...    @classmethod    def from_data(cls, data: bytes | str, mime_type: str, dimension=None) -> SDKImage: ...    @classmethod    def url_image(cls, url: str, dimension=None) -> SDKImage: ...    @classmethod    def data_image(cls, data: str, mime_type: str, dimension=None) -> SDKImage: ...    @classmethod    def from_file(cls, path, *, mime_type=None, dimension=None) -> SDKImage: ...

mime_type के साथ रिमोट url या base64 data दें। from_data() बाइट्स या base64 स्ट्रिंग स्वीकार करता है। from_file() डिस्क से फ़ाइल पढ़ता है और उसे base64 में एन्कोड करता है।

SettingSource

SettingSource, cursor_sdk.types में उपलब्ध है।

from cursor_sdk.types import SettingSource

यह नियंत्रित करता है कि स्थानीय एजेंट डिस्क पर मौजूद सेटिंग्स की कौन-सी लेयर्स लोड करता है। क्लाउड एजेंट्स हमेशा project, team और plugins लोड करते हैं और इस फ़ील्ड को अनदेखा करते हैं।

मानस्रोत
"project"कार्यस्थान में .cursor/
"user"~/.cursor/
"team"डैशबोर्ड से सिंक की गई टीम सेटिंग्स
"mdm"MDM द्वारा प्रबंधित एंटरप्राइज़ सेटिंग्स
"plugins"प्लगइन द्वारा प्रदान की गई सेटिंग्स
"all"ऊपर दिए गए सभी का संक्षिप्त रूप

सूचीResult

@dataclass(frozen=True)class ListResult(Generic[T]):    items: list[T]    next_cursor: str = ""    def to_dict(self) -> dict[str, Any]: ...    def has_next_page(self) -> bool: ...    def next_page_info(self) -> dict[str, str]: ...    def get_next_page(self) -> ListResult[T]: ...    def auto_paging_iter(self) -> Iterator[T]: ...

client.agents.list(), client.agents.list_runs() और Agent.list() द्वारा लौटाया जाता है। आगे कोई पृष्ठ न होने पर next_cursor खाली होता है। Async सूची एंडपॉइंट्स await किए जा सकने वाले समकक्षों के साथ AsyncListResult[T] लौटाते हैं।

त्रुटियाँ

सभी SDK त्रुटियाँ CursorAgentError से विस्तारित होती हैं। पुराने कॉलरों के लिए CursorSDKError, रूट का बैकवर्ड-कंपैटिबल उपनाम है। पुनः प्रयास लॉजिक के लिए is_retryable और retry_after का उपयोग करें।

class CursorAgentError(Exception):    message: str    code: str | None    status: int | None    status_code: int | None    details: list[Mapping[str, Any]]    is_retryable: bool    cause: BaseException | None    proto_error_code: str | None    request_id: str | None    headers: Mapping[str, str]    retry_after: str | None
त्रुटिकब
AuthenticationErrorAPI key अमान्य है या लॉग इन नहीं किया है।
PermissionDeniedErrorप्रमाणित कॉलर के पास अनुरोधित ऑपरेशन की अनुमति नहीं है।
RateLimitErrorबहुत अधिक अनुरोध किए गए या उपयोग सीमाएँ पार हो गईं।
ConfigurationErrorअमान्य मॉडल, आवश्यक कॉन्फ़िगरेशन अनुपलब्ध, या अनुरोध के पैरामीटर गलत हैं।
AgentBusyErrorएजेंट का रन पहले से CREATING या RUNNING स्थिति में होने पर फॉलो-अप भेजना (HTTP 409, कोड agent_busy)।
BadRequestErrorअनुरोध का प्रारूप गलत है।
IntegrationNotConnectedErrorऐसे रेपो के लिए क्लाउड एजेंट बनाना जिसका SCM प्रदाता कनेक्ट नहीं है।
NetworkErrorसेवा अनुपलब्ध है या नेटवर्क विफल हो गया है।
APITimeoutErrorअनुरोध का टाइमआउट हो गया।
InternalServerErrorCursor सेवा ने सर्वर त्रुटि लौटाई।
NotFoundErrorअनुरोधित संसाधन नहीं मिला।
AgentNotFoundErrorएजेंट मौजूद नहीं है या मौजूदा वर्किंग डायरेक्टरी में दिखाई नहीं देता।
UnsupportedRunOperationErrorमौजूदा रन स्थिति के लिए रन ऑपरेशन समर्थित नहीं है।

बैकऑफ़ के साथ पुनः प्रयास

is_retryable और retry_after कॉलर-साइड पुनः प्रयास लॉजिक को नियंत्रित करते हैं। सेट होने पर, retry_after सर्वर द्वारा दिया गया HTTP-शैली का स्ट्रिंग होता है (सेकंड या HTTP तारीख)।

import timefrom cursor_sdk import Agent, AgentOptions, CursorAgentError, LocalAgentOptions, RateLimitErrorfor attempt in range(3):    try:        result = Agent.prompt(            "Audit the auth middleware for missing input validation",            AgentOptions(model="composer-2.5", local=LocalAgentOptions(cwd=".")),        )        break    except RateLimitError as err:        time.sleep(float(err.retry_after) if err.retry_after else 2**attempt)    except CursorAgentError as err:        if not err.is_retryable:            raise        time.sleep(2**attempt)

हर CursorAgentError में, यदि सर्वर ने दिया हो, तो request_id शामिल होता है। जब भी आप कोई त्रुटि प्रदर्शित करें, इसे लॉग करें ताकि सहायता टीम विफलता की पहचान कर सके।

IntegrationNotConnectedError

class IntegrationNotConnectedError(ConfigurationError):    provider: str   # उदाहरण के लिए: "github", "gitlab", "azuredevops"    help_url: str   # पुनः कनेक्ट करने के लिए डैशबोर्ड का लिंक

उपयोगकर्ता को सही पुनः कनेक्ट करने की प्रक्रिया तक मार्गदर्शन देने के लिए help_url का उपयोग करें। SDK रिलीज़ के बिना नए प्रदाता जोड़े जा सकते हैं।

AgentBusyError

क्लाउड एजेंट्स एक समय में केवल एक सक्रिय रन की अनुमति देते हैं। जब आप agent.send() को कॉल करते हैं (या किसी अन्य तरीके से रन बनाते हैं) और उसी एजेंट पर कोई अन्य रन अभी भी CREATING या RUNNING स्थिति में है, तो AgentBusyError उत्पन्न होती है।

is_retryable का मान False है। सक्रिय रन के अंतिम स्थिति में पहुँचने या उसे रद्द करने तक तुरंत पुनः प्रयास विफल होते रहेंगे। agent_archived जैसी अन्य 409 प्रतिक्रियाएँ इसके बजाय ConfigurationError उत्पन्न करती हैं।

फिर से भेजने से पहले सक्रिय रन के समाप्त होने की प्रतीक्षा करें, उसे run.cancel() से रद्द करें, या Agent.list_runs() को पोल करें:

from cursor_sdk import Agent, AgentBusyErroragent = Agent.resume("bc-00000000-0000-0000-0000-000000000001")try:    agent.send("Also add tests for the auth middleware.")except AgentBusyError:    runs = Agent.list_runs(agent.agent_id, {"runtime": "cloud", "limit": 1})    active = runs.items[0] if runs.items else None    if active is not None and active.status == "running":        active.cancel()    agent.send("Also add tests for the auth middleware.")

स्थानीय एजेंट AgentBusyError नहीं उठाते। नया स्थानीय रन शुरू करने से पहले अटके हुए स्थानीय रन को समाप्त करने के लिए send() में local={"force": True} पास करें।

UnsupportedRunOperationError

class UnsupportedRunOperationError(ConfigurationError):    operation: str

यह त्रुटि तब होती है, जब मौजूदा रन पर कोई Run ऑपरेशन अनुमत नहीं होता। सबसे सामान्य उदाहरण पहले से टर्मिनल स्थिति में मौजूद रन पर run.cancel() चलाना है।

run.supports(operation) और run.unsupported_reason(operation) किसी ऑपरेशन नाम ("stream", "wait", "cancel", "conversation") के लिए SDK-स्तरीय क्षमता की रिपोर्ट करते हैं और रन की स्थिति की जाँच नहीं करते। स्थिति-संवेदनशील कॉल से पहले run.status पढ़ें।

समस्या निवारण

SDK के अपने लॉगर से stderr हैंडलर संलग्न करने के लिए CURSOR_SDK_LOG=debug (या info) सेट करें। SDK केवल अपने cursor_sdk लॉगर को कॉन्फ़िगर करता है, इसलिए इससे होस्ट एप्लिकेशन के लॉगिंग सेटअप में कोई हस्तक्षेप नहीं होगा।

CURSOR_SDK_LOG=debug python my_script.py

बंडल की गई ब्रिज बाइनरी पैकेज के साथ PATH में cursor-sdk-bridge के रूप में इंस्टॉल होती है। अपने wheel के साथ शामिल बिल्ड की पुष्टि करने के लिए इसे सीधे चलाएँ:

cursor-sdk-bridge --help

ज्ञात सीमाएँ

  • टूल-कॉल पेलोड स्कीमा जानबूझकर सख्ती से टाइप नहीं किए गए हैं।
  • इनलाइन MCP सर्वर Agent.resume() के बाद सहेजे नहीं जाते। आवश्यकता होने पर फिर से शुरू करते समय इन्हें दोबारा पास करें।
  • कस्टम उपकरण (local.custom_tools) और टूलसेट प्रतिबंध (tools, disallowed_tools) केवल स्थानीय एजेंट्स के लिए हैं। प्रतिबंध एजेंट पर सहेजे नहीं जाते; फिर से शुरू करते समय इन्हें दोबारा पास करें।
  • स्थानीय एजेंट्स के लिए आर्टिफैक्ट डाउनलोड उपलब्ध नहीं है।
  • local.setting_sources (और इसके द्वारा नियंत्रित फ़ाइल-आधारित MCP व उप-एजेंट पाथ) क्लाउड एजेंट्स पर लागू नहीं होता। क्लाउड हमेशा project, team और plugins लोड करता है।
  • हुक्स केवल फ़ाइल-आधारित हैं (.cursor/hooks.json)। प्रोग्रामेटिक कॉलबैक उपलब्ध नहीं हैं।