บทนำ: ทำไม Agent Roles ถึงสำคัญ?
ในโลกของ Multi-Agent System การที่ AI Agent แต่ละตัวมี "บทบาท" ที่ชัดเจนเหมือนทีมงานจริงๆ ไม่ใช่แค่เรื่องของความสวยงาม แต่เป็นรากฐานที่ทำให้ระบบทำงานได้อย่างมีประสิทธิภาพ ผมเคยเห็นหลายโปรเจกต์ที่สร้าง Agent ขึ้นมาหลายตัวแต่ทุกตัวทำงานซ้ำซ้อนกัน เพราะไม่มีใครกำหนดว่าใครรับผิดชอบอะไร
จากประสบการณ์การพัฒนาระบบ RAG ขององค์กรใหญ่แห่งหนึ่ง ทีมของเราใช้เวลาหลายสัปดาห์ในการ tune Agent Roles ให้เหมาะสม จนประสบความสำเร็จลดเวลาตอบคำถามลูกค้าจาก 30 วินาทีเหลือแค่ 3 วินาที
กรณีศึกษา: ระบบ AI ลูกค้าสัมพันธ์อีคอมเมิร์ซ
ลองนึกภาพร้านค้าออนไลน์ที่มีคำถามเข้ามาวันละหลายพันรายการ ตั้งแต่สถานะจัดส่ง การคืนสินค้า ไปจนถึงคำแนะนำสินค้า ถ้าใช้ Agent เดียวดูแลทุกเรื่อง คุณภาพจะไม่คงที่ แต่ถ้าแบ่งบทบาทชัดเจน:
- Order Specialist Agent - ดูแลเรื่องสถานะคำสั่งซื้อและการจัดส่ง
- Returns Agent - จัดการกระบวนการคืนสินค้าโดยเฉพาะ
- Product Advisor Agent - แนะนำสินค้าตามความต้องการลูกค้า
- Escalation Manager Agent - ส่งต่อปัญหาที่ซับซ้อนไปยังมนุษย์
แต่ละ Agent มี memory, tools และ goal ที่แตกต่างกัน ทำให้การตอบสนองแม่นยำและรวดเร็วกว่ามาก
โครงสร้างพื้นฐานของ Agent Role ใน CrewAI
ใน CrewAI เรากำหนด Agent Role ผ่านพารามิเตอร์หลัก 3 ตัว:
from crewai import Agent
ตัวอย่าง Agent แบบง่าย
order_specialist = Agent(
role="ผู้เชี่ยวชาญด้านคำสั่งซื้อ",
goal="ตอบคำถามสถานะคำสั่งซื้อและจัดส่งอย่างแม่นยำภายใน 5 วินาที",
backstory="คุณทำงานในแผนก logistics มา 5 ปี รู้จักระบบจัดส่งทุกเส้นทาง",
verbose=True,
allow_delegation=False
)
แต่ในการใช้งานจริง เราต้องการ Agent ที่ซับซ้อนกว่านี้ มาดูตัวอย่างที่เชื่อมต่อกับ HolySheep AI กัน
การสร้าง Agent พร้อม Tools ผ่าน HolySheep AI
สำหรับการใช้งานจริงในองค์กร ผมแนะนำให้ใช้ HolySheep AI เพราะราคาประหยัดมาก — เช่น DeepSeek V3.2 อยู่ที่ $0.42/MTok เทียบกับ GPT-4.1 ที่ $8/MTok คุณประหยัดได้ถึง 95% และยังรองรับ WeChat/Alipay สำหรับชำระเงินได้อีกด้วย
import os
from crewai import Agent, Task, Crew
from crewai_tools import SerpApiWrapper, DatabaseSearchTool
ตั้งค่า API Key ของ HolySheep AI
os.environ["OPENAI_API_KEY"] = "YOUR_HOLYSHEEP_API_KEY"
os.environ["OPENAI_API_BASE"] = "https://api.holysheep.ai/v1"
from langchain_openai import ChatOpenAI
สร้าง LLM instance ด้วย HolySheep
llm = ChatOpenAI(
model="gpt-4o",
openai_api_key="YOUR_HOLYSHEEP_API_KEY",
openai_api_base="https://api.holysheep.ai/v1"
)
กำหนด Tools สำหรับแต่ละ Agent
order_tools = [
DatabaseSearchTool(
db_path="orders.db",
description="ค้นหาข้อมูลคำสั่งซื้อและสถานะจัดส่ง"
)
]
returns_tools = [
DatabaseSearchTool(db_path="returns.db"),
SerpApiWrapper(description="ค้นหานโยบายการคืนสินค้า")
]
Agent สำหรับดูแลเรื่องคำสั่งซื้อ
order_specialist = Agent(
role="ผู้เชี่ยวชาญด้านคำสั่งซื้อและจัดส่ง",
goal="ตอบคำถามสถานะคำสั่งซื้อและติดตามพัสดุอย่างแม่นยำ",
backstory="""
คุณเป็นพนักงาน logistics ระดับ senior ที่บริษัท E-Shop
คุณรู้ระบบจัดส่งทุกขนาด ตั้งแต่ Kerry, FLASH จนถึง J&T
คุณเข้าถึงฐานข้อมูลคำสั่งซื้อแบบ real-time ได้
คุณต้องให้ข้อมูลที่เป็นปัจจุบันที่สุดเสมอ
""",
tools=order_tools,
llm=llm,
verbose=True,
memory=True # เปิดใช้งาน memory เพื่อเก็บประวัติการสนทนา
)
Agent สำหรับดูแลเรื่องการคืนสินค้า
returns_specialist = Agent(
role="ผู้เชี่ยวชาญด้านการคืนสินค้า",
goal="ช่วยเหลือลูกค้าคืนสินค้าได้อย่างราบรื่นภายในเวลาที่กำหนด",
backstory="""
คุณเป็นผู้เชี่ยวชาญด้านบริการลูกค้าที่มีประสบการณ์ 8 ปี
คุณรู้นโยบายการคืนสินค้าทุกข้อและสามารถอธิบายให้ลูกค้าเข้าใจได้ง่าย
คุณมีอำนาจอนุมัติการคืนสินค้าสำหรับรายการที่ไม่เกิน 5,000 บาท
""",
tools=returns_tools,
llm=llm,
verbose=True
)
การกำหนด Tasks และ Crew Flow
เมื่อมี Agent แล้ว ต้องกำหนด Task และจัดลำดับการทำงานให้ถูกต้อง มิฉะนั้น Agent จะทำงานสะเปะสะปะ
from crewai import Task
Task สำหรับตรวจสอบสถานะคำสั่งซื้อ
check_order_task = Task(
description="""
ลูกค้าถามว่า: {customer_question}
ให้คุณตรวจสอบข้อมูลคำสั่งซื้อเลขที่ {order_id}
และให้ข้อมูลสถานะล่าสุดพร้อม ETA การจัดส่ง
""",
agent=order_specialist,
expected_output="รายงานสถานะคำสั่งซื้อที่ละเอียดและเป็นปัจจุบัน"
)
Task สำหรับจัดการการคืนสินค้า
process_return_task = Task(
description="""
ลูกค้าต้องการคืนสินค้าเลขที่ {order_id}
ให้คุณตรวจสอบเงื่อนไขการคืนและดำเนินการให้
หากมีปัญหาให้ติดต่อผู้จัดการทันที
""",
agent=returns_specialist,
expected_output="ยืนยันการคืนสินค้าพร้อมเลข tracking และวันที่คืนเงิน"
)
กำหนด Task สำหรับ Escalation
escalation_task = Task(
description="""
คุณได้รับมอบหมายจาก {previous_task_output}
ให้ตรวจสอบว่าปัญหานี้ต้องส่งต่อให้ฝ่ายบริหารหรือไม่
หากใช่ ให้จัดทำรายงานสรุปปัญหาพร้อมคำแนะนำ
""",
agent=escalation_manager,
expected_output="รายงานส่งต่อหรือแจ้งว่าปัญหาถูกแก้ไขแล้ว",
context=[check_order_task, process_return_task] # รับ input จาก task ก่อนหน้า
)
สร้าง Crew พร้อมกำหนด flow
customer_service_crew = Crew(
agents=[order_specialist, returns_specialist, escalation_manager],
tasks=[check_order_task, process_return_task, escalation_task],
verbose=2,
memory=True,
embedder={
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
}
)
Kick off the crew
result = customer_service_crew.kickoff(
inputs={
"customer_question": "พัสดุเลขที่ TH123456 อยู่ไหนแล้ว?",
"order_id": "TH123456"
}
)
Advanced Patterns: Role Hierarchies และ Dynamic Role Assignment
สำหรับระบบ RAG ขององค์กรที่ซับซ้อน ผมแนะนำให้สร้าง Role Hierarchy เพื่อให้ Agent รู้ว่าต้องปรึกษาใครเมื่อต้องการข้อมูลเฉพาะทาง
# กำหนด Role Hierarchy สำหรับระบบ RAG องค์กร
class RoleHierarchy:
"""กำหนดลำดับชั้นของ Agent roles"""
EXECUTIVE = "executive_manager" # ผู้บริหารสูงสุด ดูแลทุกเรื่อง
DOMAIN_LEAD = "domain_lead" # หัวหน้าฝ่ายเฉพาะทาง
SPECIALIST = "specialist" # ผู้เชี่ยวชาญเฉพาะด้าน
RESEARCHER = "researcher" # นักวิจัย ค้นหาข้อมูล
COORDINATOR = "coordinator" # ผู้ประสานงาน
ตัวอย่าง Executive Agent ที่รับผิดชอบ routing
executive_manager = Agent(
role="ผู้จัดการบริการลูกค้า AI",
goal="วิเคราะห์คำถามและส่งต่อไปยัง Agent ที่เหมาะสมที่สุด",
backstory="""
คุณเป็น AI manager ที่รับผิดชอบ triaging คำถามลูกค้า
คุณมีทักษะในการเข้าใจความต้องการที่แท้จริงของลูกค้า
และรู้ว่า Agent ไหนเหมาะกับงานประเภทไหน
คุณต้องตัดสินใจภายใน 500ms
""",
llm=llm,
verbose=True
)
Dynamic routing ตามประเภทคำถาม
def route_to_specialist(question_type: str, crew: Crew) -> Agent:
"""Route คำถามไปยัง Specialist ที่เหมาะสม"""
routing_map = {
"shipping": order_specialist,
"returns": returns_specialist,
"complaint": escalation_manager,
"product_info": product_advisor,
"technical": tech_support,
"billing": billing_specialist
}
return routing_map.get(
question_type,
executive_manager # Default to executive if unknown
)
ตัวอย่างการใช้งาน routing
def handle_customer_inquiry(question: str) -> str:
"""จัดการคำถามลูกค้าโดย routing ไปยัง Agent ที่เหมาะสม"""
# ใช้ LLM วิเคราะห์ประเภทคำถาม
classification_prompt = f"""
จงวิเคราะห์คำถามต่อไปนี้และระบุประเภท:
คำถาม: {question}
ประเภทที่เป็นไปได้: shipping, returns, complaint, product_info, technical, billing
ตอบกลับเฉพาะประเภทเท่านั้น (เช่น: shipping)
"""
question_type = llm.invoke(classification_prompt).content.strip().lower()
# Route ไปยัง Specialist ที่เหมาะสม
agent = route_to_specialist(question_type, customer_service_crew)
# Execute task
task = Task(
description=question,
agent=agent,
expected_output="คำตอบที่สมบูรณ์สำหรับลูกค้า"
)
result = crew.kickoff(inputs={"question": question})
return result
Best Practices จากประสบการณ์จริง
จากการ implement ระบบหลายตัว มีหลักการสำคัญที่ผมเรียนรู้มาว่าช่วยให้ระบบทำงานได้ดี:
- Granularity ที่เหมาะสม — อย่าแบ่งบทบาทละเอียดเกินไป เพราะจะทำให้เกิด overhead ในการสื่อสารระหว่าง Agent แต่ก็อย่าหยาบเกินไปจน Agent ทำงานหลายอย่างโดยไม่เชี่ยวชาญ
- Clear Goal Statement — Goal ของแต่ละ Agent ต้องวัดผลได้ชัดเจน เช่น "ตอบภายใน 5 วินาที" ดีกว่า "ตอบคำถามให้ดี"
- Memory Configuration — เปิด memory เฉพาะ Agent ที่ต้องเก็บ context แต่ไม่จำเป็นต้องเปิดทุกตัว เพราะจะเปลือง token
- Context Window Management — ใช้ embedding และ retrieval สำหรับ long-term memory แทนการเก็บทุกอย่างใน context
- Graceful Degradation — กำหนด fallback plan เมื่อ Agent ไม่สามารถตอบได้
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
1. Agent ทะเลาะกันเองเรื่องงาน (Role Conflict)
อาการ: สอง Agent พยายามทำ task เดียวกันพร้อมกัน หรือปฏิเสธที่จะทำเพราะคิดว่าไม่ใช่หน้าที่ตัวเอง
สาเหตุ: Backstory และ Goal ไม่ชัดเจนพอ หรือ overlap กันเกินไป
วิธีแก้:
# โค้ดที่ผิด - Agents overlap กัน
bad_agent_1 = Agent(
role="ผู้ช่วยทั่วไป",
goal="ช่วยลูกค้าทุกเรื่อง",
backstory="ฉันช่วยลูกค้าได้ทุกอย่าง"
)
bad_agent_2 = Agent(
role="ที่ปรึกษาลูกค้า",
goal="ช่วยเหลือลูกค้าทุกปัญหา",
backstory="ฉันเป็นที่ปรึกษาที่ดี"
)
โค้ดที่ถูกต้อง - แยกงานชัดเจน
good_order_agent = Agent(
role="ผู้เชี่ยวชาญด้านคำสั่งซื้อ",
goal="จัดการเฉพาะเรื่องสถานะคำสั่งซื้อและจัดส่งเท่านั้น",
backstory="""
คุณรับผิดชอบเฉพาะเรื่องคำสั่งซื้อ:
- ตรวจสอบสถานะการจัดส่ง
- แก้ไขที่อยู่จัดส่ง
- ยกเลิกคำสั่งซื้อ
หากลูกค้าถามเรื่องอื่น ให้ส่งต่อไปยัง Agent ที่เหมาะสม
และไม่พยายามตอบเรื่องที่ไม่ใช่ความเชี่ยวชาญของคุณ
""",
verbose=True
)
good_returns_agent = Agent(
role="ผู้เชี่ยวชาญด้านการคืนสินค้า",
goal="จัดการเฉพาะเรื่องการคืนและเปลี่ยนสินค้าเท่านั้น",
backstory="""
คุณรับผิดชอบเฉพาะเรื่องการคืนสินค้า:
- ดำเนินการคืนสินค้า
- เปลี่ยนสินค้า
- คืนเงิน
หากลูกค้าถามเรื่องอื่น ให้ส่งต่อไปยัง Agent ที่เหมาะสม
"""
)
กำหนด allow_delegation เพื่อควบคุมการส่งต่องาน
good_order_agent = Agent(
# ... config อื่นๆ
allow_delegation=True, # อนุญาตให้ส่งต่องานได้
max_iterations=3 # จำกัดจำนวนรอบการทำงาน
)
2. Agent ตอบสารภาพรู้เรื่อง Hallucination
อาการ: Agent ตอบคำถามผิดๆ มั่วๆ โดยเฉพาะเรื่องข้อมูลที่ไม่มีใน knowledge base
สาเหตุ: Backstory ไม่ได้กำหนดว่าต้องตรวจสอบข้อมูลจากแหล่งไหน หรือไม่มี tools สำหรับค้นหาข้อมูล
วิธีแก้:
# โค้ดที่ผิด - Agent พูดเรื่องที่ไม่รู้ได้เลย
bad_agent = Agent(
role="ที่ปรึกษาสินค้า",
goal="แนะนำสินค้าให้ลูกค้า",
backstory="ฉันรู้เกี่ยวกับสินค้าทุกอย่างในร้าน"
# ไม่มี tools สำหรับค้นหา!
)
โค้ดที่ถูกต้อง - บังคับให้ตรวจสอบจากแหล่งข้อมูล
good_product_agent = Agent(
role="ผู้เชี่ยวชาญด้านสินค้า",
goal="แนะนำสินค้าที่เหมาะสมโดยอ้างอิงจากข้อมูลจริงเท่านั้น",
backstory="""
คุณเป็นผู้เชี่ยวชาญสินค้าที่ต้องแนะนำจากข้อมูลที่ตรวจสอบได้เท่านั้น
กฎสำคัญ:
1. ห้ามแต่งข้อมูลสินค้าที่ไม่มีในระบบ
2. ห้ามให้ข้อมูลราคาที่ไม่ตรงกับฐานข้อมูล
3. ห้ามสรุปคุณสมบัติสินค้าจากการคาดเดา
หากไม่แน่ใจว่ามีสินค้าที่ลูกค้าถามหรือไม่:
- ต้องค้นหาในระบบก่อนเสมอ
- ถ้าไม่พบ ให้ตอบว่า "ไม่พบสินค้าที่คุณต้องการ ต้องการให้แนะนำสินค้าทดแทนหรือไม่?"
""",
tools=[
DatabaseSearchTool(
db_path="products.db",
description="ค้นหาข้อมูลสินค้า ราคา และคุณสมบัติ"
),
RAGRetrieverTool(
description="ดึงข้อมูลจากคู่มือสินค้าและบทวิจารณ์"
)
],
llm=llm,
verbose=True,
# เพิ่ม constraints เพื่อลด hallucination
constraints=[
"ต้องตรวจสอบข้อมูลจาก tools ก่อนตอบทุกครั้ง",
"หากไม่มีข้อมูลใน tools ให้บอกว่าไม่ทราบ",
"อ้างอิง source ของข้อมูลเสมอ"
]
)
ใช้ Guardrails เพิ่มเติม
from guardrails import Guard, OnBadLLMResponse