สร้าง Agent สรุปข่าวเทคโนโลยีที่มีการจัดการด้วย Gemini API

1. ภาพรวม

โลกของ AI และเทคโนโลยีเปลี่ยนแปลงเร็วกว่าที่ใครๆ จะตามทัน โมเดล งานวิจัย และผลิตภัณฑ์ใหม่ๆ จะเปิดตัวทุกวัน เอเจนต์สรุปข่าวที่ดึงพาดหัวข่าวของวันนี้ เขียนสรุปที่กระชับ และสร้าง PDF ทุกเช้าจะช่วยแก้ปัญหานี้ได้ แต่การสร้างเอเจนต์ดังกล่าวต้องเลือกเฟรมเวิร์ก กำหนดเครื่องมือใน Python เขียนลูปการจัดระเบียบ แพ็กเกจคอนเทนเนอร์ และติดตั้งใช้งานใน Cloud Run ทั้งหมดนี้เกิดขึ้นก่อนที่เอเจนต์จะส่งคำขอเว็บแม้แต่รายการเดียว

Agent ที่ได้รับการจัดการใน Gemini API จะเปลี่ยนสมการ คุณเขียนไฟล์การกำหนดค่า Markdown 2 ไฟล์และสคริปต์ตัวแสดงผลที่สร้างไว้ล่วงหน้า ทำการเรียก API 1 ครั้ง และแซนด์บ็อกซ์ Ubuntu จริงจะบูต เรียกดูเว็บ เขียนข้อมูลสรุป และสร้าง PDF ไม่มีคอนเทนเนอร์ ไม่มีการทำให้ใช้งานได้ ไม่ต้องเขียนโค้ดการจัดการเป็นกลุ่ม

ใน Codelab นี้ คุณจะได้สร้าง Agent ดังกล่าว ตั้งแต่ฟังก์ชันว่างไปจนถึงสรุปประจำวันที่ใช้งานได้ โดยทีละแนวคิด

สิ่งที่คุณจะสร้าง

  • สร้างและเรียกใช้เอเจนต์ที่มีการจัดการตัวแรกในแซนด์บ็อกซ์ Linux จริง
  • ปรับแต่งเอเจนต์ด้วยวิธีการโดยละเอียด
  • ดาวน์โหลดเอาต์พุต PDF ของเอเจนต์
  • สนทนาต่อเพื่อปรับแต่งสรุปโดยไม่ต้องดึงข้อมูลเว็บอีกครั้ง
  • บันทึกการกำหนดค่าเอเจนต์และเรียกใช้ตามรหัสในการเรียกใช้ในอนาคต

สิ่งที่คุณต้องมี

  • Python 3.10 ขึ้นไป
  • คีย์ Gemini API ที่เปิดใช้การเรียกเก็บเงิน: aistudio.google.com/api-keys
  • เครดิต API ประมาณ$1 (การเรียกใช้แต่ละครั้งมีค่าใช้จ่าย $0.30-$1.30)

2. Agent ที่ได้รับการจัดการใน Gemini API คืออะไร

ระบบ AI 3 ระดับ

ก่อนที่จะเจาะลึกเรื่องโค้ด มาดูตำแหน่งของ Agent ที่ได้รับการจัดการ เมื่อเทียบกับทางเลือกอีก 2 ทางกัน

ระดับ

คืออะไร

ใครเป็นผู้จัดการโครงสร้างพื้นฐาน

LLM มาตรฐาน

คุณป้อนพรอมต์ แล้ว Gemini จะตอบกลับด้วยข้อความ ไม่มีมือ ไม่มีหน่วยความจำ ไม่มีอินเทอร์เน็ต

ไม่มี: ทำอะไรด้วยตัวเองไม่ได้

ตัวแทนที่โฮสต์ด้วยตนเอง

คุณเชื่อมต่อ ADK/LangChain/AutoGen + Docker + เครื่องมือ + หน่วยความจำ

คุณ: ทั้งหมด (หรือแพลตฟอร์มที่มีการจัดการ เช่น Agent Engine)

Agent ที่ได้รับการจัดการ

คุณกำหนดเป้าหมายให้ Google จัดสรรแซนด์บ็อกซ์ที่ปลอดภัย Agent จะเขียนโค้ด เรียกใช้โค้ด อ่านข้อผิดพลาด ค้นหาในเว็บ และแก้ไขข้อบกพร่องได้โดยอัตโนมัติ

