Gemini API की मदद से, मैनेज किया गया टेक डाइजेस्ट एजेंट बनाना

1. खास जानकारी

एआई और टेक्नोलॉजी के क्षेत्र में, इतनी तेज़ी से बदलाव हो रहे हैं कि कोई भी व्यक्ति इन पर नज़र नहीं रख सकता. नए मॉडल, पेपर, और प्रॉडक्ट रोज़ाना रिलीज़ होते हैं. डाइजेस्ट एजेंट, आज की मुख्य खबरें फ़ेच करता है, उनकी खास जानकारी लिखता है, और हर सुबह एक PDF जनरेट करता है. इससे यह समस्या हल हो जाएगी. हालांकि, इसे बनाने के लिए एक फ़्रेमवर्क चुनना, Python में टूल तय करना, ऑर्केस्ट्रेशन लूप लिखना, कंटेनर को पैकेज करना, और Cloud Run पर डिप्लॉय करना पड़ता था. यह सब तब हुआ, जब एजेंट ने एक भी वेब का अनुरोध नहीं किया था.

Gemini API में मैनेज किए गए एजेंट, इस समीकरण को बदल देते हैं. आपको दो मार्कडाउन कॉन्फ़िगरेशन फ़ाइलें और पहले से बनी रेंडरर स्क्रिप्ट लिखनी होती है. इसके बाद, एक एपीआई कॉल करना होता है. इससे Ubuntu का सैंडबॉक्स बूट होता है, वेब ब्राउज़ करता है, आपकी खास जानकारी लिखता है, और एक PDF जनरेट करता है. कोई कंटेनर नहीं. कोई डिप्लॉयमेंट नहीं है. ऑर्केस्ट्रेशन कोड नहीं है.

इस कोडलैब में, आपको ठीक वैसा ही एजेंट बनाना है. इसमें, एक-एक करके हर कॉन्सेप्ट को समझाया गया है. जैसे, खाली फ़ंक्शन से लेकर रोज़ाना डाइजेस्ट तैयार करने तक.

आपको क्या बनाना है

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

आपको किन चीज़ों की ज़रूरत होगी

  • Python 3.10+
  • बिलिंग की सुविधा चालू वाला Gemini API पासकोड: aistudio.google.com/api-keys
  • एपीआई क्रेडिट के तौर पर ~1 डॉलर (हर बार पूरा रन करने पर 0.30 से 1.30 डॉलर का खर्च आता है)

2. Gemini API में मैनेज किए गए एजेंट क्या होते हैं?

एआई सिस्टम के तीन लेवल

कोड के बारे में जानने से पहले, यहां बताया गया है कि मैनेज किए गए एजेंट, दो विकल्पों के मुकाबले कहां फ़िट होते हैं:

लेवल

यह क्या है

इन्फ़्रास्ट्रक्चर को कौन मैनेज करता है?

स्टैंडर्ड एलएलएम

आपके प्रॉम्प्ट के आधार पर, यह टेक्स्ट के रूप में जवाब देता है. हाथ नहीं हैं, याददाश्त नहीं है, और इंटरनेट नहीं है.

लागू नहीं: यह खुद से कुछ नहीं कर सकता

सेल्फ़-होस्ट किया गया एजेंट

ADK/LangChain/AutoGen + Docker + टूल + मेमोरी को एक साथ इस्तेमाल किया जाता है.

आप: सभी (या Agent Engine जैसे मैनेज किए गए प्लैटफ़ॉर्म)

मैनेज किया जाने वाला एजेंट

आपको इसे एक लक्ष्य देना होता है. Google, एक सुरक्षित सैंडबॉक्स उपलब्ध कराता है. यह एजेंट, कोड लिखता है, उसे चलाता है, गड़बड़ियों को पढ़ता है, वेब पर खोज करता है, और अपने-आप बग ठीक करता है.

Google: सभी

यह कोडलैब, तीसरी लाइन के बारे में है. आपको टास्क और कॉन्फ़िगरेशन फ़ाइलें देनी होंगी. बाकी का काम Google करता है.

ADK + Cloud Run की मदद से क्या बनाया जा सकता है

वेब ब्राउज़ करने, Python चलाने, और PDF जनरेट करने वाला न्यूज़ डाइजेस्ट एजेंट बनाने के लिए, आपको ADK + Cloud Run के साथ इन सभी चीज़ों की ज़रूरत होगी:

# agent.py: define tools and wire up the agent
from google.adk.agents import LlmAgent
from google.adk.tools import google_search, built_in_code_execution

