<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nisit Sirimarnkit</title>
    <description>The latest articles on Forem by Nisit Sirimarnkit (@nisit15).</description>
    <link>https://forem.com/nisit15</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F408531%2Fcc1c9a4d-369a-4515-add7-e1f78a42294e.jpeg</url>
      <title>Forem: Nisit Sirimarnkit</title>
      <link>https://forem.com/nisit15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nisit15"/>
    <language>en</language>
    <item>
      <title>สร้าง AI Agent บน LINE ด้วย Garudust (Rust) — ตั้งแต่ต้นจนใช้งานได้จริง</title>
      <dc:creator>Nisit Sirimarnkit</dc:creator>
      <pubDate>Thu, 14 May 2026 05:06:47 +0000</pubDate>
      <link>https://forem.com/nisit15/sraang-ai-agent-bn-line-dwy-garudust-rust-tangaettncchnaichngaanaidcchring-4pgj</link>
      <guid>https://forem.com/nisit15/sraang-ai-agent-bn-line-dwy-garudust-rust-tangaettncchnaichngaanaidcchring-4pgj</guid>
      <description>&lt;p&gt;ถ้าคุณอยากมี AI Agent ส่วนตัวที่คุยได้ผ่าน LINE โดยไม่ต้องพึ่ง no-code platform บทความนี้จะพาคุณทำตั้งแต่ต้นจนจบ เครื่องมือที่ใช้คือ &lt;strong&gt;&lt;a href="https://github.com/garudust-org/garudust-agent" rel="noopener noreferrer"&gt;Garudust&lt;/a&gt;&lt;/strong&gt; — AI Agent framework เขียนด้วย Rust รองรับ OpenAI, Anthropic, Ollama, vLLM และ OpenAI-compatible endpoint ทุกเจ้า&lt;/p&gt;




&lt;h2&gt;
  
  
  สิ่งที่ต้องมี
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;เซิร์ฟเวอร์ Linux หรือ macOS (หรือรันบน VPS ก็ได้)&lt;/li&gt;
&lt;li&gt;บัญชี LINE Developers (ฟรี) → &lt;a href="https://developers.line.biz" rel="noopener noreferrer"&gt;developers.line.biz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;API Key จาก OpenAI, Anthropic, หรือ endpoint อื่นๆ&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ngrok.com" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; — &lt;strong&gt;เฉพาะกรณีรันบนเครื่องตัวเองที่ไม่มี public IP&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. ติดตั้ง Garudust
&lt;/h2&gt;

&lt;h3&gt;
  
  
  วิธีที่ 1 — ดาวน์โหลด binary
&lt;/h3&gt;

&lt;p&gt;ไปที่ &lt;a href="https://github.com/garudust-org/garudust-agent/releases" rel="noopener noreferrer"&gt;Releases&lt;/a&gt; แล้วดาวน์โหลดไฟล์ที่ตรงกับระบบของคุณ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Linux x86_64&lt;/span&gt;
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://github.com/garudust-org/garudust-agent/releases/latest/download/garudust-v0.3.1-x86_64-unknown-linux-musl.tar.gz
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; garudust-&lt;span class="k"&gt;*&lt;/span&gt;.tar.gz
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;garudust&lt;span class="k"&gt;*&lt;/span&gt;/garudust garudust&lt;span class="k"&gt;*&lt;/span&gt;/garudust-server /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  วิธีที่ 2 — Build จาก source (ต้องมี Rust 1.87+)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/garudust-org/garudust-agent.git
&lt;span class="nb"&gt;cd &lt;/span&gt;garudust-agent
cargo build &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--bin&lt;/span&gt; garudust &lt;span class="nt"&gt;--bin&lt;/span&gt; garudust-server
&lt;span class="nb"&gt;sudo cp &lt;/span&gt;target/release/garudust target/release/garudust-server /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตรวจสอบว่าติดตั้งสำเร็จ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="nt"&gt;--version&lt;/span&gt;
garudust-server &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2. ตั้งค่า LINE Messaging API
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;เข้าไปที่ &lt;a href="https://developers.line.biz" rel="noopener noreferrer"&gt;LINE Developers Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;สร้าง &lt;strong&gt;Provider&lt;/strong&gt; ใหม่ (หรือใช้อันที่มีอยู่)&lt;/li&gt;
&lt;li&gt;สร้าง &lt;strong&gt;Channel&lt;/strong&gt; ประเภท &lt;strong&gt;Messaging API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ที่ tab &lt;strong&gt;Basic settings&lt;/strong&gt; → คัดลอก &lt;strong&gt;Channel secret&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ที่ tab &lt;strong&gt;Messaging API&lt;/strong&gt; → คลิก &lt;strong&gt;Issue&lt;/strong&gt; เพื่อสร้าง &lt;strong&gt;Channel access token&lt;/strong&gt; (long-lived)&lt;/li&gt;
&lt;li&gt;เปิด &lt;strong&gt;Use webhook&lt;/strong&gt; → toggle เป็น Enable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;เก็บค่าสองอย่างนี้ไว้:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;LINE_CHANNEL_SECRET&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;
&lt;span class="py"&gt;LINE_CHANNEL_TOKEN&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;eyJhbGci...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. ตั้งค่าไฟล์ config
&lt;/h2&gt;

&lt;p&gt;Garudust แยก secret ออกจาก config เป็น 2 ไฟล์:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.garudust/.env&lt;/code&gt; — credentials เท่านั้น (ห้าม commit)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.garudust/config.yaml&lt;/code&gt; — ตั้งค่าพฤติกรรม, platform, port (แชร์ได้)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;~/.garudust/.env&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# LLM provider&lt;/span&gt;
&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ant-...

&lt;span class="c"&gt;# LINE adapter — tokens ต้องอยู่ใน .env เสมอ&lt;/span&gt;
&lt;span class="nv"&gt;LINE_CHANNEL_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;span class="nv"&gt;LINE_CHANNEL_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eyJhbGci...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;~/.garudust/config.yaml&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;anthropic&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;

&lt;span class="na"&gt;system_prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;คุณคือผู้ช่วย AI ชื่อ "น้องการุด" พูดภาษาไทย ตอบสั้นกระชับ&lt;/span&gt;
  &lt;span class="s"&gt;ช่วยงานด้านข้อมูล วิเคราะห์ข้อความ และตอบคำถามทั่วไป&lt;/span&gt;
  &lt;span class="s"&gt;ไม่ตอบเนื้อหาที่ไม่เหมาะสม&lt;/span&gt;

&lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3002&lt;/span&gt;
    &lt;span class="na"&gt;webhook_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/line&lt;/span&gt;      &lt;span class="c1"&gt;# webhook URL: https://your-host/line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;หลักการ:&lt;/strong&gt; &lt;code&gt;config.yaml&lt;/code&gt; เก็บโครงสร้าง (&lt;code&gt;enabled&lt;/code&gt;, &lt;code&gt;port&lt;/code&gt;, &lt;code&gt;webhook_path&lt;/code&gt;) ส่วน &lt;code&gt;.env&lt;/code&gt; เก็บ secret (&lt;code&gt;LINE_CHANNEL_SECRET&lt;/code&gt;, &lt;code&gt;LINE_CHANNEL_TOKEN&lt;/code&gt;) เท่านั้น&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;เมื่อรัน &lt;code&gt;garudust-server&lt;/code&gt; แล้ว Garudust จะเปิด HTTP server รอรับ webhook จาก LINE ที่ &lt;code&gt;0.0.0.0:3002/line&lt;/code&gt; โดยอัตโนมัติ — &lt;strong&gt;ไม่ต้องตั้งค่า webhook server เพิ่มเอง&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. รัน garudust-server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ดู log จะเห็น:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;INFO garudust_server: LINE webhook listening on 0.0.0.0:3002/line