Google: ทั้งหมด

Codelab นี้เป็นเรื่องเกี่ยวกับแถวที่ 3 คุณจัดเตรียมไฟล์งานและการกำหนดค่า 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

ซึ่งเป็นช่วงก่อนที่ Agent จะทำงาน คุณยังคงเป็นเจ้าของการแยกแซนด์บ็อกซ์ (ดังนั้นเอเจนต์จึงไม่สามารถทําให้เซิร์ฟเวอร์เสียหายได้) การติดตั้งแพ็กเกจ การจัดการสถานะระหว่างการเรียกใช้เครื่องมือ และโครงสร้างพื้นฐานการสตรีมเพื่อรับเหตุการณ์ไปยังไคลเอ็นต์

สิ่งที่ Agent ที่ได้รับการจัดการจะแทนที่

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 ต้องการ

สิ่งที่ Agent ที่ได้รับการจัดการจะจัดการให้คุณ

อิมเมจคอนเทนเนอร์ + Dockerfile + CI/CD

แซนด์บ็อกซ์ Ubuntu ที่มีการจัดการเต็มรูปแบบ (Python 3.12, Node 22, 4 CPU / 16 GB RAM)

การติดตั้งใช้งานและการปรับขนาด Cloud Run

จัดสรรต่อการโต้ตอบ 1 ครั้ง และจะหมดอายุโดยอัตโนมัติหลังจากไม่มีการใช้งานเป็นเวลา 7 วัน

การแยกแซนด์บ็อกซ์

แยกตามการโต้ตอบ

เครื่องมือ PDF ที่กำหนดเอง + pip install

Agent ติดตั้งแพ็กเกจภายในแซนด์บ็อกซ์

โครงสร้างพื้นฐานการสตรีม SSE

stream=True จะแสดงผลการทำซ้ำของเหตุการณ์

คำจำกัดความของเครื่องมือใน Python

เครื่องมือที่มีในตัว: การท่องเว็บ การเรียกใช้โค้ด ระบบไฟล์

การจัดการสถานะระหว่างการเรียกใช้เครื่องมือ

รวมไว้ในลูปการให้เหตุผลของ Agent

คุณเขียนไฟล์การกำหนดค่า (AGENTS.md, SKILL.md, สคริปต์ที่สร้างไว้ล่วงหน้า) และทำการเรียก API 1 ครั้ง 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

Sandbox จะยังคงอยู่เป็นเวลา 7 วันหากไม่มีการใช้งาน คุณสามารถกลับมาใช้ได้ด้วย environment_id เพื่อปรับแต่งเอาต์พุต เรียกใช้งานติดตาม หรือฟอร์กเป็นเอเจนต์ที่มีชื่อที่บันทึกไว้

3. ตั้งค่า

คลิกปุ่มด้านล่างเพื่อเปิด Codelab นี้ใน Google Cloud Shell ระบบจะติดตั้งการขึ้นต่อกันทั้งหมดไว้ล่วงหน้า

เปิดใน Cloud Shell

ตัวเลือก ข: การตั้งค่าในพื้นที่

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

กำหนดค่าคีย์ API

cp .env.example .env
cloudshell edit .env

ตั้งค่าคีย์ดังนี้

GEMINI_API_KEY=your-key-here

ติดตั้งการอ้างอิง

uv sync

4. โทรหา Agent เป็นครั้งแรก

เปิดไฟล์เริ่มต้น

cloudshell edit run_digest.py

run_digest() มี TODO 1 รายการที่ต้องกรอกตอนนี้ และอีก 3 รายการสำหรับขั้นตอนถัดไป ระบบจะกรอกข้อมูลผู้ช่วย 2 คนไว้ให้แล้วที่ด้านบน

  • load_source(path): อ่านไฟล์จาก .agents/ ที่สัมพันธ์กับสคริปต์ คุณจะใช้ข้อมูลนี้ในแบบฝึกหัดถัดไปเพื่อต่อเชื่อมสไตล์การบรรณาธิการ เพลย์บุ๊ก PDF และโปรแกรมแสดงผลลงในแซนด์บ็อกซ์
  • run_stream(stream): ประมวลผลสตรีมเหตุการณ์และแสดงผล (environment_id, interaction_id) คุณไม่จำเป็นต้องเขียน Event Loop ด้วยตนเอง

สิ่งที่ต้องเพิ่ม