agent = LlmAgent(
    name="digest-agent",
    model=MODEL,
    instruction=AGENTS_MD,          # your editorial voice and rules
    tools=[google_search, built_in_code_execution],
)
# app.py: serve the agent over HTTP
from google.adk.runners import FastApiRunner
runner = FastApiRunner(agent=agent)
app = runner.app
# pdf_tool.py: custom tool, install reportlab, render PDF
# scraper.py: custom tool, fetch each news source
# streaming.py: wire agent events to your SSE endpoint
# Dockerfile: package everything
FROM python:3.12
COPY . /app
RUN pip install google-adk reportlab requests
CMD ["uvicorn", "app:app", "--host", "0.0.0.0"]
# Deploy to Cloud Run
gcloud run deploy digest-agent \
  --image gcr.io/your-project/digest-agent \
  --set-secrets GEMINI_API_KEY=gemini-key:latest \
  --memory 2Gi

ऐसा तब होता है, जब एजेंट ने एक बार भी रन न किया हो. आपके पास अब भी सैंडबॉक्स आइसोलेशन का मालिकाना हक है. इसलिए, एजेंट आपके सर्वर को नुकसान नहीं पहुंचा सकता. साथ ही, आपके पास पैकेज इंस्टॉल करने, टूल कॉल के बीच स्टेट मैनेजमेंट करने, और क्लाइंट को इवेंट भेजने के लिए स्ट्रीमिंग इन्फ़्रास्ट्रक्चर का मालिकाना हक है.

Managed Agents इसे किस चीज़ से बदलता है

from google import genai
client = genai.Client()

stream = client.interactions.create(
    agent="antigravity-preview-05-2026",
    input="",
    stream=True,
    environment={
        "type": "remote",
        "sources": [          # your config files, mounted at startup
            {
                "type": "inline",
                "target": ".agents/AGENTS.md",
                "content": AGENTS_MD,
            },
            {
                "type": "inline",
                "target": ".agents/skills/digest-pdf/SKILL.md",
                "content": SKILL_MD,
            },
            {
                "type": "inline",
                "target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
                "content": GENERATE_PDF_PY,
            },
        ],
    },
)

ADK + Cloud Run के लिए ज़रूरी शर्तें

मैनेज किए जाने वाले एजेंट आपके लिए क्या-क्या काम करते हैं

कंटेनर इमेज + Dockerfile + CI/CD

पूरी तरह से मैनेज किया गया Ubuntu सैंडबॉक्स (Python 3.12, Node 22, 4 सीपीयू / 16 जीबी रैम)

Cloud Run डिप्लॉयमेंट + स्केलिंग

हर इंटरैक्शन के लिए उपलब्ध कराया जाता है. सात दिनों तक कोई गतिविधि न होने पर, यह अपने-आप खत्म हो जाता है

सैंडबॉक्स आइसोलेशन

हर इंटरैक्शन के लिए अलग-अलग

PDF टूल को पसंद के मुताबिक बनाएं + pip install

एजेंट, सैंडबॉक्स में पैकेज इंस्टॉल करता है

एसएसई स्ट्रीमिंग इन्फ़्रास्ट्रक्चर

stream=True, इवेंट का इटरेबल ऑब्जेक्ट दिखाता है

Python में टूल की परिभाषाएं

इन टूल का इस्तेमाल किया जा सकता है: वेब ब्राउज़ करना, कोड एक्ज़ीक्यूट करना, फ़ाइल सिस्टम

टूल कॉल के बीच स्टेट मैनेजमेंट

इसे एजेंट के लॉजिक वाले लूप में शामिल किया गया है

कॉन्फ़िगरेशन फ़ाइलें (AGENTS.md, SKILL.md, पहले से बनी हुई स्क्रिप्ट) लिखी जाती हैं और एक एपीआई कॉल किया जाता है. बाकी का काम Google करता है.

सैंडबॉक्स कैसे काम करता है

interactions.create() call
        
        
Google provisions Ubuntu sandbox (Python 3.12, Node 22, 4 CPU / 16 GB RAM)
        
        
Agent reasoning loop:
  plan  fetch URLs  run Python  write files  reason  repeat
        
        
Events stream back in real time: tool calls, text chunks, completion
        
        
interaction.completed  environment_id + interaction_id

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

3. सेट करें

इस कोडलैब को Google Cloud Shell में खोलने के लिए, यहां दिए गए बटन पर क्लिक करें. सभी डिपेंडेंसी पहले से इंस्टॉल हैं.

Cloud Shell में खोलें

विकल्प B: लोकल सेटअप

git clone https://github.com/Saoussen-CH/tech-digest-managed-agent.git
cd tech-digest-managed-agent

अगर ज़रूरी हो, तो uv इंस्टॉल करें:

curl -LsSf https://astral.sh/uv/install.sh | sh

एपीआई पासकोड कॉन्फ़िगर करना

cp .env.example .env
cloudshell edit .env

अपनी कुंजी सेट करें:

GEMINI_API_KEY=your-key-here

