Show / hide languages:

📋 Course Plans · AI Agent Connectors

Six 90-minute sessions building a local AI agent (Ollama + Hermes 3 + LlamaIndex) that connects to Gmail, Calendar, CRM, support, and social — same Python stack from the Mac & Windows extras series.

6 บทเรียน บทละ 90 นาที สร้าง AI agent บนเครื่องตัวเอง (Ollama + Hermes 3 + LlamaIndex) เชื่อมเข้ากับ Gmail, ปฏิทิน, CRM, ฝ่ายดูแลลูกค้า และโซเชียล — Python stack เดียวกับซีรีส์ extras บน Mac และ Windows

六堂 90 分钟课程,搭建本地 AI 代理(Ollama + Hermes 3 + LlamaIndex),把它接到 Gmail、日历、CRM、客服和社交 — 与 Mac/Windows 进阶系列同一套 Python 技术栈。

🦙 Ollama ⚡ Hermes 3 🔗 LlamaIndex ReActAgent 🛠️ FunctionTool ⏰ launchd / Task Scheduler 🌶️ Flask webhook
📈 Your progress
📈 ความคืบหน้าของคุณ
📈 你的进度
0 / 30 checks

🦙 The stack — local-first, agent-driven

🇬🇧 The architecture

Every lab in this course runs against the same local stack you built in the Mac/Windows extras: Ollama serving Hermes 3, wrapped in a LlamaIndex ReActAgent with Python FunctionTools. No paid API keys, no cloud LLM.

Each week adds new FunctionTools to agent_pro.py, plus an OAuth flow when the system requires it.

🇹🇭 สถาปัตยกรรม

ทุกแล็บในหลักสูตรนี้ใช้ stack เดียวกับใน Mac/Windows extras: Ollama รัน Hermes 3 ห่อด้วย LlamaIndex ReActAgent และ FunctionTool ของ Python ไม่มี API key เสียเงิน ไม่มี cloud LLM

แต่ละสัปดาห์เพิ่ม FunctionTool ใหม่ลงใน agent_pro.py พร้อม OAuth flow เมื่อระบบต้องการ

🇨🇳 架构

本课程的每个实战都跑在你在 Mac/Windows 进阶系列中搭好的同一套本地栈:Ollama 跑 Hermes 3,外层用 LlamaIndex ReActAgent 包装并通过 Python FunctionTool 接外部 API。不用付费 API、不依赖云端 LLM。

每周都向 agent_pro.py 添加新的 FunctionTool,需要授权时再加上 OAuth 流程。

🦙 ollama serve hermes3:8b ReActAgent LlamaIndex verbose=True Ollama(model="hermes3:8b") @FunctionTool read_unread_gmail() @FunctionTool list_free_slots() @FunctionTool upsert_hubspot() @FunctionTool redact_pii() @FunctionTool buffer_schedule() @FunctionTool send_line_push() ⏰ launchd Task Scheduler cron → agent.chat()
One Hermes brain. Many @FunctionTools. The OS schedules the script — not the agent itself. สมอง Hermes ตัวเดียว @FunctionTool หลายตัว ระบบปฏิบัติการเป็นคนตั้งเวลาให้สคริปต์ ไม่ใช่ agent 一个 Hermes 大脑、多个 @FunctionTool。由操作系统给脚本排定时任务 — 而不是代理自己。

The 6-week timeline

1 🔐 Foundations OAuth + Hermes read_unread_gmail 2 📧 Email draft + cron draft_reply, launchd 3 📅 Calendar free/busy + book list_free_slots 4 🤝 CRM idempotent upsert upsert_hubspot 5 🎧 Support 3-agent chain responder/reviewer 6 📱 Social + CAPSTONE buffer + end-to-end Each week adds tools to the same agent_pro.py — by Week 6 it touches all five systems
Same agent_pro.py grows each week as new FunctionTools are added. ไฟล์ agent_pro.py ขยายขึ้นทุกสัปดาห์เมื่อเพิ่ม FunctionTool ใหม่ 同一份 agent_pro.py 每周都长出新的 FunctionTool。

📚 Week-by-week plans

Click any week to expand its plan. Tick checkboxes as you complete each piece — your progress is saved locally.

คลิกที่สัปดาห์ไหนก็ได้เพื่อขยายดูแผน ติ๊กช่องเมื่อทำแต่ละส่วนเสร็จ — ความคืบหน้าจะถูกบันทึกไว้ในเครื่อง

点击任意一周展开计划。完成每个小项就勾选 — 进度会保存在你的浏览器中。

1

🔐 Foundations — OAuth + Hermes ReActAgent