TODO 1: แทนที่ pass ด้วย (ข้าม TODO 3, 4 ไปก่อน — TODO เหล่านี้มีไว้สำหรับขั้นตอนถัดไป):

    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() คือการเรียกหลัก โดยมีพารามิเตอร์ 4 รายการที่ทำให้การทำงานเป็นไปได้ ดังนี้

  • agent=BASE_AGENT: เลือก Agent ของ Antigravity (antigravity-preview-05-2026) ซึ่งเป็น Agent ที่ได้รับการจัดการแบบอเนกประสงค์ที่ขับเคลื่อนโดย Gemini 3.5 Flash โดยมาพร้อมเครื่องมือในตัว 3 อย่างที่เปิดใช้โดยค่าเริ่มต้น ได้แก่ code_execution (เรียกใช้ Bash, Python, Node.js), google_search และ url_context (ดึงและอ่านหน้าเว็บ) ระบบจะเปิดใช้เครื่องมือระบบไฟล์ (read_file, write_file, list_files) โดยอัตโนมัติเมื่อคุณส่งพารามิเตอร์ environment การเรียกใช้ครั้งเดียวจะจัดสรรสภาพแวดล้อม 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

Compute

CPU 4 แกน, RAM 16 GB

การจัดการบริบท

การบีบอัดอัตโนมัติจะทริกเกอร์ที่โทเค็นประมาณ 135,000 รายการ

เครือข่าย

การเข้าถึงเว็บขาออกผ่านพร็อกซีขาออก

เอเจนต์สามารถติดตั้งแพ็กเกจใดก็ได้ที่มี pip หรือ npm อ่านและเขียนไฟล์ รวมถึงส่งคำขอเว็บขาออก เราจะไม่แตะต้องเครื่องและข้อมูลเข้าสู่ระบบของคุณ

environment_id คือแฮนเดิลของแซนด์บ็อกซ์ที่เพิ่งเรียกใช้ หลังจาก interaction.completed แซนด์บ็อกซ์จะไม่ปิดตัวลง แต่จะยังคงใช้งานได้นานสูงสุด 7 วัน environment_id คือวิธีกลับไปที่หน้าดังกล่าว จากนั้นส่งต่อสายไปยังการโทรของ interactions.create() ครั้งที่ 2 แล้วตัวแทนจะกลับมาทำงานต่อในระบบไฟล์เดิม โดยมีไฟล์และแพ็กเกจที่ติดตั้งไว้เหมือนเดิมราวกับว่าไม่เคยหยุดทำงาน ขั้นตอนถัดไปจะใช้ข้อมูลนี้เพื่อดาวน์โหลด 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

API จะแสดงผล environment_id จริงแม้จะมี environment="remote" แซนด์บ็อกซ์ทำงานแล้ว สิ่งที่ขาดหายไปคือการกำหนดค่า ซึ่งไม่มีเสียง ไม่มีทักษะ และไม่มีเครื่องมือสร้าง PDF เอเจนต์เพียงแค่พิมพ์เรื่องราวเป็นข้อความแล้วก็หยุด ขั้นตอนถัดไปคือการเพิ่มข้อมูลเหล่านั้น

เอาต์พุตแต่ละบรรทัดจะแมปกับเหตุการณ์จาก run_stream() ดังนี้

step.type

คำอธิบาย

สิ่งที่ run_stream() พิมพ์

"url_context_call"

ตัวแทนดึงข้อมูล URL

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

"code_execution_call"

Agent ที่รันโค้ดในแซนด์บ็อกซ์

[tool] run_code

"google_search_call"

เอเจนต์กำลังค้นหาในเว็บ

[tool] google_search

"function_call"

เครื่องมือไฟล์และอื่นๆ

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

step.delta เมื่อ delta.type == "text"

ตัวแทนเขียนข้อความ

สตรีมไปยัง stdout โดยตรง

5. ปรับแต่ง Agent

ตัวแทนไม่มีคำสั่ง ไม่ว่าจะเป็นเสียง ทักษะ หรือเครื่องมือสร้าง PDF ในขั้นตอนนี้ คุณจะโหลดไฟล์การกำหนดค่าจาก .agents/ และติดตั้งไฟล์เหล่านั้นลงในแซนด์บ็อกซ์

สิ่งที่ต้องเปลี่ยน

ทำการเปลี่ยนแปลง 4 อย่างใน run_digest.py ดังนี้