डिपेंडेंसी इंस्टॉल करना

uv sync

4. एजेंट को अपना पहला कॉल करना

स्टार्टर फ़ाइल खोलें

cloudshell edit run_digest.py

run_digest() को अभी एक काम पूरा करना है और अगले चरण के लिए तीन और काम पूरे करने हैं. ऊपर दो हेल्पर के नाम पहले से भरे गए हैं:

  • load_source(path): स्क्रिप्ट के हिसाब से, .agents/ से फ़ाइल पढ़ता है. इसका इस्तेमाल अगले चरण में, संपादकीय नज़रिया, PDF प्लेबुक, और रेंडरर को सैंडबॉक्स में माउंट करने के लिए किया जाएगा.
  • run_stream(stream): यह इवेंट स्ट्रीम को प्रोसेस करता है और (environment_id, interaction_id) दिखाता है. आपको इवेंट लूप खुद लिखने की ज़रूरत नहीं है.

क्या जोड़ना है

TODO 1: pass को इससे बदलें (अभी TODO 3 और 4 को अनदेखा करें — ये अगले चरण के लिए हैं):

    from google import genai
    client = genai.Client()

    stream = client.interactions.create(
        agent=BASE_AGENT,
        input="Fetch the Hacker News front page and list the top 5 stories.",
        stream=True,
        environment="remote",
    )

    environment_id, interaction_id = run_stream(stream)
    print(f"\nDone. environment_id={environment_id}")

हर हिस्से का क्या काम है

genai.Client(), एनवायरमेंट से GEMINI_API_KEY पढ़ता है. बाकी सभी काम इस क्लाइंट के ज़रिए किए जाते हैं.

interactions.create() मुख्य कॉल है. ये चार पैरामीटर, इस सुविधा को काम करने में मदद करते हैं:

  • agent=BASE_AGENT: इससे Antigravity एजेंट (antigravity-preview-05-2026) चुना जाता है. यह Gemini 3.5 Flash की मदद से काम करने वाला, अलग-अलग कामों के लिए इस्तेमाल की जाने वाली मशीन है. इसमें तीन टूल पहले से मौजूद होते हैं, जो डिफ़ॉल्ट रूप से चालू होते हैं: code_execution (Bash, Python, Node.js चलाएं), google_search, और url_context (वेब पेज फ़ेच और पढ़ें). environment पैरामीटर पास करने पर, फ़ाइल सिस्टम टूल (read_file, write_file, list_files) अपने-आप चालू हो जाते हैं. एक कॉल से, पूरी तरह से मैनेज किया गया Ubuntu एनवायरमेंट उपलब्ध कराया जाता है. इसमें Python 3.12, Node.js 22, git, pip, और curl पहले से इंस्टॉल होते हैं. बनाने के लिए कोई कंटेनर नहीं है और चलाने के लिए कोई डिप्लॉयमेंट नहीं है.
  • input: इस रन के लिए टास्क. इस इमेज में, एजेंट को Hacker News ब्राउज़ करते हुए दिखाया गया है. साथ ही, वह नतीजों के बारे में जानकारी दे रहा है.
  • environment="remote": इस इंटरैक्शन के लिए, नया क्लाउड सैंडबॉक्स उपलब्ध कराता है.
  • stream=True: यह ब्लॉक करने के बजाय, इवेंट का एक इटरेबल दिखाता है. इस विकल्प के बिना, कॉल 30 से 90 सेकंड तक इंतज़ार करता है और सभी आउटपुट को एक साथ interaction.output_text के तौर पर दिखाता है. स्ट्रीमिंग की सुविधा की मदद से, एजेंट के जवाब की वजह देखी जा सकती है और जवाब मिलते ही कार्रवाई की जा सकती है. यहां स्ट्रीमिंग कोई ऐडवांस सुविधा नहीं है: यह सही डिफ़ॉल्ट है, क्योंकि 90 सेकंड का ब्लैक बॉक्स आपको यह जानकारी नहीं देता कि एजेंट काम कर रहा है या अटक गया है.

आपने अभी-अभी क्या उपलब्ध कराया है: हर interactions.create() कॉल, एक खास सैंडबॉक्स बूट करता है:

कॉम्पोनेंट

खास जानकारी

ऑपरेटिंग सिस्टम

Ubuntu Linux का सुरक्षित एनवायरमेंट

पहले से इंस्टॉल किए गए रनटाइम

Python 3.12, Node.js 22, Bash

कंप्यूट

4 सीपीयू कोर, 16 जीबी रैम

पिछली बातचीत से जुड़ा डेटा मैनेज करना

अपने-आप कंपैक्ट होने की सुविधा, ~135 हज़ार टोकन पर ट्रिगर होती है

नेटवर्किंग