INFO garudust_server: API server listening on 0.0.0.0:3000
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Port mapping ของ Garudust:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;ใช้สำหรับ&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HTTP API หลัก (&lt;code&gt;/chat&lt;/code&gt;, &lt;code&gt;/health&lt;/code&gt;, &lt;code&gt;/metrics&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generic webhook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3002&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;LINE adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3003&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;WhatsApp adapter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  5. ตั้งค่า Webhook URL ใน LINE Developers Console
&lt;/h2&gt;

&lt;p&gt;ขั้นตอนนี้แตกต่างกันตามสภาพแวดล้อม:&lt;/p&gt;

&lt;h3&gt;
  
  
  กรณี A — VPS หรือเซิร์ฟเวอร์ที่มี public IP (Production)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;ไม่ต้องใช้ ngrok&lt;/strong&gt; — LINE เข้าถึง server ของคุณได้ตรงๆ ผ่าน nginx&lt;/p&gt;

&lt;p&gt;ตั้งค่า nginx reverse proxy ก่อน (ดูขั้นตอนที่ 7) แล้วใช้ URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://yourdomain.com/line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  กรณี B — เครื่องตัวเองที่ไม่มี public IP (Dev/ทดสอบ)
&lt;/h3&gt;

&lt;p&gt;LINE ไม่สามารถเข้าถึง &lt;code&gt;localhost&lt;/code&gt; ได้และต้องการ HTTPS — ใช้ ngrok สร้าง tunnel ชั่วคราว:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http 3002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ngrok จะแสดง URL เช่น:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;Forwarding  https://abc123.ngrok-free.app -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://localhost:3002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;webhook URL ของคุณคือ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://abc123.ngrok-free.app/line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;หมายเหตุ:&lt;/strong&gt; ngrok free tier เปลี่ยน URL ทุกครั้งที่รีสตาร์ท เหมาะสำหรับทดสอบเท่านั้น ใช้ VPS หรือ ngrok paid plan สำหรับ production&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;ตั้ง webhook URL ใน LINE Developers Console:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tab &lt;strong&gt;Messaging API&lt;/strong&gt; → ส่วน &lt;strong&gt;Webhook settings&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;ใส่ URL ตามสภาพแวดล้อมของคุณ (จากด้านบน)&lt;/li&gt;
&lt;li&gt;คลิก &lt;strong&gt;Verify&lt;/strong&gt; — ควรได้ "Success"&lt;/li&gt;
&lt;li&gt;เปิด &lt;strong&gt;Use webhook&lt;/strong&gt; ให้เป็น Enable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ลองส่งข้อความหา LINE Official Account ของคุณ — AI จะตอบกลับทันที&lt;/p&gt;




&lt;h2&gt;
  
  
  6. เพิ่ม Cron Job (ทำงานอัตโนมัติ)
&lt;/h2&gt;

&lt;p&gt;Garudust มีระบบ cron ในตัว ตั้งค่าใน &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ส่ง briefing ทุกเช้า 8 โมง&lt;/span&gt;
&lt;span class="nv"&gt;GARUDUST_CRON_JOBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 8 * * *=สรุปข่าวเทคโนโลยีไทยวันนี้ บันทึกลงไฟล์ ~/briefing.md"&lt;/span&gt;

&lt;span class="c"&gt;# รวบรวม memory อัตโนมัติทุกคืน 03:00&lt;/span&gt;
&lt;span class="nv"&gt;GARUDUST_MEMORY_CRON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 3 * * *"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Deploy Production (systemd + nginx)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  nginx reverse proxy
&lt;/h3&gt;

&lt;p&gt;LINE ต้องการ HTTPS — nginx จัดการ SSL แล้ว proxy ต่อไปยัง Garudust บน port 3002:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# /etc/nginx/sites-available/garudust&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;     &lt;span class="n"&gt;/etc/letsencrypt/live/yourdomain.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/yourdomain.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# LINE webhook — proxy ไปที่ Garudust LINE adapter port 3002&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/line&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3002&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# HTTP API หลัก&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/garudust /etc/nginx/sites-enabled/
&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  systemd service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# /etc/systemd/system/garudust.service
&lt;/span&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;
&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Garudust AI Agent Server&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;

&lt;span class="nn"&gt;[Service]&lt;/span&gt;
&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;
&lt;span class="py"&gt;User&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ubuntu&lt;/span&gt;
&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/local/bin/garudust-server&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-failure&lt;/span&gt;
&lt;span class="py"&gt;RestartSec&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;
&lt;span class="py"&gt;EnvironmentFile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/ubuntu/.garudust/.env&lt;/span&gt;
&lt;span class="py"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/home/ubuntu&lt;/span&gt;

&lt;span class="nn"&gt;[Install]&lt;/span&gt;
&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; garudust
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status garudust
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;webhook URL สำหรับตั้งใน LINE Console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://yourdomain.com/line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  สรุป config ทั้งหมด
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;~/.garudust/.env&lt;/code&gt;&lt;/strong&gt; — secrets เท่านั้น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ant-...
&lt;span class="nv"&gt;LINE_CHANNEL_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;span class="nv"&gt;LINE_CHANNEL_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;eyJhbGci...
&lt;span class="nv"&gt;GARUDUST_MEMORY_CRON&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 3 * * *"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;~/.garudust/config.yaml&lt;/code&gt;&lt;/strong&gt; — พฤติกรรมและโครงสร้าง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;anthropic&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sonnet-4-6&lt;/span&gt;

&lt;span class="na"&gt;system_prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;คุณคือผู้ช่วย AI ชื่อ "น้องการุด" พูดภาษาไทย ตอบสั้นกระชับ&lt;/span&gt;

&lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;line&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3002&lt;/span&gt;
    &lt;span class="na"&gt;webhook_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/line&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  สรุปขั้นตอนตามสภาพแวดล้อม
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Dev (localhost)&lt;/th&gt;
&lt;th&gt;Production (VPS)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Garudust รัน webhook ที่&lt;/td&gt;
&lt;td&gt;&lt;code&gt;localhost:3002/line&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;localhost:3002/line&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;เปิด HTTPS ด้วย&lt;/td&gt;
&lt;td&gt;ngrok tunnel&lt;/td&gt;
&lt;td&gt;nginx + Let's Encrypt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook URL ใน LINE Console&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://xxx.ngrok-free.app/line&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;https://yourdomain.com/line&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ngrok&lt;/td&gt;
&lt;td&gt;✅ จำเป็น&lt;/td&gt;
&lt;td&gt;❌ ไม่ต้อง&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Garudust รองรับ OpenAI, Anthropic, Ollama, vLLM และ OpenAI-compatible endpoint ทุกเจ้า — เปลี่ยน provider ได้แค่แก้ 2 บรรทัดใน &lt;code&gt;config.yaml&lt;/code&gt; แล้วรีสตาร์ท&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-agent" rel="noopener noreferrer"&gt;garudust-org/garudust-agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://garudust-org.github.io/garudust-agent" rel="noopener noreferrer"&gt;garudust-org.github.io/garudust-agent&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ถ้ามีคำถามหรือเจอปัญหา เปิด Issue บน GitHub ได้เลย หรือ comment ไว้ด้านล่างครับ&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ai</category>
      <category>line</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>ใช้งาน Garudust Agent ร่วมกับ Typhoon Thai LLM: คู่มือฉบับสมบูรณ์</title>
      <dc:creator>Nisit Sirimarnkit</dc:creator>
      <pubDate>Wed, 13 May 2026 14:07:29 +0000</pubDate>
      <link>https://forem.com/nisit15/aichngaan-garudust-agent-rwmkab-typhoon-thai-llm-khuumuuechbabsmbuurn-3b6c</link>
      <guid>https://forem.com/nisit15/aichngaan-garudust-agent-rwmkab-typhoon-thai-llm-khuumuuechbabsmbuurn-3b6c</guid>
      <description>&lt;p&gt;Garudust เป็น AI agent ที่เขียนด้วย Rust — binary ขนาด ~10 MB, cold start ไม่ถึง 20 มิลลิวินาที และมี persistent memory ที่จำทุกอย่างข้ามหลาย session&lt;/p&gt;

&lt;p&gt;แต่ถ้างานที่ทำเป็นภาษาไทยล้วนๆ — เขียนอีเมลธุรกิจ, ตอบลูกค้า LINE OA, สรุปเอกสารราชการ — การใช้ &lt;strong&gt;Typhoon&lt;/strong&gt; โมเดลภาษาไทยจาก SCB 10X จะได้ผลลัพธ์ที่ดีกว่าอย่างชัดเจน&lt;/p&gt;

&lt;p&gt;Typhoon มี &lt;strong&gt;free API ที่ compatible กับ OpenAI&lt;/strong&gt; ที่ &lt;code&gt;https://api.opentyphoon.ai/v1&lt;/code&gt; ซึ่งหมายความว่า Garudust เชื่อมต่อได้ทันทีด้วยการตั้งค่า 2 บรรทัด ไม่ต้องแก้โค้ดแม้แต่บรรทัดเดียว&lt;/p&gt;




&lt;h2&gt;
  
  
  สิ่งที่ต้องเตรียม
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Linux, macOS หรือ Windows (WSL2)&lt;/li&gt;
&lt;li&gt;Rust 1.75+ — หรือดาวน์โหลด pre-built binary เลยก็ได้&lt;/li&gt;
&lt;li&gt;API key จาก &lt;a href="https://opentyphoon.ai" rel="noopener noreferrer"&gt;opentyphoon.ai&lt;/a&gt; (ฟรี)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ขั้นตอนที่ 1 — ขอ Typhoon API Key
&lt;/h2&gt;

&lt;p&gt;ไปที่ &lt;a href="https://opentyphoon.ai" rel="noopener noreferrer"&gt;opentyphoon.ai&lt;/a&gt; สมัครบัญชีฟรี แล้ว generate API key จาก dashboard&lt;/p&gt;

&lt;p&gt;API key จะมีหน้าตาประมาณนี้:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sk-ty-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Free tier ใช้งานได้กับทั้ง 2 โมเดล:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;โมเดล&lt;/th&gt;
&lt;th&gt;Req/วินาที&lt;/th&gt;
&lt;th&gt;Req/นาที&lt;/th&gt;
&lt;th&gt;เหมาะกับ&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;typhoon-v2.1-12b-instruct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;งานทั่วไป, ตอบเร็ว&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;typhoon-v2.5-30b-a3b-instruct&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;งานซับซ้อน, reasoning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;สำหรับงาน agent ส่วนใหญ่ แนะนำ &lt;code&gt;typhoon-v2.1-12b-instruct&lt;/code&gt; ก่อน — เร็วกว่าและเหมาะกับ multi-turn loop มากกว่า&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;หมายเหตุ:&lt;/strong&gt; Free API มี rate limit และไม่เหมาะกับ production workload หนักๆ สำหรับการใช้งานจริงในระดับ enterprise รอ production API บน AWS ที่ Typhoon วางแผนจะเปิดในปี 2026&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ขั้นตอนที่ 2 — ติดตั้ง Garudust
&lt;/h2&gt;

&lt;h3&gt;
  
  
  วิธีที่ 1: ดาวน์โหลด binary สำเร็จรูป (แนะนำ)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Linux x86_64&lt;/span&gt;
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; https://github.com/garudust-org/garudust-agent/releases/latest/download/garudust-x86_64-unknown-linux-musl.tar.gz
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; garudust-x86_64-unknown-linux-musl.tar.gz
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;garudust garudust-server /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;แพลตฟอร์ม&lt;/th&gt;
&lt;th&gt;ไฟล์&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linux x86_64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;garudust-*-x86_64-unknown-linux-musl.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux ARM64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;garudust-*-aarch64-unknown-linux-musl.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Apple Silicon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;garudust-*-aarch64-apple-darwin.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS Intel&lt;/td&gt;
&lt;td&gt;&lt;code&gt;garudust-*-x86_64-apple-darwin.tar.gz&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;&lt;code&gt;garudust-*-x86_64-pc-windows-msvc.zip&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  วิธีที่ 2: ติดตั้งจาก crates.io
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;garudust garudust-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ตรวจสอบว่าติดตั้งสำเร็จ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# garudust 0.2.8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ขั้นตอนที่ 3 — เชื่อมต่อ Garudust กับ Typhoon
&lt;/h2&gt;

&lt;p&gt;Garudust แยก config ออกจาก secret เป็น 2 ไฟล์ใน &lt;code&gt;~/.garudust/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config.yaml&lt;/code&gt; — ชื่อโมเดล, provider, ค่าพฤติกรรมต่างๆ (แชร์ได้)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt; — API key อย่างเดียว (ห้าม commit เด็ดขาด)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;สร้างไฟล์ &lt;code&gt;~/.garudust/config.yaml&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# เชื่อมต่อ Typhoon ผ่าน OpenAI-compatible endpoint&lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typhoon-v2.1-12b-instruct&lt;/span&gt;
&lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://api.opentyphoon.ai/v1&lt;/span&gt;

&lt;span class="c1"&gt;# Context window สำหรับโมเดล 12B&lt;/span&gt;
&lt;span class="na"&gt;context_window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8192&lt;/span&gt;
&lt;span class="na"&gt;compression&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;threshold_fraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.65&lt;/span&gt;

&lt;span class="c1"&gt;# Memory nudge — บันทึก fact ทุก 5 iteration&lt;/span&gt;
&lt;span class="na"&gt;nudge_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;สร้างไฟล์ &lt;code&gt;~/.garudust/.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Typhoon API key&lt;/span&gt;
&lt;span class="nv"&gt;VLLM_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ty-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ทำไมใช้ &lt;code&gt;VLLM_API_KEY&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Garudust ส่ง key นี้เป็น &lt;code&gt;Authorization: Bearer&lt;/code&gt; header ไปยัง base_url ที่กำหนด Typhoon API รับ format นี้ได้ตรงๆ เลย&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;หรือจะใช้ setup wizard ก็ได้:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เลือก provider เป็น &lt;strong&gt;vllm&lt;/strong&gt; แล้วกรอก &lt;code&gt;base_url&lt;/code&gt; และ &lt;code&gt;model&lt;/code&gt; ตามด้านบน&lt;/p&gt;




&lt;h2&gt;
  
  
  ขั้นตอนที่ 4 — ตรวจสอบการเชื่อมต่อ
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้าทุกอย่างถูกต้องจะเห็น:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;✓ Config loaded     provider=vllm  model=typhoon-v2.1-12b-instruct
✓ API key present   VLLM_API_KEY
✓ LLM reachable     https://api.opentyphoon.ai/v1 → 200 OK
✓ Memory dir        ~/.garudust/memory/ (0 entries)
✓ Session DB        ~/.garudust/sessions.db
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ขั้นตอนที่ 5 — ทดสอบสนทนาภาษาไทย
&lt;/h2&gt;

&lt;p&gt;เปิด TUI แบบ interactive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ลองพิมพ์:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;คุณ: สวัสดีครับ ช่วยแนะนำตัวเองหน่อยได้ไหม
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent จะตรวจจับภาษาไทยโดยอัตโนมัติและตอบกลับเป็นภาษาไทย โดยไม่ต้องตั้งค่าภาษาเพิ่มเติม&lt;/p&gt;

&lt;p&gt;หรือใช้แบบ one-shot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"สรุปข้อดีข้อเสียของการเปิดบริษัทในไทยแบบสั้นๆ"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ขั้นตอนที่ 6 — ตั้งให้ตอบไทยเป็นค่าเริ่มต้นถาวร
&lt;/h2&gt;

&lt;p&gt;บอก agent ครั้งเดียว มันจำตลอด:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;คุณ: ตั้งแต่นี้ไปตอบเป็นภาษาไทยเสมอ ยกเว้นถ้าฉันถามเป็นภาษาอื่น
Agent: [บันทึกลง memory] เข้าใจแล้วครับ จะตอบเป็นภาษาไทยใน session หน้าทุกครั้ง
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Garudust บันทึกลง &lt;code&gt;~/.garudust/memory/&lt;/code&gt; และโหลดขึ้นมาทุก session โดยอัตโนมัติ ไม่ต้องบอกซ้ำอีก&lt;/p&gt;




&lt;h2&gt;
  
  
  ตัวอย่างการใช้งานจริง
&lt;/h2&gt;

&lt;h3&gt;
  
  
  เขียนอีเมลธุรกิจภาษาไทย
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"เขียนอีเมลทางการถึงพาร์ทเนอร์ แจ้งว่าต้องการต่อสัญญา partnership อีก 1 ปี พร้อมเสนอเพิ่มงบ 15% และขอนัดประชุมสัปดาห์หน้า"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  สรุปเอกสาร PDF ภาษาไทย
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"อ่านไฟล์นี้แล้วสรุปประเด็นสำคัญเป็นภาษาไทย 5 ข้อ: /path/to/contract.pdf"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent จะเรียก &lt;code&gt;pdf_read&lt;/code&gt; tool โดยอัตโนมัติ แล้วสรุปเนื้อหาให้&lt;/p&gt;

&lt;h3&gt;
  
  
  เขียน template ตอบ LINE OA
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"เขียน template ตอบลูกค้าใน LINE OA สำหรับคำถามเรื่อง shipping 5 แบบ ให้เป็นภาษาไทยที่สุภาพและเป็นมิตร พร้อมระบุวันจัดส่งโดยประมาณ"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  สร้าง skill ภาษาไทยให้ใช้ซ้ำได้
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;คุณ: สร้าง skill สำหรับเขียนรายงานสรุปประจำสัปดาห์เป็นภาษาไทย พร้อม format หัวข้อ ผลงานที่ทำ ปัญหาที่พบ และแผนสัปดาห์หน้า
Agent: [เรียก write_skill]
       บันทึก skill 'weekly-report-th' ไปยัง ~/.garudust/skills/weekly-report-th/SKILL.md แล้ว
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ครั้งต่อไปแค่พิมพ์:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"ใช้ skill weekly-report-th สรุปสัปดาห์นี้"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ส่ง briefing ภาษาไทยทุกเช้า (Cron)
&lt;/h3&gt;

&lt;p&gt;เพิ่มใน &lt;code&gt;~/.garudust/.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GARUDUST_CRON_JOBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 8 * * *=ค้นหาข่าวเศรษฐกิจและเทคโนโลยีไทยล่าสุด สรุปเป็นรายการ 5 ข้อ บันทึกลงไฟล์ ~/briefing-th.md"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เปิด server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ทุกวันตี 8 โมงเช้า agent จะค้นหาข่าว สรุปเป็นภาษาไทย และบันทึกไฟล์ให้โดยอัตโนมัติ&lt;/p&gt;




&lt;h2&gt;
  
  
  เปลี่ยนเป็นโมเดลใหญ่เมื่อต้องการ
&lt;/h2&gt;

&lt;p&gt;สำหรับงานที่ซับซ้อนกว่า เช่น วิเคราะห์สัญญา หรือ multi-step planning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# เปลี่ยนชั่วคราวใน TUI&lt;/span&gt;
/model typhoon-v2.5-30b-a3b-instruct

&lt;span class="c"&gt;# หรือเปลี่ยนถาวร&lt;/span&gt;
garudust config &lt;span class="nb"&gt;set &lt;/span&gt;model typhoon-v2.5-30b-a3b-instruct
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;อย่าลืมอัปเดต &lt;code&gt;context_window&lt;/code&gt; ใน &lt;code&gt;config.yaml&lt;/code&gt; ด้วย:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typhoon-v2.5-30b-a3b-instruct&lt;/span&gt;
&lt;span class="na"&gt;context_window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;32768&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  แก้ปัญหาเบื้องต้น
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;อาการ&lt;/th&gt;
&lt;th&gt;สาเหตุ&lt;/th&gt;
&lt;th&gt;วิธีแก้&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HTTP 401 Unauthorized&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;API key ผิด&lt;/td&gt;
&lt;td&gt;ตรวจสอบ &lt;code&gt;VLLM_API_KEY&lt;/code&gt; ใน &lt;code&gt;~/.garudust/.env&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HTTP 429 Too Many Requests&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;เกิน rate limit&lt;/td&gt;
&lt;td&gt;รอ ~1 นาที — Garudust retry อัตโนมัติ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent ตอบภาษาอังกฤษตลอด&lt;/td&gt;
&lt;td&gt;ยังไม่ได้ตั้ง memory&lt;/td&gt;
&lt;td&gt;บอกครั้งเดียว: "ตอบเป็นภาษาไทยเสมอ"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent ไม่เรียก tool&lt;/td&gt;
&lt;td&gt;โมเดลข้าม tool call&lt;/td&gt;
&lt;td&gt;ระบุชัดขึ้น: "ใช้ web_search หา..." หรือเปลี่ยนเป็น 30B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context เกิน&lt;/td&gt;
&lt;td&gt;prompt ยาวเกินไป&lt;/td&gt;
&lt;td&gt;ลด &lt;code&gt;context_window&lt;/code&gt; หรือเปิด compression&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Config สรุปฉบับสมบูรณ์
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/.garudust/config.yaml&lt;/span&gt;

&lt;span class="c1"&gt;# --- LLM ---&lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm&lt;/span&gt;
&lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://api.opentyphoon.ai/v1&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;typhoon-v2.1-12b-instruct&lt;/span&gt;    &lt;span class="c1"&gt;# หรือ typhoon-v2.5-30b-a3b-instruct&lt;/span&gt;

&lt;span class="c1"&gt;# --- Context ---&lt;/span&gt;
&lt;span class="na"&gt;context_window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8192&lt;/span&gt;                &lt;span class="c1"&gt;# 8192 สำหรับ 12B, 32768 สำหรับ 30B&lt;/span&gt;
&lt;span class="na"&gt;compression&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;threshold_fraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.65&lt;/span&gt;

&lt;span class="c1"&gt;# --- Memory ---&lt;/span&gt;
&lt;span class="na"&gt;nudge_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;                   &lt;span class="c1"&gt;# บันทึก fact ทุก 5 iteration (0 = ปิด)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ~/.garudust/.env&lt;/span&gt;
&lt;span class="nv"&gt;VLLM_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ty-xxxxxxxxxxxxxxxxxxxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ลิงก์ที่เกี่ยวข้อง
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Garudust:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-agent" rel="noopener noreferrer"&gt;github.com/garudust-org/garudust-agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typhoon API:&lt;/strong&gt; &lt;a href="https://opentyphoon.ai" rel="noopener noreferrer"&gt;opentyphoon.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typhoon Docs:&lt;/strong&gt; &lt;a href="https://docs.opentyphoon.ai" rel="noopener noreferrer"&gt;docs.opentyphoon.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typhoon Rate Limits:&lt;/strong&gt; &lt;a href="https://docs.opentyphoon.ai/en/rate-limits/" rel="noopener noreferrer"&gt;docs.opentyphoon.ai/en/rate-limits&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garudust Latest Release:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-agent/releases/latest" rel="noopener noreferrer"&gt;v0.2.8&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Garudust + Typhoon = AI agent ที่รันบน hardware ของคุณเอง พูดภาษาไทยได้ดี และไม่ส่งข้อมูลออกนอกบ้านถ้าคุณ self-host Typhoon เอง&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ai</category>
      <category>thaillm</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>Garudust: A Self-Improving AI Agent Runtime Built in Rust</title>
      <dc:creator>Nisit Sirimarnkit</dc:creator>
      <pubDate>Wed, 13 May 2026 08:31:13 +0000</pubDate>
      <link>https://forem.com/nisit15/garudust-a-self-improving-ai-agent-runtime-built-in-rust-1j09</link>
      <guid>https://forem.com/nisit15/garudust-a-self-improving-ai-agent-runtime-built-in-rust-1j09</guid>
      <description>&lt;p&gt;WELCOME Garudian!!!&lt;/p&gt;

&lt;p&gt;Most AI agent frameworks share the same two problems: they're heavy to deploy, and they forget everything the moment a session ends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Garudust&lt;/strong&gt; takes a different approach. It's a self-hostable AI agent runtime written entirely in Rust — a single ~10 MB binary that starts in under 20 milliseconds, remembers what you teach it across sessions, and gets smarter with every conversation.&lt;/p&gt;

&lt;p&gt;No Python runtime. No Docker required for local use. No cloud dependency.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Current release: v0.2.8&lt;/strong&gt; — released 12 May 2025. The project moved from v0.1.0 to v0.2.8 in under two weeks, so it's moving fast.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What Makes Garudust Different?
&lt;/h2&gt;

&lt;p&gt;There's no shortage of AI agent frameworks. Here's why Garudust stands out:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Garudust&lt;/th&gt;
&lt;th&gt;Python-based agents&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Binary size&lt;/td&gt;
&lt;td&gt;~10 MB&lt;/td&gt;
&lt;td&gt;100–500 MB (with deps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold start&lt;/td&gt;
&lt;td&gt;&amp;lt; 20 ms&lt;/td&gt;
&lt;td&gt;2–10+ seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;Persistent across sessions&lt;/td&gt;
&lt;td&gt;Usually in-memory only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-improvement&lt;/td&gt;
&lt;td&gt;Built-in skill learning loop&lt;/td&gt;
&lt;td&gt;Manual, if at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-platform&lt;/td&gt;
&lt;td&gt;Telegram, Discord, Slack, LINE, WhatsApp, Matrix, HTTP&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM backends&lt;/td&gt;
&lt;td&gt;Any OpenAI-compatible + Bedrock&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The self-improvement loop is what makes it genuinely different. When Garudust discovers a repeatable multi-step workflow during a session, it writes a skill file automatically. Next time you ask for the same thing, it already knows how to do it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;Garudust is a multi-crate Rust workspace. Every concern is its own crate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crates/
  garudust-core        Shared traits &amp;amp; types — zero I/O
  garudust-transport   LLM adapters (Anthropic, OpenRouter, Bedrock, Ollama, vLLM, …)
  garudust-tools       Tool registry + built-in toolsets
  garudust-memory      FileMemoryStore (markdown) + SessionDb (SQLite + FTS5)
  garudust-agent       Agent run loop, context compressor, prompt builder
  garudust-platforms   Telegram, Discord, Slack, LINE, WhatsApp, Matrix, Webhook
  garudust-cron        Cron scheduler
  garudust-gateway     axum HTTP gateway — /chat, /chat/stream, /chat/ws, /metrics

bin/
  garudust             CLI: interactive TUI, one-shot, setup, doctor, config
  garudust-server      Headless: all platforms + HTTP + cron in one process
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This composable design means you can add a new tool, platform adapter, or LLM transport without touching anything outside the relevant crate. Most contributions are under 100 lines.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started in 3 Minutes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;

&lt;p&gt;Download a pre-built binary from &lt;a href="https://github.com/garudust-org/garudust-agent/releases/latest" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt; — no Rust required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; garudust-&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;-x86_64-unknown-linux-musl&lt;/span&gt;.tar.gz
&lt;span class="nb"&gt;sudo mv &lt;/span&gt;garudust garudust-server /usr/local/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or install directly from crates.io:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;garudust garudust-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or build from source (requires Rust 1.75+):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/garudust-org/garudust-agent
&lt;span class="nb"&gt;cd &lt;/span&gt;garudust-agent
cargo build &lt;span class="nt"&gt;--release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure
&lt;/h3&gt;

&lt;p&gt;Run the setup wizard — it walks you through provider selection and saves your API key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Garudust supports: &lt;strong&gt;Anthropic, OpenRouter, AWS Bedrock, Ollama, vLLM&lt;/strong&gt;, or any OpenAI-compatible endpoint. Swap providers with a single env var — no code changes needed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The wizard pre-fills existing values and masks secrets. Press Enter to keep a value unchanged — a small detail that makes re-configuration much less painful.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Chat
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust   &lt;span class="c"&gt;# interactive TUI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or run a one-shot task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"summarise the git log from the last 7 days into a changelog"&lt;/span&gt;
garudust &lt;span class="nt"&gt;--model&lt;/span&gt; anthropic/claude-opus-4-7 &lt;span class="s2"&gt;"review this PR for security issues"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Persistent Memory
&lt;/h2&gt;

&lt;p&gt;This is the feature that changes how you work with the agent day to day.&lt;/p&gt;

&lt;p&gt;Garudust automatically saves facts to &lt;code&gt;~/.garudust/memory/&lt;/code&gt; — preferences, project conventions, corrections you make:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: always format JSON with 2-space indent
Agent: Got it — I'll use 2-space indent for JSON from now on.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next session starts with that preference already loaded. You never repeat yourself.&lt;/p&gt;

&lt;p&gt;A built-in nudge fires every few iterations during long tasks, prompting the agent to persist new facts before the session ends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/.garudust/config.yaml&lt;/span&gt;
&lt;span class="na"&gt;nudge_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;   &lt;span class="c1"&gt;# inject memory reminder every 5 LLM iterations (0 = off)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Memory is also protected from prompt injection — recalled facts are wrapped in &lt;code&gt;&amp;lt;untrusted_memory&amp;gt;&lt;/code&gt; tags so the model treats them as data, not instructions.&lt;/p&gt;

&lt;p&gt;What gets saved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Preferences&lt;/strong&gt; — output format, language, tone, tool choices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project details&lt;/strong&gt; — paths, configs, conventions, known quirks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corrections&lt;/strong&gt; — anything you tell the agent to stop doing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What does &lt;em&gt;not&lt;/em&gt; get saved: session logs, task progress, one-off details. Only facts that will matter in future sessions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Skill System
&lt;/h2&gt;

&lt;p&gt;Skills are reusable instruction sets stored as plain Markdown files in &lt;code&gt;~/.garudust/skills/&lt;/code&gt;. They're hot-reloaded on every call — edit a file and the next message picks up the change immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.garudust/skills/
  git-workflow/SKILL.md
  daily-standup/SKILL.md
  rust-code-review/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Skills are created automatically
&lt;/h3&gt;

&lt;p&gt;When Garudust discovers a multi-step workflow, it writes the skill itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: write a skill for reviewing Rust PRs
Agent: [calls write_skill]
       Saved to ~/.garudust/skills/rust-code-review/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Skills stay up to date
&lt;/h3&gt;

&lt;p&gt;The skill reflection pipeline (v0.2.0) automatically updates skills after complex tasks. If steps are outdated or wrong, the agent patches the file — no manual maintenance required.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skill-level tool permissions (v0.2.1)
&lt;/h3&gt;

&lt;p&gt;Each skill declares exactly which tools it's allowed to use via frontmatter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git-workflow&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Opinionated Git commit and PR workflow&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;terminal&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;read_file&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;write_file&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Always write conventional commits. Run tests before pushing.
Open a draft PR first, then mark ready when CI is green.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This limits the blast radius of any skill — it can't call tools it hasn't declared.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install skills from the hub (v0.2.5)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust skill &lt;span class="nb"&gt;install &lt;/span&gt;facebook-workflow
garudust skill list
garudust skill uninstall facebook-workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skills pull from &lt;a href="https://github.com/garudust-org/garudust-hub" rel="noopener noreferrer"&gt;garudust-hub&lt;/a&gt; and install their required tools automatically. If the tool needs a runtime (&lt;code&gt;python3&lt;/code&gt;, &lt;code&gt;node&lt;/code&gt;, etc.) that isn't on PATH, you get a warning immediately at install time — not a silent failure at run time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multi-Platform Gateway
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;garudust-server&lt;/code&gt; runs HTTP, all platform adapters, and cron jobs in a single process. Set the relevant env vars and start the server — every adapter runs together.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Required env var(s)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Telegram&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TELEGRAM_TOKEN&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discord&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DISCORD_TOKEN&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slack&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SLACK_BOT_TOKEN&lt;/code&gt; + &lt;code&gt;SLACK_APP_TOKEN&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LINE&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;LINE_CHANNEL_SECRET&lt;/code&gt; + &lt;code&gt;LINE_CHANNEL_ACCESS_TOKEN&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WhatsApp&lt;/td&gt;
&lt;td&gt;Meta Cloud API credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Matrix&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;MATRIX_HOMESERVER&lt;/code&gt; + &lt;code&gt;MATRIX_USER&lt;/code&gt; + &lt;code&gt;MATRIX_PASSWORD&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Always-on at &lt;code&gt;POST /chat&lt;/code&gt; — no token needed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TELEGRAM_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;123:ABC &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;LINE_CHANNEL_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;abc... &lt;span class="se"&gt;\&lt;/span&gt;
garudust-server &lt;span class="nt"&gt;--anthropic-key&lt;/span&gt; sk-ant-...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One binary, every channel.&lt;/p&gt;




&lt;h2&gt;
  
  
  HTTP API
&lt;/h2&gt;

&lt;p&gt;Three transport modes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Blocking&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3000/chat &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message": "write a haiku about Rust"}'&lt;/span&gt;

&lt;span class="c"&gt;# Streaming (Server-Sent Events)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3000/chat/stream &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message": "explain async/await in 3 sentences"}'&lt;/span&gt;

&lt;span class="c"&gt;# WebSocket: ws://localhost:3000/chat/ws&lt;/span&gt;
&lt;span class="c"&gt;# Send: {"message": "..."} → Receive: text chunks ... {"done": true}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prometheus-compatible metrics at &lt;code&gt;/metrics&lt;/code&gt;. Health check at &lt;code&gt;/health&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cron Scheduling
&lt;/h2&gt;

&lt;p&gt;Run agent tasks on a schedule with a single env var:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;GARUDUST_CRON_JOBS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0 9 * * *=Write a morning briefing and save to ~/briefing.md"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
garudust-server &lt;span class="nt"&gt;--anthropic-key&lt;/span&gt; sk-ant-...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined with the skill system and a platform adapter, this becomes a powerful automation layer — daily social media posts, standup summaries, report generation, or any workflow you can describe in plain text.&lt;/p&gt;




&lt;h2&gt;
  
  
  Built-in Tools
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Since&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;web_fetch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fetch any URL (capped at 512 KB)&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;web_search&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Brave Search API; falls back to DuckDuckGo&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;browser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Control Chrome via CDP — navigate, click, screenshot, JS&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;read_file&lt;/code&gt; / &lt;code&gt;write_file&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Filesystem access&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terminal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run shell commands (sandboxed via Docker, opt-in)&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Persistent key-value store&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;session_search&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full-text search across past conversations (SQLite FTS5)&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;delegate_task&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spawn parallel sub-agents; results returned in order&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;list_directory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Browse filesystem&lt;/td&gt;
&lt;td&gt;v0.2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http_request&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Make REST API calls directly without curl&lt;/td&gt;
&lt;td&gt;v0.2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdf_read&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Extract text from PDF files&lt;/td&gt;
&lt;td&gt;v0.2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;write_skill&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create or update skills on the fly&lt;/td&gt;
&lt;td&gt;v0.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  MCP Support
&lt;/h3&gt;

&lt;p&gt;Connect any &lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; server in &lt;code&gt;~/.garudust/config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;mcp_servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;filesystem&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-y"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@modelcontextprotocol/server-filesystem"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/tmp"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-y"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@modelcontextprotocol/server-postgres"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgresql://localhost/mydb"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;A few things worth highlighting for anyone self-hosting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terminal sandbox&lt;/strong&gt; — shell commands run inside a hardened Docker container (&lt;code&gt;--cap-drop ALL&lt;/code&gt;, &lt;code&gt;--security-opt no-new-privileges:true&lt;/code&gt;, tmpfs &lt;code&gt;/tmp&lt;/code&gt;). Opt-in via &lt;code&gt;terminal_sandbox: docker&lt;/code&gt; in config.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConstitutionalApprover&lt;/strong&gt; — LLM-based approval gate for commands, not regex that can be bypassed via shell obfuscation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS TOCTOU fix&lt;/strong&gt; — a custom &lt;code&gt;SafeResolver&lt;/code&gt; closes the gap where a hostname could resolve to a private IP between the check and the actual request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt injection protection&lt;/strong&gt; — recalled memory is wrapped in &lt;code&gt;&amp;lt;untrusted_memory&amp;gt;&lt;/code&gt; tags so the model treats it as data, not instructions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured audit log&lt;/strong&gt; — every tool call is logged at INFO level with session ID, tool name, and arguments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM retry with exponential backoff&lt;/strong&gt; — transient 429/5xx errors are retried automatically.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Usage Footer
&lt;/h2&gt;

&lt;p&gt;Every completed task appends a summary (added in v0.2.2):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[5 iter | 24657in 689out tok | ~$0.003 @ Qwen3-14B-AWQ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Iterations, token counts, estimated cost, and model — useful for understanding what tasks actually cost at scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  Self-Hosted LLM Support
&lt;/h2&gt;

&lt;p&gt;If you run your own LLM (vLLM, Ollama), Garudust connects with zero friction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ollama&lt;/span&gt;
&lt;span class="nv"&gt;OLLAMA_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:11434
&lt;span class="nv"&gt;GARUDUST_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;llama3.2

&lt;span class="c"&gt;# vLLM&lt;/span&gt;
&lt;span class="nv"&gt;VLLM_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:8000/v1
&lt;span class="nv"&gt;VLLM_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;token-abc123
&lt;span class="nv"&gt;GARUDUST_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Qwen/Qwen3-14B-AWQ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No cloud required. Your data stays local.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"OPENROUTER_API_KEY=sk-or-..."&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .env
docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compose file is included in the repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;Good first issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New tool&lt;/strong&gt; — wrap any CLI or API as a &lt;code&gt;Tool&lt;/code&gt; impl in &lt;code&gt;garudust-tools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New platform&lt;/strong&gt; — implement &lt;code&gt;PlatformAdapter&lt;/code&gt; (Signal, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improve TUI&lt;/strong&gt; — multi-line input, syntax highlighting, mouse support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests&lt;/strong&gt; — integration, property, snapshot
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/garudust-org/garudust-agent
&lt;span class="nb"&gt;cd &lt;/span&gt;garudust-agent
cargo build
cargo &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--workspace&lt;/span&gt;
cargo clippy &lt;span class="nt"&gt;--workspace&lt;/span&gt; &lt;span class="nt"&gt;--all-targets&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-W&lt;/span&gt; clippy::all &lt;span class="nt"&gt;-W&lt;/span&gt; clippy::pedantic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-agent" rel="noopener noreferrer"&gt;github.com/garudust-org/garudust-agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill &amp;amp; Tool Hub:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-hub" rel="noopener noreferrer"&gt;github.com/garudust-org/garudust-hub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;crates.io:&lt;/strong&gt; &lt;a href="https://crates.io/crates/garudust" rel="noopener noreferrer"&gt;crates.io/crates/garudust&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docs.rs:&lt;/strong&gt; &lt;a href="https://docs.rs/garudust-agent" rel="noopener noreferrer"&gt;docs.rs/garudust-agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latest release:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-agent/releases/latest" rel="noopener noreferrer"&gt;v0.2.8&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built by developers who got tired of agent frameworks that weigh a gigabyte, forget everything, and require three cloud services to run "locally."&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ai</category>
      <category>agents</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>Build an AI-Powered Auto-Post Bot for Facebook with Garudust</title>
      <dc:creator>Nisit Sirimarnkit</dc:creator>
      <pubDate>Wed, 13 May 2026 08:07:57 +0000</pubDate>
      <link>https://forem.com/nisit15/build-an-ai-powered-auto-post-bot-for-facebook-with-garudust-430</link>
      <guid>https://forem.com/nisit15/build-an-ai-powered-auto-post-bot-for-facebook-with-garudust-430</guid>
      <description>&lt;p&gt;Social media managers spend hours crafting posts, finding images, and hitting "publish." What if a single terminal command could do all of that — research a topic, write an engaging post, generate a matching image, and publish it to your Facebook Page automatically?&lt;/p&gt;

&lt;p&gt;That's exactly what &lt;strong&gt;Garudust&lt;/strong&gt; does. It's an open-source AI agent written in Rust that connects to any OpenAI-compatible LLM (local or cloud) and runs multi-step workflows through a simple skill system.&lt;/p&gt;

&lt;p&gt;In this guide, you'll set up Garudust and run a fully automated Facebook post workflow from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;One command → one full Facebook post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"use skill facebook-workflow, post about AI news today, page_id=YOUR_PAGE_ID"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔍 &lt;strong&gt;Search the web&lt;/strong&gt; for recent news on your topic&lt;/li&gt;
&lt;li&gt;📄 &lt;strong&gt;Read and summarize&lt;/strong&gt; the best article it finds&lt;/li&gt;
&lt;li&gt;🎨 &lt;strong&gt;Generate a matching image&lt;/strong&gt; with overlay text&lt;/li&gt;
&lt;li&gt;✍️ &lt;strong&gt;Write a detailed post&lt;/strong&gt; with hashtags in your target language&lt;/li&gt;
&lt;li&gt;📢 &lt;strong&gt;Publish everything&lt;/strong&gt; to your Facebook Page — no manual steps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rust (stable)&lt;/strong&gt; — install via &lt;a href="https://rustup.rs" rel="noopener noreferrer"&gt;rustup.rs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Facebook Page&lt;/strong&gt; you manage&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Facebook Developer App&lt;/strong&gt; with &lt;code&gt;pages_manage_posts&lt;/code&gt; permission&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;LLM endpoint&lt;/strong&gt; — local (vLLM / Ollama) or cloud (OpenRouter / Anthropic)&lt;/li&gt;
&lt;li&gt;Optional: A &lt;strong&gt;Hugging Face token&lt;/strong&gt; for AI image generation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 — Install Garudust
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;garudust
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the interactive setup wizard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates two files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.garudust/config.yaml&lt;/code&gt; — non-secret settings&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.garudust/.env&lt;/code&gt; — API keys and tokens&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 2 — Configure Your LLM
&lt;/h2&gt;

&lt;p&gt;Garudust separates settings from secrets. Open &lt;code&gt;~/.garudust/config.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Non-secret settings — safe to share or commit&lt;/span&gt;
&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Qwen/Qwen3-14B-AWQ&lt;/span&gt;    &lt;span class="c1"&gt;# or gpt-4o, claude-3-5-sonnet, etc.&lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vllm&lt;/span&gt;                &lt;span class="c1"&gt;# vllm | ollama | anthropic | openrouter&lt;/span&gt;
&lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://localhost:8000/v1&lt;/span&gt;

&lt;span class="na"&gt;context_window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;32768&lt;/span&gt;
&lt;span class="na"&gt;compression&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;threshold_fraction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.65&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add your secrets to &lt;code&gt;~/.garudust/.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Secrets only — never put model or URL here&lt;/span&gt;
&lt;span class="nv"&gt;VLLM_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-vllm-key
&lt;span class="nv"&gt;HF_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;hf_xxxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Design principle:&lt;/strong&gt; &lt;code&gt;config.yaml&lt;/code&gt; holds everything that isn't a secret (model name, provider, URLs, behavior tuning). &lt;code&gt;.env&lt;/code&gt; holds only API keys. This makes it trivial to share your config without leaking credentials.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Using a cloud provider instead? Here's how each maps:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;config.yaml&lt;/th&gt;
&lt;th&gt;.env&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vLLM (local)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;provider: vllm&lt;/code&gt; + &lt;code&gt;base_url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;VLLM_API_KEY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ollama (local)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;provider: ollama&lt;/code&gt; + &lt;code&gt;base_url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(none needed)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;&lt;code&gt;provider: anthropic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenRouter&lt;/td&gt;
&lt;td&gt;&lt;code&gt;provider: openrouter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Step 3 — Get a Facebook Page Access Token
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://developers.facebook.com" rel="noopener noreferrer"&gt;developers.facebook.com&lt;/a&gt; → &lt;strong&gt;My Apps&lt;/strong&gt; → create a new app&lt;/li&gt;
&lt;li&gt;Add the &lt;strong&gt;Facebook Login&lt;/strong&gt; product&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Graph API Explorer&lt;/strong&gt;, select your app and your Page&lt;/li&gt;
&lt;li&gt;Generate a token with these permissions:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pages_manage_posts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pages_read_engagement&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Exchange it for a &lt;strong&gt;long-lived Page Access Token&lt;/strong&gt; (valid 60 days)&lt;/li&gt;
&lt;li&gt;Add it to your &lt;code&gt;.env&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;FACEBOOK_ACCESS_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;EAAxxxxxxxxxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Your Page ID is visible in Page Settings under &lt;strong&gt;About&lt;/strong&gt;, or in the Page URL.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4 — Install the Skill and Tools
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust skill &lt;span class="nb"&gt;install &lt;/span&gt;facebook-workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pulls the skill from garudust-hub and automatically installs the required tools: &lt;code&gt;facebook_post&lt;/code&gt; and &lt;code&gt;generate_image&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Verify everything is in place:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust skill list
&lt;span class="c"&gt;# ✓ facebook-workflow  v3.0.0&lt;/span&gt;

garudust tool list
&lt;span class="c"&gt;# ✓ facebook_post&lt;/span&gt;
&lt;span class="c"&gt;# ✓ generate_image&lt;/span&gt;
&lt;span class="c"&gt;# ✓ web_search&lt;/span&gt;
&lt;span class="c"&gt;# ✓ web_fetch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5 — Run Your First Auto-Post
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garudust &lt;span class="s2"&gt;"use skill facebook-workflow, research latest AI news, write a detailed post, generate an image, post to page_id=831735183365530"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch the agent work through each step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[web_search]     searching: AI news 2025...
[web_fetch]      fetching top result...
[generate_image] creating /tmp/fb_post_image.png...
[facebook_post]  publishing to page 831735183365530...

Posted — ID: 831735183365530_122126910027165465
[5 iter | 24657in 689out @ Qwen3-14B-AWQ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Your post is live. ✅&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;facebook-workflow&lt;/code&gt; skill is a plain Markdown file at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.garudust/skills/facebook-workflow/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It guides the agent through four steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1 — Research   →  web_search + web_fetch (1 search, 1 fetch)
Step 2 — Image      →  generate_image (1024×576, with overlay text)
Step 3 — Post       →  facebook_post (page_id + message + image_path)
Step 4 — Report     →  confirm post_id or surface the error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step explicitly tells the model which tool to call and when. This prevents weak models from staying in "text mode" and skipping tool calls entirely — a common failure mode in multi-step agent workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic Context Management
&lt;/h3&gt;

&lt;p&gt;For models with small context windows (e.g. 27K tokens), Garudust handles overflow automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compresses conversation history when it reaches &lt;strong&gt;65%&lt;/strong&gt; of the context limit&lt;/li&gt;
&lt;li&gt;Caps &lt;code&gt;max_tokens&lt;/code&gt; at &lt;code&gt;context_window / 8&lt;/code&gt; to always leave room for input&lt;/li&gt;
&lt;li&gt;Retries with a smaller output budget (&lt;code&gt;/16&lt;/code&gt; → &lt;code&gt;/32&lt;/code&gt;) if the first attempt still overflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't need to think about tokens — just set &lt;code&gt;context_window&lt;/code&gt; in &lt;code&gt;config.yaml&lt;/code&gt; and the agent handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6 — Customize the Post Format
&lt;/h2&gt;

&lt;p&gt;The post format is defined directly in the skill file. Edit it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano ~/.garudust/skills/facebook-workflow/SKILL.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find the post format section and adjust it to your style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gs"&gt;**Post format (minimum 200 words):**&lt;/span&gt;

[hook — 1–2 attention-grabbing sentences, use a question or surprising fact]

[background — why this matters, 2–3 sentences of context]

[main content — facts, figures, and deep details from research, 3–4 sentences]

[real example — a company, product, or case study, 2–3 sentences]

[impact &amp;amp; trends — what this means for the future, 2–3 sentences]

[call to action — ask for opinions or suggest next steps, 1–2 sentences]

&lt;span class="gh"&gt;#hashtag1 #hashtag2 #hashtag3 #hashtag4 #hashtag5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want posts in English instead of Thai? Change the language note. Want longer posts? Raise the minimum word count. The model will follow whatever format you define here.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7 — Automate with a Daily Cron Job
&lt;/h2&gt;

&lt;p&gt;Create a shell script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# /usr/local/bin/daily-ai-post.sh&lt;/span&gt;
&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
garudust &lt;span class="s2"&gt;"use skill facebook-workflow, latest AI technology news, write a detailed post, generate an image, post to page_id=YOUR_PAGE_ID"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.garudust/post.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable and add it to cron:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /usr/local/bin/daily-ai-post.sh
crontab &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# Post every day at 9:00 AM&lt;/span&gt;
0 9 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /usr/local/bin/daily-ai-post.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it — &lt;strong&gt;fully automated daily posts with zero manual work.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;required tool facebook_post not called&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Model skipped the tool call&lt;/td&gt;
&lt;td&gt;Retry, or switch to a stronger model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;HTTP 400 context overflow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prompt too long for context window&lt;/td&gt;
&lt;td&gt;Reduce &lt;code&gt;context_window&lt;/code&gt; or set a smaller &lt;code&gt;web_fetch&lt;/code&gt; limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FACEBOOK_ACCESS_TOKEN not set&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Missing secret&lt;/td&gt;
&lt;td&gt;Add to &lt;code&gt;~/.garudust/.env&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Post published but has no image&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;generate_image&lt;/code&gt; failed silently&lt;/td&gt;
&lt;td&gt;Check &lt;code&gt;HF_TOKEN&lt;/code&gt; in &lt;code&gt;.env&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token expired after 60 days&lt;/td&gt;
&lt;td&gt;Short-lived token used&lt;/td&gt;
&lt;td&gt;Regenerate a long-lived Page Access Token&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What to Try Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple languages&lt;/strong&gt; — add &lt;code&gt;"write in English"&lt;/code&gt; or &lt;code&gt;"write in Japanese"&lt;/code&gt; to your task&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Topic rotation&lt;/strong&gt; — pass a topics array in a shell script and pick one per day&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple pages&lt;/strong&gt; — loop over page IDs to cross-post automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom image styles&lt;/strong&gt; — edit the &lt;code&gt;generate_image&lt;/code&gt; prompt in the skill to match your brand&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;Garudust is fully open source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-agent" rel="noopener noreferrer"&gt;github.com/garudust-org/garudust-agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill &amp;amp; Tool Hub:&lt;/strong&gt; &lt;a href="https://github.com/garudust-org/garudust-hub" rel="noopener noreferrer"&gt;github.com/garudust-org/garudust-hub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The hub has community-contributed skills and tools — install any of them with a single &lt;code&gt;garudust skill install&lt;/code&gt; command. If you build something useful, &lt;strong&gt;contributions are welcome.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>facebook</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
