ErawanEN

Hermes Agent

NousResearch ทำเอเจนต์มาให้แล้ว เหลือแค่หาที่รัน

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

1. สิ่งที่กำลังจะขึ้นระบบคืออะไร

NousResearch/hermes-agent ปล่อยอิมเมจคอนเทนเนอร์ออกมาให้ ข้างในนั้นนอกจากตัวเอเจนต์ยังมีอะแดปเตอร์ LINE ที่เป็นแพลตฟอร์มชั้นหนึ่ง อยู่ชั้นเดียวกับ Telegram, Discord, Slack, WhatsApp, Teams, SMS และ WeCom มันตรวจลายเซ็นของเว็บฮุกเอง ตัดข้อความยาวให้พอดีกับห้าบับเบิลของ LINE ส่งรูปและเสียงได้ มีรายชื่อผู้ใช้และกลุ่มที่อนุญาต และตัดข้อความซ้ำที่ LINE ส่งมาสองรอบทิ้ง

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

บทนี้จึงไม่มีโค้ดเลย มีสองไฟล์ และไม่มีไฟล์ไหนเป็นโปรแกรม

2. สองไฟล์นั้น

อิมเมจนี้ไม่ประกาศทั้ง ENTRYPOINT และ CMD — อ่านจากตัวอิมเมจ ไม่ใช่จากเอกสาร — Dockerfile ที่ไม่บอกคำสั่งจึงรันอะไรไม่ได้เลย และ gateway ไม่ใช่โปรแกรม แต่เป็นซับคอมมานด์ของไบนารี สั่ง gateway run เฉย ๆ จะได้ sh: gateway: not found

Dockerfile
FROM nousresearch/hermes-agent:v2026.9.7

# เว็บฮุกฟังที่พอร์ต 8646 ที่พาธ /line/webhook และปลั๊กอิน LINE
# จะเปิดตัวเองเมื่อมีคีย์ทั้งสองตัวอยู่ใน environment
# ไม่ต้องเขียนไฟล์ config และไม่ต้องเลือกแพลตฟอร์ม
ENV LINE_PORT=8646

# แดชบอร์ดคือที่ตัดสินใจว่าเอเจนต์ทำอะไรได้บ้าง — เทอร์มินัล การรันโค้ด
# การใช้คอมพิวเตอร์ และเบราว์เซอร์ เปิดไว้หมดตั้งแต่ต้น
# นั่นเป็นการตัดสินใจของเจ้าของ จึงเสิร์ฟหน้านี้ออกมา ไม่ใช่เดาแทนตอน deploy
ENV HERMES_DASHBOARD=1 \
    HERMES_DASHBOARD_PORT=9119

EXPOSE 8646 9119

CMD ["/opt/hermes/bin/hermes", "gateway", "run"]

อีกไฟล์คือ manifest access: owner ปิดแอปไม่ให้ใครเข้าถึงนอกจากบัญชีคุณ ส่วนพาธเดียวที่ LINE ต้องเข้าถึงได้จะเปิดคืนตอน deploy เพราะ LINE ยิงเข้ามาโดยไม่มีเซสชัน และไม่มีทางเข้าสู่ระบบ

erawan.yaml
version: 1
access: owner
components:
  web:
    path: .
    port: 8646
    public: true
    # แดชบอร์ด บนชื่อของตัวเอง คอนเทนเนอร์เดียวกัน HERMES_HOME เดียวกัน
    # ถ้าแยกเป็นสอง component จะแชร์ดิสก์ก้อนนี้ไม่ได้
    ports:
      9119: hermes-admin
    # เซสชันและความจำ HERMES_HOME ชี้มาที่นี่ในคำสั่งข้างล่าง
    disk: true
    # ประกาศไว้ แต่ไม่ถูกส่งผ่าน: deploy จะหยุดรอให้คุณกรอกเองในหน้าแอป
    # ไม่มีคีย์ไหนผ่านมือเอไอ
    secrets:
      [
        LINE_CHANNEL_ACCESS_TOKEN,
        LINE_CHANNEL_SECRET,
        OPENROUTER_API_KEY,
        HERMES_DASHBOARD_BASIC_AUTH_PASSWORD,
      ]
    resources:
      requests: {memory: 512Mi, cpu: 250m}
      limits:   {memory: 2048Mi, cpu: 1000m}