Egress Proxy के ज़रिए आउटबाउंड वेब ऐक्सेस

एजेंट, pip या npm के साथ कोई भी पैकेज इंस्टॉल कर सकता है. साथ ही, फ़ाइलें पढ़ और लिख सकता है. इसके अलावा, आउटबाउंड वेब अनुरोध कर सकता है. आपके मशीन और क्रेडेंशियल को कभी ऐक्सेस नहीं किया जाता.

environment_id, सैंडबॉक्स का हैंडल है. interaction.completed के बाद, सैंडबॉक्स बंद नहीं होता है. यह सात दिनों तक चालू रहता है. environment_id पर क्लिक करके, आपको वापस उसी पेज पर ले जाया जाएगा. इसे दूसरी interactions.create() कॉल पर पास करें. इसके बाद, एजेंट उसी फ़ाइल सिस्टम पर काम करना जारी रखता है. साथ ही, उसे वही फ़ाइलें और इंस्टॉल किए गए पैकेज मिलते हैं जो पहले मिल रहे थे. अगले चरण में, इसका इस्तेमाल एजेंट को फिर से चलाए बिना PDF डाउनलोड करने के लिए किया जाता है. इसके बाद वाले चरण में, इसका इस्तेमाल बातचीत जारी रखने के लिए किया जाता है.

interaction_id, बातचीत के उस टर्न का हैंडल है जो अभी पूरा हुआ है. इसे अगली कॉल में previous_interaction_id के तौर पर पास करें. इससे एजेंट को यह याद रहेगा कि इस बातचीत में क्या कहा गया और क्या किया गया.

पुष्टि करें

uv run python run_digest.py

एजेंट के काम करने के दौरान, आपको लाइव आउटपुट दिखेगा:

[agent started]
  [tool] run_code
Here are the top 5 stories currently on the Hacker News front page, retrieved via the official Hacker News API:

1. **Qwen 3.6 27B is the sweet spot for local development** — 471 points
2. **.self: A new top-level domain designed to support self-hosting** — 116 points
...
Done. environment_id=e3de58774073f75a6ef42924c6ce2e88

एपीआई, environment="remote" के साथ भी असली environment_id दिखाता है. सैंडबॉक्स चल गया है. इसमें कॉन्फ़िगरेशन मौजूद नहीं है: न तो आवाज़ है, न कोई स्किल है, और न ही कोई PDF जनरेटर है. एजेंट ने सिर्फ़ कहानियों को टेक्स्ट के तौर पर प्रिंट किया और बंद कर दिया. अगले चरण में, उन्हें जोड़ा जाता है.

आउटपुट की हर लाइन, run_stream() के किसी इवेंट से मैप होती है:

step.type

यह क्या है

run_stream() प्रिंट क्या है

"url_context_call"

यूआरएल फ़ेच करने वाला एजेंट