TODO 2: ใต้ load_source() ให้เพิ่มค่าคงที่ระดับโมดูล 3 รายการ (ค่าคงที่เหล่านี้อยู่นอก 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 คือโปรแกรมแสดงผลที่สร้างไว้ล่วงหน้าซึ่งตัวแทนจะเรียกใช้

ตอนนี้ให้ทำการเปลี่ยนแปลงอีก 2 รายการภายใน run_digest() ดังนี้

TODO 3: เปลี่ยน environment จาก "remote" เป็นพจนานุกรมแหล่งที่มา และตั้งค่า 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,
                },
            ],
        },

สิ่งที่ต้องทำ 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 แล้ว)

ซึ่งจะเขียนทั้ง 2 รหัสไปยัง .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

การเรียกใช้จะใช้เวลา 1-3 นาที คุณควรเห็นเอเจนต์อ่านไฟล์การกำหนดค่า เขียนข้อมูลสรุป และบันทึก 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 ตอนนี้เป็นค่าจริงแล้ว Sandbox ทำงานด้วยไฟล์กำหนดค่าของคุณ และ Agent สร้าง digest.pdf ขั้นตอนถัดไปคือการดาวน์โหลด

6. ดาวน์โหลด PDF

ตัวแทนเขียน digest.pdf ถึง /workspace/digest.pdf ภายในแซนด์บ็อกซ์ ภาพรวมสภาพแวดล้อมจะพร้อมใช้งานเป็นไฟล์เก็บถาวร tar ผ่าน Gemini Files API

ติดตั้ง requests หากจำเป็น

uv pip install requests

สิ่งที่ต้องกรอก

เปิด download_pdf.py โดยมีสิ่งที่ต้องทำ 2 รายการ

สิ่งที่ต้องทำ 1: กรอกข้อมูลในrequests.get() call:

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

URL จะระบุภาพรวมของแซนด์บ็อกซ์ params={"alt": "media"} จะแสดงผลไบต์ดิบแทนข้อมูลเมตา GEMINI_API_KEYที่มีอยู่จะตรวจสอบสิทธิ์ Files API ด้วย

TODO 2: ค้นหาและแยกไฟล์ PDF จากที่เก็บถาวร tar

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

คำนำหน้าเส้นทาง tar จะแตกต่างกันไปในแต่ละการเรียกใช้ ดังนั้นให้ค้นหาตามคำต่อท้ายแทนที่จะเขียนโค้ดเส้นทางที่แน่นอน filter="data" จะไม่แสดงคำเตือนการเลิกใช้งาน Python 3.13 เกี่ยวกับการแยกไฟล์ tar ที่ไม่ปลอดภัย

ยืนยัน

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

เปิด digest.pdf ในไดเรกทอรีเดียวกัน ซึ่งมีข้อมูลสรุปที่จัดรูปแบบแล้วซึ่งเอเจนต์สร้างจากหน้าเว็บที่ใช้งานจริง

7. สานต่อการสนทนา

คุณมี digest.pdf อยู่แล้ว หากต้องการเพียงแค่ไฟล์ ก็ถือว่าเสร็จสิ้น ขั้นตอนนี้เกี่ยวข้องกับสิ่งอื่น นั่นคือการขอให้ Agent เปลี่ยนข้อมูลสรุปโดยไม่ต้องดึงข้อมูลเว็บอีกครั้ง

Sandbox ยังคงใช้งานได้ เอเจนต์ยังคงมี /workspace/digest.pdf และจดจำทุกเรื่องราวที่สรุป การinteractions.create()เรียกใช้interactions.create()ครั้งที่ 2 จะส่งข้อความติดตามผลไปยังแซนด์บ็อกซ์เดียวกัน ในที่นี้ คุณขอให้เพิ่มหมายเหตุ "เหตุผลที่เรื่องนี้สำคัญ" ใต้แต่ละเรื่อง และอัปเดต PDF ในตำแหน่งเดิมโดยไม่ต้องดึงข้อมูลหรือสรุปใหม่

สิ่งที่ต้องกรอก

เปิด refine_digest.py มีสิ่งที่ต้องทำ 3 รายการ

สิ่งที่ต้องทำ 1 และ 2: กรอกพารามิเตอร์การสนทนาไปมา 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 จึงไม่ต้องอัปเดต

พารามิเตอร์ 2 รายการที่ทำให้การสนทนาไปมาทำงานได้

รหัส

สิ่งที่ยังคงอยู่

การอุปมา