3. สั่งขึ้นระบบ

erawan deploy . --name NAME --port 8646 --access owner --public-path /line/webhook --env HERMES_HOME=/data --env LINE_PUBLIC_URL=https://NAME.erawan.app --env HERMES_DASHBOARD_BASIC_AUTH_USERNAME=owner

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

4. คีย์ไม่ได้อยู่ในคำสั่ง

deploy จะหยุดก่อนเริ่มอะไรทั้งนั้น แล้วพิมพ์ลิงก์ออกมา มีสี่คีย์ที่ประกาศไว้ใน manifest และไม่มีตัวไหนผ่านเอไอที่กำลังทำ deploy ให้ หรือผ่านประวัติคำสั่งในเทอร์มินัลของคุณ

คีย์

เอามาจากไหน

LINE_CHANNEL_ACCESS_TOKEN

LINE Developers console

LINE_CHANNEL_SECRET

LINE Developers console

OPENROUTER_API_KEY

ผู้ให้บริการโมเดลที่คุณจ่ายเงิน

HERMES_DASHBOARD_BASIC_AUTH_PASSWORD

คุณตั้งเอง

เปิดลิงก์ กรอกในหน้าแอปของตัวเอง แล้ว deploy จะไปต่อ ตัวสุดท้ายถูกประกาศไว้ด้วยเหตุผล: Hermes ไม่ยอมเปิดแดชบอร์ดออกนอก loopback ถ้าไม่มีระบบยืนยันตัวตน และแดชบอร์ดคือหน้าที่ตัดสินว่า เอเจนต์ทำอะไรได้บ้าง อ่านเรื่องการเก็บคีย์ต่อได้ที่นี่

5. คอนเทนเนอร์เดียว ได้สองที่อยู่

ที่อยู่

คืออะไร

NAME.erawan.app/line/webhook

เอาไปวางใน LINE Developers

hermes-admin.erawan.app

แดชบอร์ด มีหน้าล็อกอินของตัวเอง

จากนั้นตั้ง webhook URL ใน LINE Developers console แล้วกด Verify ทักไปหาบัญชีนั้นหนึ่งข้อความ เท่านี้จบ

6. ราคา และสิ่งที่เรารู้เพราะรันเอง

ขนาดนี้อยู่ในแพ็ก Hobby — ฿99 ต่อเดือน เพดานใน manifest คือหนึ่งคอร์ ซึ่งคือสิ่งที่ Hobby ให้ ส่วนที่จองไว้คือ 250m เอเจนต์ที่นั่งรออยู่จึงแทบไม่กินอะไรเลย และตัวที่ทำงานหนักจะถูกหน่วง ไม่ใช่ถูกปฏิเสธ ขยับแพ็กขึ้นคือสิ่งที่ซื้อคอร์ที่สอง

เราเดินเรื่องนี้จริงบน production ด้วยบัญชีจริงและช่อง LINE จริง และใช้ไปสาม deploy ทุกความล้มเหลวเป็นของเรา ไม่ใช่ของ template และไม่มีอันไหนหาเจอได้โดยไม่ลงมือรัน: worker ที่ไม่มีวันพร้อมเพราะทุก workload ถูกตรวจสุขภาพ รวมถึงตัวที่ไม่ได้ฟังพอร์ตไหนเลย; ชื่อพอร์ตที่ถูกจองและถูกคืนในวินาทีเดียวกัน ทำให้แดชบอร์ดตอบ 404 ทั้งที่ข้างใต้ถูกทุกอย่าง; และแอปที่ใช้ manifest แล้วพาธสาธารณะหายไปเงียบ ๆ ทำให้เว็บฮุกตอบหน้าเข้าสู่ระบบแทน อันสุดท้ายเกิดกับแอปที่ใช้ manifest ทุกตัว ที่มีเว็บฮุกหรือ callback การชำระเงิน และคนที่รู้ก่อนคือ LINE หรือ Stripe ไม่ใช่เจ้าของแอป

ทั้งสามเรื่องแก้แล้ว ที่เล่าให้ฟังเพราะหน้าที่บอกว่า deploy แรกผ่านฉลุย คือหน้าที่เขียนโดยคนที่ไม่ได้ลงมือทำ

บทเรียนทั้งหมด