🎯 Learning objectives
Define the staircase
Distinguish a chatbot from a tool-using ReActAgent and place each on the staircase.
แยกแยะระหว่าง chatbot กับ ReActAgent ที่ใช้เครื่องมือ และวางตำแหน่งบนขั้นบันได
区分聊天机器人与会用工具的 ReActAgent,并把它们放到阶梯上对应的位置。
Complete OAuth in Python
Run a Google OAuth flow and cache the refresh token locally — without ever exposing your password.
รัน OAuth flow ของ Google และเก็บ refresh token ไว้ในเครื่อง โดยไม่เปิดเผยรหัสผ่าน
在 Python 里跑完 Google OAuth 流程并把 refresh token 缓存到本地 — 不暴露密码。
Register a FunctionTool
Add a Python function to agent_pro.py, wrap it with FunctionTool.from_defaults, verify Hermes picks it up.
เพิ่มฟังก์ชัน Python ใน agent_pro.py ห่อด้วย FunctionTool.from_defaults แล้วดู Hermes เลือกใช้
在 agent_pro.py 中加一个 Python 函数,用 FunctionTool.from_defaults 包装,确认 Hermes 能识别并调用。
🔑 Interactive: the OAuth handshake
Click Next step to walk through every actor in the OAuth dance — see who sends what to whom, and which secrets never leave your laptop.
กด Next step เพื่อเดินผ่านทุกตัวละครในการ OAuth — ดูว่าใครส่งอะไรให้ใคร และความลับไหนไม่เคยออกจากเครื่อง
点击 Next step 逐步看完 OAuth 流程 — 谁向谁发了什么、哪些机密从不离开你的电脑。
⚠️ The password never moves
Your Google password is typed into Google's page, not into Python. Hermes only ever holds a short-lived access_token with the gmail.readonly scope.
รหัสผ่าน Google ของคุณพิมพ์ที่หน้า Google เท่านั้น ไม่ได้ส่งเข้า Python Hermes ถือเพียง access_token อายุสั้นที่มีสิทธิ์ gmail.readonly
你的 Google 密码只输入到 Google 自己的页面,不会进入 Python。Hermes 只持有一个短期 access_token,权限范围是 gmail.readonly。
📚 Key concepts
🇬🇧 English
The staircase — chatbot → copilot → tool-using agent → proactive agent (cron-triggered).
OAuth scopes — Google's valet key. readonly lets the agent read; compose lets it draft; send lets it send. Always grant the least.
ReActAgent + FunctionTool — LlamaIndex's ReAct loop makes Hermes pick which Python function to call. Clear docstrings + type hints are the contract.
🇹🇭 ไทย
ขั้นบันได — chatbot → copilot → agent ที่ใช้เครื่องมือ → agent แบบ proactive (ทำงานตาม cron)
OAuth scopes — กุญแจ valet ของ Google: readonly ให้อ่าน compose ให้ร่าง send ให้ส่ง — ให้น้อยที่สุดเสมอ
ReActAgent + FunctionTool — ReAct loop ของ LlamaIndex ทำให้ Hermes เลือกฟังก์ชันมาเรียก docstring กับ type hint คือสัญญา
🇨🇳 中文
阶梯 — 聊天机器人 → 副驾驶 → 工具型代理 → 主动型代理(由 cron 触发)。
OAuth 权限范围 — Google 的"代客钥匙":readonly 只读、compose 可起草、send 可发送 — 永远只授最小权限。
ReActAgent + FunctionTool — LlamaIndex 的 ReAct 循环让 Hermes 选择调用哪个 Python 函数;docstring 和类型注解就是接口约定。
🧪 Hands-on lab
Install OAuth deps in your existing venv
From the same venv you used for the Mac/Windows stack:
ใน venv เดียวกับที่ใช้ใน Mac/Windows stack:
在你跑 Mac/Windows 栈用过的同一个 venv 里:
Add a small gmail_auth.py helper
It runs the browser-based consent flow once, then caches the token to disk so subsequent runs are silent.
รัน consent flow ในเบราว์เซอร์ครั้งแรก แล้วเก็บ token ไว้ในไฟล์ ครั้งต่อ ๆ ไปจะเงียบ
第一次会在浏览器里完成同意流程,之后把 token 缓存到磁盘,后续直接静默使用。
Add the first FunctionTool to agent_pro.py
Append below the existing tools (web_search, generate_image …):
เพิ่มต่อจากเครื่องมือเดิม (web_search, generate_image …):
追加在现有工具(web_search、generate_image …)之后:
💡 docstring = tool description
Hermes reads the docstring to decide when to call this tool. Vague docstring → bad tool selection. Clear examples in the docstring are gold.
Hermes อ่าน docstring เพื่อตัดสินว่าจะเรียกเครื่องมือนี้ เมื่อไหร่ docstring คลุมเครือ = เลือกเครื่องมือผิด ตัวอย่างชัด ๆ ใน docstring มีค่ามาก
Hermes 通过 docstring 决定什么时候调用这个工具。模糊的 docstring 会让它选错工具;写清楚示例非常关键。
Run it
Now revoke the app from your Google permissions page, delete gmail_token.json, ask the same question — and watch the agent fail gracefully. That's the staircase made concrete.
ลองเข้า หน้าจัดการสิทธิ์ Google เพิกถอน แอป แล้วลบ gmail_token.json ถามคำถามเดิม — agent จะ fail แบบ graceful ให้คุณดู
现在到 Google 权限页 撤销这个应用,并删除 gmail_token.json,再问同样的问题 — 看代理如何优雅地失败。阶梯就这么具体地体现出来了。
⚠️ Top gotchas
1. OAuth scope too broad
Start with gmail.readonly only. Don't grant gmail.send in Week 1.
เริ่มที่ gmail.readonly เท่านั้น อย่าเพิ่ง gmail.send ในสัปดาห์ 1
起步只用 gmail.readonly,第一周别给 gmail.send。
2. Hermes doesn't see the tool
Forgot to append to TOOLS or didn't restart. Hermes only sees what's in TOOLS at startup.
ลืม append เข้า TOOLS หรือไม่ได้ restart agent Hermes เห็นเฉพาะที่อยู่ใน TOOLS ตอนเริ่ม
忘了 append 到 TOOLS 或没重启。Hermes 只看启动时 TOOLS 里的工具。
3. Token JSON in git
The cached gmail_token.json is a credential. echo gmail_token.json >> .gitignore right now.
gmail_token.json ที่เก็บไว้ = credential เพิ่มเข้า .gitignore เดี๋ยวนี้เลย
缓存的 gmail_token.json 就是凭证。立刻把它加进 .gitignore。
📝 Assessment & homework
✅ Assessment
Practical: show Hermes returning a summary of your top 3 unread emails. Conceptual: explain (EN/TH/中文) why Hermes never sees your Google password.
ภาคปฏิบัติ: ให้ Hermes สรุปอีเมลที่ยังไม่อ่าน 3 ฉบับแรก ภาคทฤษฎี: อธิบาย (EN/TH/中文) ว่าทำไม Hermes ไม่เห็นรหัสผ่าน Google ของคุณ
实操:让 Hermes 总结你前 3 封未读邮件。概念:用 EN/TH/中文 说明为什么 Hermes 永远看不到你的 Google 密码。
🏠 Homework
Use the agent to paraphrase (don't draft, don't send) replies to 3 complex client emails. Note one place Hermes misunderstood the business context — we'll fix it in Week 2.
ใช้ agent เรียบเรียงใหม่ (ยังไม่ร่าง ยังไม่ส่ง) คำตอบสำหรับอีเมลลูกค้า 3 ฉบับ จดจุดที่ Hermes เข้าใจผิด — สัปดาห์ 2 จะมาแก้กัน
用代理转述(不要起草、不要发送)3 封复杂客户邮件。记下 Hermes 误解业务背景的一处 — 下周修正。