[tool] url_context (https://...)

"code_execution_call"

सैंडबॉक्स में कोड चलाने वाला एजेंट

[tool] run_code

"google_search_call"

एजेंट वेब पर खोज कर रहा है

[tool] google_search

"function_call"

फ़ाइल टूल और अन्य

[tool] read_file (/workspace/...)

step.delta कहां delta.type == "text"

एजेंट का जवाब टाइप करना

को सीधे तौर पर stdout पर स्ट्रीम किया जाता है

5. एजेंट को पसंद के मुताबिक बनाना

एजेंट को कोई निर्देश नहीं दिया गया था: न तो आवाज़, न कोई स्किल, और न ही PDF जनरेटर. इस चरण में, .agents/ से कॉन्फ़िगरेशन फ़ाइलें लोड की जाती हैं और उन्हें सैंडबॉक्स में माउंट किया जाता है.

क्या बदलना है

run_digest.py में चार बदलाव करें:

TODO 2: load_source() के नीचे, मॉड्यूल-लेवल के तीन कॉन्स्टेंट जोड़ें. ये run_digest() के बाहर, फ़ाइल में सबसे ऊपर मौजूद होते हैं:

AGENTS_MD       = load_source(".agents/AGENTS.md")
SKILL_MD        = load_source(".agents/skills/digest-pdf/SKILL.md")
GENERATE_PDF_PY = load_source(".agents/skills/digest-pdf/scripts/generate_pdf.py")

हर फ़ाइल खोलकर देखें कि क्या लोड किया जा रहा है: AGENTS.md संपादकीय नज़रिया और वर्कफ़्लो के नियम सेट करता है; SKILL.md सिलसिलेवार तरीके से PDF प्लेबुक है; generate_pdf.py एक पहले से बना हुआ रेंडरर है, जिसे एजेंट चलाएगा.

अब run_digest() में दो और बदलाव करें:

TODO 3: environment को "remote" से बदलकर sources dict में ले जाएं. साथ ही, input को "" पर सेट करें:

        environment={
            "type": "remote",
            "sources": [
                {
                    "type": "inline",
                    "target": ".agents/AGENTS.md",
                    "content": AGENTS_MD,
                },
                {
                    "type": "inline",
                    "target": ".agents/skills/digest-pdf/SKILL.md",
                    "content": SKILL_MD,
                },
                {
                    "type": "inline",
                    "target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
                    "content": GENERATE_PDF_PY,
                },
            ],
        },

TODO 4: इन लाइनों को print(f"\nDone. environment_id={environment_id}") के ठीक बाद जोड़ें:

    set_key(".env", "ENVIRONMENT_ID", environment_id)
    set_key(".env", "INTERACTION_ID", interaction_id)

(set_key को run_digest.py के सबसे ऊपर पहले ही इंपोर्ट कर दिया गया है.)

यह इस रन के दौरान, दोनों आईडी को .env में लिखता है. इसलिए, अगला चरण एजेंट को फिर से चलाए बिना PDF डाउनलोड कर सकता है.

हर सोर्स क्या करता है

हर सोर्स एक ऐसी फ़ाइल होती है जिसे एजेंट के चलने से पहले, स्टार्टअप के समय सैंडबॉक्स फ़ाइल सिस्टम में माउंट किया जाता है. target पाथ, Antigravity हार्नेस के हिसाब से सही जगह पर हैं:

.agents/
├── AGENTS.md                               auto-loaded as global instructions
└── skills/
    └── digest-pdf/
        ├── SKILL.md                        auto-discovered and registered as a skill
        └── scripts/
            └── generate_pdf.py             pre-built renderer the agent can run

target पाथ

वैरिएबल

हार्नेस इसका इस्तेमाल कैसे करता है

.agents/AGENTS.md

AGENTS_MD

लगातार दिखने वाले निर्देशों के तौर पर अपने-आप लोड हो जाते हैं: संपादकीय नज़रिया, वर्कफ़्लो, एक्ज़ीक्यूशन के नियम

.agents/skills/digest-pdf/SKILL.md

SKILL_MD

नाम वाली सुविधा के तौर पर अपने-आप खोजी गई और रजिस्टर की गई; एजेंट इसे नाम से शुरू करता है

.agents/skills/digest-pdf/scripts/generate_pdf.py

GENERATE_PDF_PY

पहले से बनाया गया PDF रेंडरर; एजेंट summaries.json लिखता है और फिर इस स्क्रिप्ट को चलाता है

पुष्टि करें

uv run python run_digest.py

अब इसमें एक से तीन मिनट लगते हैं. आपको एजेंट को कॉन्फ़िगरेशन फ़ाइलें पढ़ते हुए, जवाब लिखते हुए, और PDF सेव करते हुए दिखना चाहिए:

[agent started]
  [tool] read_file (/.agents/skills/digest-pdf/SKILL.md)
  [tool] list_files (/.agents/skills/digest-pdf/scripts)
  [tool] read_file (/.agents/skills/digest-pdf/scripts/generate_pdf.py)
  [tool] run_code
  [tool] write_file (/workspace/summaries.json)
  [tool] run_code
  [tool] delete_file (/tmp/test_scrape.py)
I have successfully generated today's tech news digest and saved the formatted document to /workspace/digest.pdf.
Done. environment_id=4129ffd75574e308748e9425d7ec828f

environment_id अब एक असल वैल्यू है: सैंडबॉक्स, आपकी कॉन्फ़िगरेशन फ़ाइलों के साथ चला और एजेंट ने digest.pdf बनाया. अगले चरण में इसे डाउनलोड किया जाता है.

6. PDF डाउनलोड करें

एजेंट ने सैंडबॉक्स में digest.pdf से /workspace/digest.pdf तक लिखा. एनवायरमेंट स्नैपशॉट, Gemini Files API के ज़रिए टार आर्काइव के तौर पर उपलब्ध है.

अगर ज़रूरी हो, तो requests इंस्टॉल करें:

uv pip install requests

क्या-क्या जानकारी भरनी है

download_pdf.py खोलें. इसमें दो काम की सूची हैं.

TODO 1: requests.get() कॉल के बारे में जानकारी भरो:

    r = requests.get(
        f"https://generativelanguage.googleapis.com/v1beta/files/environment-{environment_id}:download",
        params={"alt": "media"},
        headers={"x-goog-api-key": api_key},
        allow_redirects=True,
    )
    r.raise_for_status()

यूआरएल, सैंडबॉक्स स्नैपशॉट के बारे में बताता है. params={"alt": "media"} मेटाडेटा के बजाय रॉ बाइट दिखाता है. आपका मौजूदा GEMINI_API_KEY, Files API की पुष्टि भी करता है.

TODO 2: tar संग्रह से PDF ढूंढें और उसे निकालें:

            member = next(m for m in tar.getmembers() if m.name.endswith("workspace/digest.pdf"))
            tar.extract(member, path=tmp, filter="data")

टार पाथ प्रीफ़िक्स, अलग-अलग रन के हिसाब से अलग-अलग होता है. इसलिए, सटीक पाथ को हार्डकोड करने के बजाय, प्रत्यय के हिसाब से खोजें. filter="data" असुरक्षित टार एक्सट्रैक्शन के बारे में, Python 3.13 में दी गई चेतावनी को बंद कर देता है.

पुष्टि करें

uv run python download_pdf.py
Saved digest.pdf (48,231 bytes)

digest.pdf को उसी डायरेक्ट्री में खोलें. इसमें लाइव वेब पेजों से एजेंट के जनरेट किए गए फ़ॉर्मैट किए गए डाइजेस्ट शामिल होते हैं.

7. बातचीत जारी रखना

आपके पास पहले से ही digest.pdf है. अगर आपको सिर्फ़ फ़ाइल चाहिए थी, तो आपका काम हो गया. यह चरण किसी दूसरी चीज़ के बारे में है: एजेंट से वेब को फिर से फ़ेच किए बिना डाइजेस्ट को बदलने के लिए कहना.

सैंडबॉक्स अब भी चालू है. एजेंट के पास अब भी /workspace/digest.pdf है और उसे उन सभी कहानियों के बारे में याद है जिन्हें उसने छोटा करके बताया था. दूसरी बार interactions.create() कॉल करने पर, फ़ॉलो-अप मैसेज उसी सैंडबॉक्स में भेजा जाता है. यहां, हर कहानी के नीचे "यह क्यों ज़रूरी है" नोट जोड़ने के लिए कहा गया है. इसके बाद, यह PDF को अपडेट कर देता है. इसके लिए, न तो इसे फिर से फ़ेच करने की ज़रूरत पड़ती है और न ही फिर से खास जानकारी तैयार करने की.

क्या-क्या जानकारी भरनी है

refine_digest.py खोलें. इसमें तीन TODO हैं.

TODO 1 और 2: interactions.create() में मौजूद, सिलसिलेवार बातचीत के दो पैरामीटर की वैल्यू भरें:

    environment=environment_id,
    previous_interaction_id=interaction_id,

environment=environment_id उसी सैंडबॉक्स को उसकी फ़ाइलों और पैकेज के साथ फिर से शुरू करता है. previous_interaction_id=interaction_id एजेंट को बातचीत का इतिहास देता है. पहले कॉल के बाद, कुछ और नहीं बदलता.

TODO 3: इवेंट लूप के बाद, नए interaction_id को .env में सेव करें:

set_key(".env", "INTERACTION_ID", interaction_id)

हर interactions.create() कॉल से एक नया interaction_id जनरेट होता है. इसे वापस लिखने का मतलब है कि अगली बार यह रिफ़ाइनमेंट previous_interaction_id के तौर पर पास हो जाएगा और चेन सही तरीके से काम करेगी. सैंडबॉक्स आईडी कभी नहीं बदलता, इसलिए ENVIRONMENT_ID को अपडेट करने की ज़रूरत नहीं होती.

दो पैरामीटर, जिनकी वजह से सिलसिलेवार बातचीत काम करती है

आईडी

यह क्या-क्या सेव करता है

उपमा

environment=environment_id

फ़ाइलें, इंस्टॉल किए गए पैकेज, सिस्टम की स्थिति: Linux फ़ाइल सिस्टम पर मौजूद हर चीज़

मीटिंग के बीच, ऑफ़िस डेस्क को एक ही जगह पर रखना

previous_interaction_id=interaction_id

बातचीत का इतिहास: एजेंट ने पिछले टर्न में क्या कहा और क्या किया

पिछली मीटिंग में हुई चर्चा को याद रखना

इनमें से किसी भी आईडी को अलग-अलग पास किया जा सकता है:

  • environment_id के लिए: फ़ाइलों और पैकेज का फिर से इस्तेमाल करें, लेकिन नई बातचीत शुरू करें. यह एक ही फ़ाइल फ़ोल्डर में मौजूद नए टास्क के लिए काम का है.
  • previous_interaction_id सिर्फ़: बातचीत के कॉन्टेक्स्ट को जारी रखें, लेकिन नए सैंडबॉक्स में (फ़ाइलें मिट जाती हैं).
  • दोनों: पूरी तरह से जारी रखना. इस चरण में इसका इस्तेमाल किया जाता है.

environment_id के बिना: खाली सैंडबॉक्स, कोई PDF नहीं. previous_interaction_id के बिना: कोई कॉन्टेक्स्ट नहीं है. एजेंट किसी खास सेक्शन को बेहतर नहीं बना सकता.

पुष्टि करें

uv run python refine_digest.py

स्ट्रीमिंग तुरंत शुरू होनी चाहिए. एजेंट किसी भी जानकारी को फिर से फ़ेच नहीं करता है. यह प्रोसेस पूरी होने के बाद:

Refinement done.
Saved digest_v2.pdf (52,418 bytes)

digest_v2.pdf खोलें और इसकी तुलना digest.pdf से करें. अब हर स्टोरी में "यह क्यों अहम है" लाइन जोड़ी जानी चाहिए.

8. मैनेज किए जा रहे एजेंट के कॉन्फ़िगरेशन को सेव करना

अब तक किए गए हर कॉल में, AGENTS.md, SKILL.md, और generate_pdf.py इनलाइन पास हो गए हैं. यह काम करता है, लेकिन हर बार कॉल करने पर, आपके कॉलिंग कोड में पूरी फ़ाइल का कॉन्टेंट शामिल होता है. agents.create(), कॉन्फ़िगरेशन को Google के सर्वर पर सेव किए गए एजेंट में शामिल करता है. अगले इनवोकेशन में, सिर्फ़ एजेंट आईडी पास किया जाता है:

Inline calls:   send sources on every call
Named agent:    bake once → invoke by ID, no sources

क्या-क्या जानकारी भरनी है

save_agent.py खोलें. इसमें एक TODO (TODO 1) है.

ध्यान दें कि कॉन्स्टेंट को सीधे तौर पर run_digest.py से इंपोर्ट किया जाता है (कोई डुप्लीकेट नहीं):

from run_digest import BASE_AGENT, AGENTS_MD, SKILL_MD, GENERATE_PDF_PY

TODO 1: agents.create() कॉल के बारे में जानकारी भरो:

agent = client.agents.create(
    id="my-digest",
    base_agent=BASE_AGENT,
    description="Daily tech digest with editorial voice and PDF generation.",
    base_environment={
        "type": "remote",
        "sources": [
            {
                "type": "inline",
                "target": ".agents/AGENTS.md",
                "content": AGENTS_MD,
            },
            {
                "type": "inline",
                "target": ".agents/skills/digest-pdf/SKILL.md",
                "content": SKILL_MD,
            },
            {
                "type": "inline",
                "target": ".agents/skills/digest-pdf/scripts/generate_pdf.py",
                "content": GENERATE_PDF_PY,
            },
        ],
    },
)

base_environment (environment नहीं) पिछले चरण में मौजूद इनलाइन कॉल से अलग है: सोर्स, Google के सर्वर पर सेव किए जाते हैं और हर बार कॉल करने पर अपने-आप माउंट हो जाते हैं. इसे एक बार चलाएं, न कि हर डाइजेस्ट रन पर.

पुष्टि करें: एजेंट को सेव करें

uv run python save_agent.py
Saved: my-digest
my-digest: Daily tech digest with editorial voice and PDF generation.

सेव किए गए एजेंट को चालू करना

invoke_agent.py खोलें. यह सेव किए गए एजेंट को बिना किसी सोर्स के आईडी से कॉल करता है:

stream = client.interactions.create(
    agent="my-digest",
    input="",
    stream=True,
    environment="remote",
)

इसकी तुलना इनलाइन कॉल से करें: agent=BASE_AGENT को "my-digest" से बदल दिया गया है. साथ ही, तीन इनलाइन सोर्स वाले पूरे environment ब्लॉक को environment="remote" से बदल दिया गया है. यह कॉन्फ़िगरेशन, Google के सर्वर पर पहले से ही मौजूद है.

पुष्टि करें: सेव किए गए एजेंट को चालू करें

uv run python invoke_agent.py

आपको इनलाइन रन के तौर पर वही लाइव स्ट्रीम दिखेगी. हालांकि, कॉल में सोर्स फ़ाइलें नहीं होंगी. जांच पूरी होने के बाद, .env में मौजूद ENVIRONMENT_ID और INTERACTION_ID अपडेट हो जाते हैं. इससे, refine_digest.py का इस्तेमाल पहले की तरह किया जा सकता है.

[agent started]
  [tool] read_file
  [tool] write_file
  [tool] run_code
I have successfully created today's tech news digest.
Done. environment_id=9a1c3e02-...

9. क्लीन अप करें

सैंडबॉक्स का इस्तेमाल न करने पर, यह सात दिनों के बाद अपने-आप बंद हो जाता है. बंद करने के लिए कोई सर्वर नहीं है. मिटाने के लिए कोई कंटेनर नहीं है.

अगर आपने एजेंट कॉन्फ़िगरेशन सेव किया है, तो उसे मिटाएं:

uv run python delete_agent.py

10. खास जानकारी

आपने मैनेज किया गया एजेंट शुरू से बनाया है. इसमें एक-एक करके सभी कॉन्सेप्ट शामिल किए गए हैं. यहां बताया गया है कि हर कसरत से क्या सीखा जा सकता है:

कसरत

सिद्धांत

Key API

पहला कॉल करना

असली Linux सैंडबॉक्स उपलब्ध कराना और उसके इवेंट को लाइव स्ट्रीम करना

interactions.create(agent, input, environment, stream=True), event.event_type

एजेंट को पसंद के मुताबिक बनाना

कॉन्फ़िगरेशन फ़ाइलों को माउंट करें; एक ही रन में आईडी को .env पर बनाए रखें

environment.sources, set_key

PDF डाउनलोड करें

एजेंट को फिर से चलाए बिना PDF डाउनलोड करना

download_pdf.py में Gemini Files API :download

Assistant से बातचीत जारी रखना

वेब से फिर से जानकारी फ़ेच किए बिना बातचीत जारी रखें

environment=environment_id, previous_interaction_id=interaction_id

एजेंट के कॉन्फ़िगरेशन को सेव रखना

एजेंट कॉन्फ़िगरेशन को सेव करता है; आईडी से शुरू करता है, किसी सोर्स की ज़रूरत नहीं होती

agents.create(), agents.list()

मुख्य पैटर्न

  1. एक कॉल, एक सैंडबॉक्स: interactions.create() सभी इन्फ़्रास्ट्रक्चर को मैनेज करता है. इसके लिए, न तो कंटेनर डिप्लॉय करने होते हैं और न ही पैकेज को स्थानीय तौर पर इंस्टॉल करना होता है
  2. प्रोग्रेसिव स्ट्रीमिंग: stream=True इस सुविधा की मदद से, 90 सेकंड के ब्लैक बॉक्स को टूल कॉल और टेक्स्ट के हिस्सों के लाइव फ़ीड में बदला जा सकता है
  3. इनलाइन सोर्स: अपलोड या डिप्लॉयमेंट के किसी भी चरण के बिना, सैंडबॉक्स में AGENTS.md, SKILL.md, और पहले से बनी स्क्रिप्ट को माउंट करें
  4. अपने-आप फ़ाइलें ढूंढने की सुविधा का इस्तेमाल करें: .agents/ में रखी गई फ़ाइलें अपने-आप चुन ली जाती हैं. इसके लिए, एसडीके कॉन्फ़िगरेशन की ज़रूरत नहीं होती
  5. दो डाइमेंशन वाली स्थिति: environment_id फ़ाइलों और पैकेज को ट्रैक करता है; previous_interaction_id बातचीत के कॉन्टेक्स्ट को ट्रैक करता है; दोनों को अलग-अलग पास किया जा सकता है
  6. स्नैपशॉट डाउनलोड करें: एनवायरमेंट एक फ़ुल फ़ाइल सिस्टम टार है. इसे Gemini Files API के ज़रिए ऐक्सेस किया जा सकता है
  7. नाम वाले एजेंट: agents.create() कॉन्फ़िगरेशन को हमेशा के लिए सेव करता है; आने वाले समय में होने वाली कॉल में, सिर्फ़ एजेंट आईडी और environment="remote" पास किए जाते हैं. इनमें कोई सोर्स नहीं होता

ADK + Cloud Run बनाम मैनेज किए गए एजेंट: एक नज़र में अंतर

अनुमति

ADK + Cloud Run

Gemini API पर मैनेज किए गए एजेंट

सैंडबॉक्स उपलब्ध कराना

docker build + gcloud run deploy

interactions.create()

टूल तय करना

Python फ़ंक्शन, जो एजेंट के साथ रजिस्टर किए गए हैं

इनके लिए पहले से मौजूद टूल: वेब ब्राउज़ करना, कोड एक्ज़ीक्यूट करना, फ़ाइल सिस्टम

पैकेज इंस्टॉल करना

pip install in Dockerfile

एजेंट, सैंडबॉक्स में pip install रन करता है

इवेंट स्ट्रीम करना

पसंद के मुताबिक बनाया गया SSE इंफ़्रास्ट्रक्चर

stream=True

सेशन जारी रखना

सेशन डेटाबेस + कॉन्टेक्स्ट इंजेक्शन

environment_id + previous_interaction_id

कॉन्फ़िगरेशन फ़ाइलें

एजेंट में हार्ड-कोड किया गया हो या स्टार्टअप के समय इंजेक्ट किया गया हो

environment.sources के ज़रिए माउंट किया गया

मैनेज करने के लिए इन्फ़्रास्ट्रक्चर

कंटेनर, Cloud Run, IAM, सीक्रेट

कोई नहीं

अगले चरण