Connect Gmail to a local Hermes agent. No paid LLM, no cloud.
เชื่อม Gmail เข้ากับ Hermes agent บนเครื่อง ไม่ใช้ LLM เสียเงิน ไม่ใช้คลาวด์
把 Gmail 接入本地 Hermes 代理。不用付费 LLM、不依赖云端。
Foundations
Your progress this week
Learning objectives
  • Define the AI-agent staircase
  • Complete OAuth without exposing a password
  • Register a Python function as a Hermes tool
Stack additions
  • google-auth-oauthlib
  • google-api-python-client
  • 1 new @FunctionTool
Top gotchas
  • OAuth scope too broad
  • Hermes calling tools in wrong order
  • Token JSON committed to git 😱
# agent_pro.py — add this FunctionTool (Week 1) def read_unread_gmail(label: str = "INBOX") -> str: """Return up to 10 unread Gmail messages matching a label.""" from googleapiclient.discovery import build creds = load_user_creds() # OAuth, cached locally svc = build("gmail", "v1", credentials=creds) msgs = svc.users().messages().list( userId="me", q=f"label:{label} is:unread", maxResults=10 ).execute().get("messages", []) return "\n---\n".join(snippet_of(m["id"], svc) for m in msgs) TOOLS.append(FunctionTool.from_defaults(read_unread_gmail))

💡 Pre-class checklist

ollama pull hermes3:8b · venv activated · agent_pro.py opens without errors.

🎓 Open lesson page →
2

📧 Email — daily briefing via launchd

Hermes drafts replies; launchd runs the script at 8 AM daily.
Hermes ร่างคำตอบ ส่วน launchd รันสคริปต์ทุกวัน 8 โมงเช้า
Hermes 起草回复,launchd 每天早上 8 点跑脚本。
Connector
Your progress this week
Learning objectives
  • Gmail labels as agent inputs
  • Draft-then-confirm pattern
  • OS-scheduled agent run (launchd / Task Scheduler)
Stack additions
  • 2 new @FunctionTools
  • ~/Library/LaunchAgents/com.kruai.daily.plist
  • A daily_brief.py entry point
Top gotchas
  • The "send" hallucination
  • Sleeping laptop misses 8 AM
  • Context drain on newsletters
# daily_brief.py — launchd points here at 08:00 daily from agent_pro import build_agent agent = build_agent() brief = agent.chat( "Read unread emails in label '@AI_Handle'. " "Output a 3-bullet summary, then save FAQ replies to Drafts. " "Do NOT send anything." ) print(brief)
🎓 Open lesson page →
3

📅 Calendar — free/busy + booking with timezone safety

Hermes converts ICT ↔ foreign-client timezones, checks conflicts before booking.
Hermes แปลงเวลา ICT ↔ โซนเวลาลูกค้าต่างชาติ และเช็คเวลาทับซ้อนก่อนจอง
Hermes 在 ICT 与海外客户时区之间换算,订之前先查冲突。
Connector
Your progress this week
Learning objectives
  • Free/busy scans
  • Timezone math (ICT vs UTC)
  • Conflict detection before book
Stack additions
  • 2 new @FunctionTools
  • zoneinfo.ZoneInfo("Asia/Bangkok")
  • Calendar API scopes
Top gotchas
  • Hermes "thinks" in UTC
  • Mid-task token expiry
  • Race: slot taken between propose & book
from zoneinfo import ZoneInfo ICT = ZoneInfo("Asia/Bangkok") def list_free_slots(day_iso: str, duration_min: int = 60) -> str: """1-hr free blocks on day_iso (YYYY-MM-DD), in ICT, 09:00-17:00.""" svc = build("calendar", "v3", credentials=load_user_creds()) fb = svc.freebusy().query(body={ "timeMin": f"{day_iso}T09:00:00+07:00", "timeMax": f"{day_iso}T17:00:00+07:00", "items": [{"id": "primary"}], }).execute() return compute_gaps(fb["calendars"]["primary"]["busy"])
🎓 Open lesson page →
4

🤝 CRM — idempotent contact upserts

HubSpot via REST + phone-number idempotency key. No duplicates.
HubSpot ผ่าน REST + ใช้เบอร์โทรเป็น idempotency key — ไม่มีข้อมูลซ้ำ
通过 REST 接 HubSpot,用电话号当幂等键 — 不出现重复记录。
Connector
Your progress this week
Learning objectives
  • Token tax & tool trimming
  • Idempotency keys
  • Pipeline as state machine
Stack additions
  • hubspot-api-client
  • 3 trimmed @FunctionTools
  • HubSpot token in .env
Top gotchas
  • Token-tax crash (giving Hermes 200 tools)
  • Duplicate contacts on retry
  • Premature "Closed Won"