environment=environment_id

ไฟล์ แพ็กเกจที่ติดตั้ง สถานะระบบ: ทุกอย่างในระบบไฟล์ Linux

การใช้โต๊ะทำงานเดียวกันระหว่างการประชุม

previous_interaction_id=interaction_id

ประวัติการสนทนา: สิ่งที่ Agent พูดและทำในรอบก่อนหน้า

จดจำเนื้อหาที่พูดคุยกันในการประชุมครั้งล่าสุด

คุณจะส่งบัตรประจำตัวอย่างใดอย่างหนึ่งแยกกันได้ ดังนี้

  • environment_id เท่านั้น: ใช้ไฟล์และแพ็กเกจซ้ำ แต่เริ่มการสนทนาใหม่ มีประโยชน์สำหรับงานใหม่ในพื้นที่ทำงานเดียวกัน
  • previous_interaction_id เท่านั้น: ดำเนินบริบทการสนทนาต่อ แต่ในแซนด์บ็อกซ์ใหม่ (ไฟล์จะหายไป)
  • ทั้ง 2 อย่าง: ความต่อเนื่องเต็มรูปแบบ ซึ่งเป็นสิ่งที่ขั้นตอนนี้ใช้

ไม่มี environment_id: แซนด์บ็อกซ์เปล่า ไม่มี PDF หากไม่มี previous_interaction_id: ไม่มีบริบท ตัวแทนจะปรับแต่งส่วนใดส่วนหนึ่งไม่ได้

ยืนยัน

uv run python refine_digest.py

สตรีมควรจะรวดเร็ว เนื่องจาก Agent ไม่ได้ดึงข้อมูลใดๆ อีก หลังจากดำเนินการเสร็จแล้ว ให้ทำดังนี้

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

เปิด digest_v2.pdf แล้วเปรียบเทียบกับ digest.pdf ตอนนี้แต่ละเรื่องควรมีบรรทัด "ทำไมถึงสำคัญ" เพิ่มเข้ามาแล้ว

8. คงการกำหนดค่า Agent ที่มีการจัดการ

การโทรทุกครั้งที่ผ่านมาผ่าน 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 มีรายการสิ่งที่ต้องทำ 1 รายการ (สิ่งที่ต้องทำ 1)

โปรดทราบว่าค่าคงที่จะนำเข้าจาก run_digest.py โดยตรง (ไม่มีการทำซ้ำ)

from run_digest import BASE_AGENT, AGENTS_MD, SKILL_MD, GENERATE_PDF_PY

สิ่งที่ต้องทำ 1: กรอกข้อมูลในagents.create() call:

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 และจะติดตั้งโดยอัตโนมัติในการเรียกใช้ครั้งต่อๆ ไป เรียกใช้เพียงครั้งเดียว ไม่ใช่ทุกครั้งที่เรียกใช้ข้อมูลสรุป

ยืนยัน: บันทึก Agent

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

เรียกใช้ Agent ที่บันทึกไว้

เปิด invoke_agent.py โดยจะเรียกใช้เอเจนต์ที่บันทึกไว้ตามรหัสโดยไม่มีแหล่งที่มา

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

เปรียบเทียบกับคำสั่งเรียกใช้แบบอินไลน์: agent=BASE_AGENT จะแทนที่ด้วย "my-digest" และบล็อก environment แบบเต็มที่มีแหล่งที่มาแบบอินไลน์ 3 รายการจะแทนที่ด้วย environment="remote" การกำหนดค่าจะฝังไว้ในฝั่งของ Google อยู่แล้ว

ยืนยัน: เรียกใช้เอเจนต์ที่บันทึกไว้

uv run python invoke_agent.py

คุณควรเห็นไลฟ์สดเดียวกันกับการทดสอบในบรรทัด แต่การเรียกใช้จะไม่มีไฟล์ต้นฉบับ หลังจากเรียกใช้แล้ว ระบบจะอัปเดต ENVIRONMENT_ID และ INTERACTION_ID ใน .env เพื่อให้คุณใช้ 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. ล้าง

Sandbox จะหมดอายุโดยอัตโนมัติหลังจากไม่มีการใช้งานเป็นเวลา 7 วัน ไม่มีเซิร์ฟเวอร์ที่จะหยุด ไม่มีคอนเทนเนอร์ที่จะลบ

หากบันทึกการกำหนดค่าเอเจนต์ไว้ ให้ลบออกโดยทำดังนี้

