🤖 Agent Platform
Агенты — это DB-сущности, не Python классы. Профиль + методы + sub-agents + selection policy. Выбираются автоматически через agent_selection.py.
Что такое Агент
Агент в clowbot — это комбинация DB-таблиц, которая описывает поведение LLM:
Goal, tools, models, temperature
Prompt templates + tools per method
Делегирование задач
Когда выбирать агента
🔄 Agent Selection Flow
От intent до assembled prompt
💻 Код: select_agent
async def select_agent(
db, *,
intent: str = "", # "web_search", "code", "summarize"
process_code: str = "", # "direct_chat", "travel_research"
scope: str = "direct", # "direct", "group", "operator"
user_text: str = "",
complexity: str = "simple", # "simple", "complex", "high"
) -> dict[str, Any]:
# 1. Поиск по политике
matched = await db.find_agent_by_policy(
intent=intent,
process_code=process_code,
scope=scope,
)
if matched:
agent_code = matched["agent_code"]
else:
agent_code = "core_orchestrator" # Fallback
# 2. Загрузка профиля
profile = await db.get_agent_profile(agent_code)
methods = await db.get_agent_methods(agent_code)
sub_agents = await db.get_agent_sub_agents(agent_code)
# 3. Загрузка prompt fragments
fragments = await db.get_agent_prompt_fragments(agent_code)
if not fragments:
# Auto-select fragments by type/family
fragment_type = _infer_fragment_type(intent) # "research", "coding", etc.
agent_family = _infer_agent_family(agent_code) # "orchestrator", "researcher"
fragments = await db.get_top_prompt_fragments(
fragment_type=fragment_type,
agent_family=agent_family,
limit=3,
)
# 4. Сборка system prompt
assembled_prompt = _assemble_prompt(profile, fragments)
prompt_hash = hashlib.sha256(assembled_prompt.encode()).hexdigest()[:16]
# 5. Return result
return {
"selected_agent_code": agent_code,
"assembled_system_prompt": assembled_prompt,
"system_prompt_hash": prompt_hash,
"fragment_ids": [f["fragment_id"] for f in fragments],
"allowed_tools": list(profile.get("allowed_tools") or []),
"forbidden_tools": list(profile.get("forbidden_tools") or []),
"preferred_model": (profile.get("preferred_models") or [""])[0],
"default_temperature": float(profile.get("default_temperature") or 0.7),
"execution_mode": _infer_execution_mode(intent, complexity),
"selection_reason": f"intent_match={intent}",
"methods": methods,
"sub_agents": sub_agents,
}📝 Prompt Assembly
Fragment Assembly Modes
Assembly Order
def _assemble_prompt(profile, fragments) -> str:
parts = []
# 1. Goal
goal = profile.get("goal", "").strip()
if goal:
parts.append(goal)
# 2. Tools
allowed = profile.get("allowed_tools") or []
forbidden = profile.get("forbidden_tools") or []
if allowed:
parts.append(f"Available tools: {', '.join(allowed)}")
if forbidden:
parts.append(f"Forbidden tools: {', '.join(forbidden)}")
# 3. Fragments
prepend = []
append = []
for frag in fragments:
content = frag.get("content", "").strip()
mode = frag.get("assembly_mode", "append")
if mode == "prepend":
prepend.append(content)
elif mode == "replace":
return content # Replace everything
else:
append.append(content)
# 4. Combine
return "\n\n".join(prepend + parts + append)🎯 Intent → Fragment Type
🗄️ DB Schema
agent_profile
agent_methods
agent_sub_agents
agent_selection_policy
💡 Примеры агентов
Главный оркестратор. Выбирается когда нет точного match.
Поиск и синтез информации из интернета.
Написание и выполнение кода, SQL queries.
🛠️ Создание нового агента
Авто-деплой новых агентов запрещён. Требуется human approval.
-- Step 1: Create profile (DRAFT status)
INSERT INTO clowbot.agent_profile (
agent_code, goal, description,
allowed_tools, forbidden_tools,
preferred_models, default_temperature,
safety_level, review_mode, is_active
) VALUES (
'my_custom_agent',
'You are a custom agent for specific tasks...',
'Handles X, Y, Z tasks',
ARRAY['tool_a', 'tool_b'],
ARRAY['dangerous_tool'],
ARRAY['phi4-mini', 'llama3.2:3b'],
0.3,
'safe',
'human_approval',
false -- Not active until approved
);
-- Step 2: Add methods
INSERT INTO clowbot.agent_methods (agent_code, method_code, method_type, prompt_template)
VALUES
('my_custom_agent', 'analyze', 'prompt', 'Analyze: {{input}}'),
('my_custom_agent', 'summarize', 'prompt', 'Summarize: {{input}}');
-- Step 3: Add selection policy
INSERT INTO clowbot.agent_selection_policy (
agent_code, match_intent, match_process_code, priority, is_active
) VALUES (
'my_custom_agent',
ARRAY['custom_task', 'my_intent'],
ARRAY['my_process'],
100,
true
);
-- Step 4: Review & Approve (manual step)
UPDATE clowbot.agent_profile
SET is_active = true
WHERE agent_code = 'my_custom_agent';🔧 Troubleshooting
Агент не выбирается
Проверьте agent_selection_policy.match_intent — должен содержать intent. Проверьте is_active = true.
Fallback на core_orchestrator
Нормально если нет точного match. Проверьте selection_reason в ответе.
Prompt fragments не находятся
Проверьте prompt_fragments table и agent_family mapping.