docs: add Agent Management and OpenClaw Webhooks integration
- Agent Registry schema - OpenClaw Webhooks API documentation - Team Board → OpenClaw architecture - Python client example - Task execution flow
This commit is contained in:
parent
35907c0e0f
commit
4209bc26fd
309
RESEARCH.md
309
RESEARCH.md
@ -354,4 +354,313 @@ class AgentSessionManager:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Agent Management System
|
||||||
|
|
||||||
|
### Agent Registry (БД)
|
||||||
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE agents (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name TEXT NOT NULL, -- "Coder", "Analyst"
|
||||||
|
slug TEXT UNIQUE NOT NULL, -- "coder", "analyst"
|
||||||
|
|
||||||
|
-- Настройки
|
||||||
|
model TEXT, -- "claude-opus-4-5", "claude-sonnet"
|
||||||
|
system_prompt TEXT, -- роль/персона
|
||||||
|
max_concurrent INT DEFAULT 1, -- макс параллельных задач
|
||||||
|
|
||||||
|
-- Статус
|
||||||
|
status TEXT DEFAULT 'idle', -- idle, working, error, disabled
|
||||||
|
current_tasks INT DEFAULT 0,
|
||||||
|
|
||||||
|
-- Мета
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Web UI: Agent Config
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Agents [+ Add] │
|
||||||
|
├─────────────────────────────────────────────┤
|
||||||
|
│ 🟢 Coder claude-opus idle [⚙] │
|
||||||
|
│ 🟢 Reviewer claude-sonnet idle [⚙] │
|
||||||
|
│ 🟡 Analyst claude-opus working[⚙] │
|
||||||
|
│ ⚫ Tester claude-sonnet disabled[⚙] │
|
||||||
|
└─────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Task Assignment Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
1. User создаёт задачу в Web UI
|
||||||
|
2. Назначает агента (или Auto → Lead решает)
|
||||||
|
3. Team Board → POST /hooks/agent → OpenClaw
|
||||||
|
4. OpenClaw проверяет лимиты, спавнит субагента
|
||||||
|
5. Субагент работает, результат → callback
|
||||||
|
6. Team Board обновляет задачу в БД
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## OpenClaw Webhooks API
|
||||||
|
|
||||||
|
### Конфигурация
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"enabled": true,
|
||||||
|
"token": "${OPENCLAW_HOOKS_TOKEN}",
|
||||||
|
"path": "/hooks",
|
||||||
|
"defaultSessionKey": "hook:team-board",
|
||||||
|
"allowRequestSessionKey": true,
|
||||||
|
"allowedSessionKeyPrefixes": ["hook:", "task:"],
|
||||||
|
"allowedAgentIds": ["main", "coder", "reviewer"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Эндпоинты
|
||||||
|
|
||||||
|
#### POST /hooks/wake — Разбудить основную сессию
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:18789/hooks/wake \
|
||||||
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"text": "Новая задача в Team Board", "mode": "now"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Параметры:**
|
||||||
|
- `text` (required) — описание события
|
||||||
|
- `mode` — `now` (сразу) или `next-heartbeat` (при след. проверке)
|
||||||
|
|
||||||
|
#### POST /hooks/agent — Запустить изолированную сессию
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:18789/hooks/agent \
|
||||||
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"message": "Напиши функцию сортировки на Python",
|
||||||
|
"name": "TeamBoard",
|
||||||
|
"agentId": "main",
|
||||||
|
"sessionKey": "task:abc123",
|
||||||
|
"deliver": true,
|
||||||
|
"channel": "telegram",
|
||||||
|
"timeoutSeconds": 300
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Параметры:**
|
||||||
|
- `message` (required) — промпт для агента
|
||||||
|
- `name` — название хука для логов
|
||||||
|
- `agentId` — ID агента (main, coder, etc.)
|
||||||
|
- `sessionKey` — ключ сессии для отслеживания
|
||||||
|
- `deliver` — отправить ответ в канал
|
||||||
|
- `channel` — канал для ответа (telegram, discord, etc.)
|
||||||
|
- `model` — переопределение модели
|
||||||
|
- `thinking` — уровень размышлений (low, medium, high)
|
||||||
|
- `timeoutSeconds` — таймаут выполнения
|
||||||
|
|
||||||
|
### Аутентификация
|
||||||
|
|
||||||
|
```
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
# или
|
||||||
|
x-openclaw-token: <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ Query-string токены (`?token=...`) запрещены.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Team Board → OpenClaw Integration
|
||||||
|
|
||||||
|
### Архитектура
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Team Board │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ Web UI │ │ Tasks │ │ Agents │ │
|
||||||
|
│ │ (Next.js) │ │ Service │ │ Service │ │
|
||||||
|
│ └─────────────┘ └──────┬──────┘ └──────┬──────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ └────────┬────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ┌────────▼────────┐ │
|
||||||
|
│ │ OpenClaw │ │
|
||||||
|
│ │ Client │ │
|
||||||
|
│ └────────┬────────┘ │
|
||||||
|
└───────────────────────────────────┼─────────────────────────┘
|
||||||
|
│ HTTP
|
||||||
|
▼
|
||||||
|
┌───────────────────────────────────────────────────────────────┐
|
||||||
|
│ OpenClaw Gateway │
|
||||||
|
│ localhost:18789 │
|
||||||
|
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||||
|
│ │ /hooks/wake │ │/hooks/agent │ │ Sessions │ │
|
||||||
|
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ ▼ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Agent: main (Марков) │ │
|
||||||
|
│ │ - sessions_spawn → субагенты │ │
|
||||||
|
│ │ - sessions_send → коммуникация │ │
|
||||||
|
│ │ - sessions_history → история │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
└───────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### OpenClaw Client (Python)
|
||||||
|
|
||||||
|
```python
|
||||||
|
import httpx
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class OpenClawClient:
|
||||||
|
def __init__(self, base_url: str, token: str):
|
||||||
|
self.base_url = base_url
|
||||||
|
self.headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
async def wake(self, text: str, mode: str = "now"):
|
||||||
|
"""Разбудить основную сессию"""
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.post(
|
||||||
|
f"{self.base_url}/hooks/wake",
|
||||||
|
headers=self.headers,
|
||||||
|
json={"text": text, "mode": mode}
|
||||||
|
)
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
async def run_agent(
|
||||||
|
self,
|
||||||
|
message: str,
|
||||||
|
session_key: str,
|
||||||
|
agent_id: str = "main",
|
||||||
|
deliver: bool = False,
|
||||||
|
timeout: int = 300
|
||||||
|
):
|
||||||
|
"""Запустить задачу в изолированной сессии"""
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.post(
|
||||||
|
f"{self.base_url}/hooks/agent",
|
||||||
|
headers=self.headers,
|
||||||
|
json={
|
||||||
|
"message": message,
|
||||||
|
"name": "TeamBoard",
|
||||||
|
"agentId": agent_id,
|
||||||
|
"sessionKey": session_key,
|
||||||
|
"deliver": deliver,
|
||||||
|
"timeoutSeconds": timeout
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return response.json()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Task Execution Flow
|
||||||
|
|
||||||
|
```python
|
||||||
|
async def execute_task(task: Task, agent: Agent):
|
||||||
|
client = OpenClawClient(
|
||||||
|
base_url="http://localhost:18789",
|
||||||
|
token=settings.OPENCLAW_TOKEN
|
||||||
|
)
|
||||||
|
|
||||||
|
# Формируем промпт
|
||||||
|
prompt = f"""
|
||||||
|
Задача: {task.title}
|
||||||
|
|
||||||
|
Описание: {task.description}
|
||||||
|
|
||||||
|
Контекст проекта: {task.project.brief}
|
||||||
|
|
||||||
|
Выполни задачу и верни результат.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Запускаем агента
|
||||||
|
result = await client.run_agent(
|
||||||
|
message=prompt,
|
||||||
|
session_key=f"task:{task.id}",
|
||||||
|
agent_id=agent.slug,
|
||||||
|
timeout=600
|
||||||
|
)
|
||||||
|
|
||||||
|
# Обновляем статус
|
||||||
|
task.status = "in_progress"
|
||||||
|
task.openclaw_session = result.get("sessionKey")
|
||||||
|
await task.save()
|
||||||
|
|
||||||
|
return result
|
||||||
|
```
|
||||||
|
|
||||||
|
### Получение результатов
|
||||||
|
|
||||||
|
**Вариант 1: Polling**
|
||||||
|
```python
|
||||||
|
async def poll_task_result(task: Task):
|
||||||
|
client = OpenClawClient(...)
|
||||||
|
|
||||||
|
# Получаем историю сессии
|
||||||
|
history = await client.get_session_history(task.openclaw_session)
|
||||||
|
|
||||||
|
# Парсим последний ответ
|
||||||
|
last_message = history["messages"][-1]
|
||||||
|
if last_message["role"] == "assistant":
|
||||||
|
task.result = last_message["content"]
|
||||||
|
task.status = "completed"
|
||||||
|
await task.save()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Вариант 2: Callback Webhook**
|
||||||
|
```python
|
||||||
|
# Team Board получает callback от OpenClaw
|
||||||
|
@app.post("/api/callbacks/openclaw")
|
||||||
|
async def openclaw_callback(data: dict):
|
||||||
|
session_key = data.get("sessionKey")
|
||||||
|
result = data.get("result")
|
||||||
|
|
||||||
|
# Находим задачу по session_key
|
||||||
|
task = await Task.find_by_session(session_key)
|
||||||
|
task.result = result
|
||||||
|
task.status = "completed"
|
||||||
|
await task.save()
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Текущий статус OpenClaw
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Gateway endpoint
|
||||||
|
http://localhost:18789
|
||||||
|
|
||||||
|
# Текущий токен
|
||||||
|
cat ~/.openclaw/openclaw.json | jq '.gateway.auth.token'
|
||||||
|
|
||||||
|
# Webhooks пока не настроены — нужно включить
|
||||||
|
```
|
||||||
|
|
||||||
|
### Для активации webhooks:
|
||||||
|
|
||||||
|
```json
|
||||||
|
// ~/.openclaw/openclaw.json
|
||||||
|
{
|
||||||
|
"hooks": {
|
||||||
|
"enabled": true,
|
||||||
|
"token": "team-board-secret-token",
|
||||||
|
"path": "/hooks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
*Документ обновляется по мере исследования.*
|
*Документ обновляется по мере исследования.*
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user