def upsert_hubspot_contact(phone: str, name: str) -> str: """Find a contact by phone, or create one. Idempotent by phone.""" from hubspot import HubSpot hs = HubSpot(access_token=os.environ["HUBSPOT_TOKEN"]) found = hs.crm.contacts.search_api.do_search(filterGroups=...) if found.total > 0: return f"existing contact {found.results[0].id}" new = hs.crm.contacts.basic_api.create(properties={"phone": phone, "firstname": name}) return f"created contact {new.id}"
🎓 Open lesson page →
5

🎧 Support — three Hermes agents in a chain

Responder · Adversarial Reviewer · Closer. PII redacted before Hermes ever sees the ticket.
Responder · Adversarial Reviewer · Closer — ลบ PII ก่อน Hermes จะเห็น ticket
回复者 · 对抗审查者 · 关单者。Hermes 看到工单前先脱敏 PII。
Connector
Your progress this week
Learning objectives
  • RAG vs tool-calling
  • Confidence thresholds
  • Adversarial reviewer pattern
  • PII redaction
Stack additions
  • LlamaIndex VectorStoreIndex over policy PDF
  • 3 build_agent() instances
  • presidio-analyzer for PII
Top gotchas
  • Hallucinated refund exceptions
  • Language drift (EN reply to TH customer)
  • PII leaking into chat history
def support_pipeline(ticket: str) -> str: safe = redact_pii(ticket) draft = responder.chat(f"Using ONLY the policy index, draft a reply: {safe}") review = reviewer.chat(f"Critique this draft. Confidence 0-100. " f"HALT if refund > 1000 THB. Draft:\n{draft}") if "HALT" in review or confidence(review) < 90: return save_to_drafts(draft) return closer.chat(f"Send and close: {draft}")
🎓 Open lesson page →
6

📱 Social Media + Capstone

Buffer + Slack tools, then one prompt-chain touching all 5 connectors.
เครื่องมือ Buffer + Slack แล้วรวมทุก connector ทั้ง 5 ตัวใน prompt chain เดียว
Buffer + Slack 工具,再用一条提示链贯穿全部 5 个连接器。
Capstone
Your progress this week
Learning objectives
  • API rate limits / cost ceilings
  • Schedule, never post
  • Sentiment loops
  • End-to-end integration
Capstone rubric
  • Integration (4 pts)
  • Safety / HITL (3 pts)
  • Business logic (3 pts)
Top gotchas
  • Runaway loops burning the budget
  • Context bloat from raw feeds
  • Agent bypassing Buffer to post live
# capstone.py — Instagram DM → support → CRM → calendar → email agent = build_agent() # now has ALL the tools from weeks 1-5 + Buffer response = agent.chat(""" An Instagram DM just arrived: "Hi, do you have a 3-day jungle trek?" 1. Answer using the support policy index. 2. Upsert the sender in HubSpot (phone is the idempotency key). 3. Propose 3 calendar slots, all in ICT. 4. Draft a confirmation email with a packing list. 5. Never send or post without my review. """)

⚠️ Capstone constraint

The capstone must run against the local Hermes stack only — no proprietary LLM allowed. This proves the whole pipeline works without cloud dependencies.

🎓 Open lesson page →

🎓 What you'll have built by Week 6

📂

A growing agent_pro.py

agent_pro.py ที่ขยายขึ้นเรื่อย ๆ

不断成长的 agent_pro.py

~12 FunctionTools across Email, Calendar, CRM, Support, Social.

FunctionTool ราว 12 ตัว ครอบคลุม Email, Calendar, CRM, Support, Social

大约 12 个 FunctionTool,覆盖邮件、日历、CRM、客服、社交。

⏰

A scheduled morning brief

บรีฟตอนเช้าตามเวลา

每天早晨的自动简报

launchd / Task Scheduler running daily_brief.py at 8 AM.

launchd / Task Scheduler รัน daily_brief.py 8 โมงเช้า

launchd / Task Scheduler 每天早 8 点跑 daily_brief.py。

🛡️

A 3-agent support pipeline

ไปป์ไลน์ support ที่มี 3 agent

三代理客服流水线

Responder + Reviewer + Closer with PII redaction and 1,000 THB HITL.

Responder + Reviewer + Closer ลบ PII และ HITL ที่ 1,000 บาท

回复者 + 审查者 + 关单者,含 PII 脱敏与 1,000 泰铢人工介入。

🌐

An end-to-end capstone

โครงงานรวบยอด end-to-end

端到端综合项目

One prompt: Instagram DM → support → CRM → calendar → email draft.

หนึ่ง prompt: Instagram DM → support → CRM → ปฏิทิน → ร่างอีเมล

一条提示:Instagram 私信 → 客服 → CRM → 日历 → 邮件草稿。