uv run python delete_agent.py

10. สรุป

คุณสร้าง Agent ที่มีการจัดการตั้งแต่เริ่มต้นทีละแนวคิด แบบฝึกหัดแต่ละแบบสอนอะไรบ้าง

การออกกำลังกาย

แนวคิด

คีย์ API

โทรครั้งแรก

จัดสรรแซนด์บ็อกซ์ Linux จริงและสตรีมเหตุการณ์แบบสด

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

ปรับแต่ง Agent

ต่อเชื่อมไฟล์การกำหนดค่าและคงรหัสไว้ใน .env ในการเรียกใช้เดียวกัน

environment.sources, set_key

ดาวน์โหลด PDF

ดาวน์โหลด PDF โดยไม่ต้องเรียกใช้ Agent อีกครั้ง

Gemini Files API :download ใน download_pdf.py

สนทนาต่อ

สานต่อการสนทนาโดยไม่ต้องดึงข้อมูลเว็บอีกครั้ง

environment=environment_id, previous_interaction_id=interaction_id

คงการกำหนดค่า Agent

คงการกำหนดค่าตัวแทน เรียกใช้ตามรหัส ไม่ต้องระบุแหล่งที่มา

agents.create(), agents.list()

รูปแบบสำคัญ

  1. การเรียกใช้ครั้งเดียว แซนด์บ็อกซ์เดียว: interactions.create() จัดการโครงสร้างพื้นฐานทั้งหมด (ไม่ต้องติดตั้งใช้งานคอนเทนเนอร์ ไม่ต้องติดตั้งแพ็กเกจในเครื่อง)
  2. การสตรีมแบบก้าวหน้า: stream=True เปลี่ยนกล่องดำขนาด 90 วินาทีให้เป็นฟีดสดของการเรียกใช้เครื่องมือและข้อความ
  3. แหล่งที่มาแบบอินไลน์: ติดตั้ง AGENTS.md, SKILL.md และสคริปต์ที่สร้างไว้ล่วงหน้าลงในแซนด์บ็อกซ์โดยไม่ต้องดำเนินการอัปโหลดหรือติดตั้งใช้งาน
  4. ใช้ประโยชน์จากการค้นหาอัตโนมัติ: ระบบจะเลือกไฟล์ที่วางไว้ใน .agents/ โดยอัตโนมัติ (ไม่ต้องกำหนดค่า SDK)
  5. สถานะ 2 มิติ: environment_id ติดตามไฟล์และแพ็กเกจ previous_interaction_id ติดตามบริบทการสนทนา โดยส่งแยกกันได้
  6. การดาวน์โหลดสแนปชอต: สภาพแวดล้อมคือไฟล์ tar ของระบบไฟล์แบบเต็ม ซึ่งเข้าถึงได้ผ่าน Gemini Files API
  7. ตัวแทนที่ระบุชื่อ: agents.create()ฝังการกำหนดค่าอย่างถาวร การเรียกใช้ในอนาคตจะส่งเฉพาะรหัสตัวแทนและ environment="remote" โดยไม่มีแหล่งที่มา

ADK + Cloud Run กับ Agent ที่ได้รับการจัดการ: ความแตกต่างโดยย่อ

ความสามารถ

ADK + Cloud Run

Agent ที่ได้รับการจัดการใน Gemini API

จัดสรรแซนด์บ็อกซ์

docker build + gcloud run deploy

interactions.create()

กำหนดเครื่องมือ

ฟังก์ชัน Python ที่ลงทะเบียนกับเอเจนต์

ในตัว: การท่องเว็บ การเรียกใช้โค้ด ระบบไฟล์

ติดตั้งแพ็กเกจ

pip install ใน Dockerfile

Agent ทำงาน pip install ภายในแซนด์บ็อกซ์

สตรีมกิจกรรม

โครงสร้างพื้นฐาน SSE ที่กำหนดเอง

stream=True

ดำเนินการต่อในเซสชัน

ฐานข้อมูลเซสชัน + การแทรกบริบท

environment_id + previous_interaction_id

ไฟล์การกำหนดค่า

ฝังไว้ใน Agent หรือแทรกเมื่อเริ่มต้น

ติดตั้งผ่าน environment.sources

โครงสร้างพื้นฐานที่จะจัดการ

คอนเทนเนอร์, Cloud Run, IAM, ข้อมูลลับ

ไม่มี

ขั้นตอนถัดไป