# picogent Минимальный AI-агент с in-process agentic loop на базе Pi Agent Core. Два режима работы: WebSocket-чат и интеграция с Team Board Tracker. ## Требования - Node.js 22+ - npm ## Установка ```bash npm install npm run build ``` ## Режимы работы Picogent автоматически определяет режим по наличию конфигурации: ### 1. WebSocket-режим (чат) Без конфига запускается как WebSocket-сервер для прямого общения через браузерный клиент. ```bash npm run dev # или npm start ``` Откройте `client.html` в браузере, подключение к `ws://localhost:3100`. Настройка через переменные окружения (или `.env` файл): | Переменная | Описание | Default | |---|---|---| | `PICOGENT_PORT` | Порт WebSocket-сервера | `3100` | | `PICOGENT_WORK_DIR` | Рабочая директория агента | `cwd` | | `PICOGENT_MODEL` | Модель LLM | `sonnet` | | `PICOGENT_PROVIDER` | Провайдер LLM | `anthropic` | | `PICOGENT_API_KEY` | API ключ | — | | `ANTHROPIC_API_KEY` | API ключ (альтернатива) | — | ### 2. Agent-режим (Team Board Tracker) Агент регистрируется в трекере, получает задачи и выполняет их. Поддерживает два транспорта: - **`http`** (по умолчанию) — агент поднимает HTTP-сервер, трекер шлёт события через POST. Требует открытый порт (`listen_port`). - **`ws`** — агент сам подключается к трекеру по WebSocket. Не требует открытого порта и callback_url. Автоматический reconnect с exponential backoff. Активируется при наличии `agent.json`, директории с конфигом, или переменной `TRACKER_URL`. ## Параметры запуска ```bash # Режим директории — папка с agent.json, skills/, sessions/ npm run dev -- ./agents/coder/ # Режим файла — путь к JSON-конфигу npm run dev -- ./my-agent.json # Через переменную окружения PICOGENT_CONFIG=./agent.json npm run dev # Только через env (без файла конфига) TRACKER_URL=http://localhost:8100 AGENT_TOKEN=tb-xxx npm run dev # Production npm start -- ./agents/coder/ ``` ### Приоритет конфигурации 1. CLI аргумент (директория или файл) 2. Переменная `PICOGENT_CONFIG` 3. `./agent.json` в текущей директории (если существует) 4. Env-переменные (`TRACKER_URL` + `AGENT_TOKEN`) Env-переменные всегда имеют приоритет над значениями из JSON-файла. ## Конфигурация агента (`agent.json`) Все поля опциональны (кроме `tracker_url` и `token` для agent-режима). Полный пример с описаниями — `agent.example.json`. ```json { "name": "Кодер", "slug": "coder", "prompt": "Ты опытный Go-разработчик...", "tracker_url": "http://localhost:8100", "token": "tb-agent-abc123", "transport": "http", "listen_port": 3200, "work_dir": "/projects/my-app", "model": "sonnet", "provider": "anthropic", "capabilities": ["coding", "review"], "max_concurrent_tasks": 2, "heartbeat_interval_sec": 30, "allowed_paths": [] } ``` | Поле | Env | Default | Описание | |---|---|---|---| | `name` | `AGENT_NAME` | `Agent` | Имя агента в трекере | | `slug` | `AGENT_SLUG` | `agent` | Уникальный ID (латиница) | | `prompt` | `AGENT_PROMPT` | — | Системный промпт — роль агента | | `tracker_url` | `TRACKER_URL` | — | URL Team Board Tracker (**обязательно**) | | `token` | `AGENT_TOKEN` | — | Bearer-токен для Tracker API (**обязательно**) | | `transport` | `AGENT_TRANSPORT` | `http` | Транспорт: `http` или `ws` | | `listen_port` | `AGENT_PORT` | `3200` | Порт HTTP (только transport=http) | | `work_dir` | `PICOGENT_WORK_DIR` | `agentHome` / `cwd` | Рабочая директория | | `model` | `PICOGENT_MODEL` | `sonnet` | Модель LLM | | `provider` | `PICOGENT_PROVIDER` | `anthropic` | Провайдер LLM | | `api_key` | `PICOGENT_API_KEY` / `ANTHROPIC_API_KEY` | — | API ключ провайдера | | `capabilities` | — | `["coding"]` | Возможности для трекера | | `max_concurrent_tasks` | — | `2` | Макс. параллельных задач | | `heartbeat_interval_sec` | — | `30` | Интервал heartbeat (сек.) | | `allowed_paths` | — | `[]` (без ограничений) | Ограничение доступа к FS | ### Алиасы моделей | Алиас | Полный ID | |---|---| | `sonnet` | `claude-sonnet-4-6` | | `opus` | `claude-opus-4-6` | | `haiku` | `claude-haiku-4-5` | | `sonnet-4` | `claude-sonnet-4-6` | | `opus-4` | `claude-opus-4-6` | | `sonnet-3.5` | `claude-3-5-sonnet-20241022` | ## Режим директории (рекомендуется) Самый удобный способ — создать папку со всем необходимым: ``` agents/coder/ agent.json # конфиг skills/ # скилы агента review/ SKILL.md sessions/ # сессии (создаётся автоматически) ``` Запуск: ```bash npm run dev -- ./agents/coder/ ``` В этом режиме: - `agentHome` = путь к директории - `workDir` = то же (если не переопределён через `work_dir` или env) - Скилы загружаются из `agentHome/skills/` - Сессии сохраняются в `agentHome/sessions/` ## Скилы (Skills) Агент поддерживает скилы — специализированные инструкции в формате `SKILL.md`. ### Структура скила ``` skills/ review/ SKILL.md refactor/ SKILL.md ``` ### Формат `SKILL.md` ```markdown --- name: review description: "Code review — анализ кода на ошибки, стиль, производительность" --- # Code Review Инструкции для агента... ``` ### Как работает Используется **progressive loading** (как в Claude Code): 1. В системный промпт попадают только XML-сводки скилов (имя + описание + путь) 2. Агент читает полный `SKILL.md` через инструмент `Read` только когда скил нужен 3. Контекст не засоряется лишним текстом Скилы загружаются из двух мест: - `agentHome/skills/` (или `workDir/skills/`) — скилы конкретного агента - `~/.picogent/skills/` — глобальные скилы ## Ограничение доступа к файлам (`allowed_paths`) По умолчанию агент может читать и писать файлы без ограничений. Для ограничения укажите список разрешённых директорий: ```json { "allowed_paths": [ "/projects/my-app/src", "/projects/my-app/tests" ] } ``` Что защищено: - **Read** — проверка пути перед чтением - **Write** — проверка перед записью и созданием директорий - **Edit** — проверка перед чтением и записью - **Bash** — проверка, что рабочая директория команды внутри allowed_paths Что **не** защищено: - **Grep/Find/Ls** — read-only инструменты, не ограничиваются - **Bash-команды** — содержимое команд не парсится (агент может выполнить `cat /etc/passwd`). Для полной изоляции bash используйте контейнеры ## `.env` файл API ключи и секреты удобно хранить в `.env` файле в корне проекта: ```env ANTHROPIC_API_KEY=sk-ant-... TRACKER_URL=http://localhost:8100 AGENT_TOKEN=tb-agent-abc123 ``` Node 22 загружает `.env` автоматически через флаг `--env-file=.env` (прописан в `package.json`). ## Архитектура ``` src/ index.ts # Точка входа, dual-mode wiring config.ts # Загрузка конфигурации (JSON + env) agent.ts # Pi Agent Core — agentic loop, skills, sessions sandbox.ts # Sandboxed tools с проверкой путей router.ts # Роутер событий трекера -> agent logger.ts # Pino logger transport/ websocket.ts # WebSocket-сервер (чат-режим) http.ts # HTTP-сервер (agent-режим, transport=http) ws-client.ts # WebSocket-клиент к трекеру (agent-режим, transport=ws) types.ts # Общие типы транспорта tracker/ client.ts # HTTP-клиент к Tracker API registration.ts # Регистрация + heartbeat types.ts # Типы Tracker API ``` ### Поток данных **WebSocket-режим:** ``` Browser (client.html) -> WebSocket -> index.ts -> runAgent() -> Pi Agent Core -> WebSocket -> Browser ``` **Agent-режим (transport=http):** ``` Tracker -> HTTP POST /events -> HttpTransport -> EventRouter -> runAgent() -> Pi Agent Core -> TrackerClient -> Tracker ``` **Agent-режим (transport=ws):** ``` Agent -> WebSocket -> Tracker (auth + heartbeat + events) -> WsClientTransport -> EventRouter -> runAgent() -> TrackerClient -> Tracker ``` ### Ядро (`agent.ts`) Использует Pi Agent Core (`@mariozechner/pi-coding-agent`) для in-process agentic loop: - Модели через `ModelRegistry` с `models.json` в `~/.picogent/` - API ключи через `AuthStorage` с runtime injection (`initAgent()`) - Инструменты: Read, Write, Edit, Bash, Grep, Find, Ls (через `createSandboxedTools`) - Сессии: JSONL-файлы через `SessionManager` - Скилы: `loadSkills()` + `formatSkillsForPrompt()` для progressive loading ### Tracker интеграция - **HTTP-транспорт** (по умолчанию): POST `/api/v1/agents/register` с callback_url, POST `/api/v1/agents/heartbeat`, события через HTTP POST - **WS-транспорт**: агент подключается к `/ws?client_type=agent`, регистрация и heartbeat через WebSocket, события приходят через тот же канал - **Задачи**: трекер отправляет `task.assigned` event -> агент выполняет -> результат как комментарий + статус `review` - **Чат**: трекер отправляет `chat.message` -> агент отвечает -> комментарий к задаче - **Устойчивость**: HTTP — retry регистрации каждые 5с. WS — reconnect с exponential backoff (1с → 30с) ## WebSocket-протокол ### Клиент -> Сервер ```json { "id": "msg-1", "content": "Какие файлы есть в текущей директории?", "sessionId": "my-session", "workDir": "/projects/my-app", "systemPrompt": "Ты помощник-разработчик" } ``` | Поле | Обязательно | Описание | |---|---|---| | `id` | да | Уникальный ID сообщения | | `content` | да | Текст промпта | | `sessionId` | нет | Имя сессии (для сохранения контекста между сообщениями) | | `workDir` | нет | Рабочая директория для этого запроса | | `systemPrompt` | нет | Дополнительный системный промпт | ### Сервер -> Клиент (стрим) ```json { "id": "msg-1", "type": "text", "content": "В директории находятся...", "sessionId": "abc-123" } ``` Типы сообщений: - **`text`** — фрагмент текстового ответа (стримится по мере генерации) - **`tool_use`** — агент вызвал инструмент (формат: `ToolName: описание`) - **`tool_result`** — результат инструмента с ошибкой - **`error`** — ошибка агента или API - **`done`** — запрос завершён ## Команды ```bash npm install # Установка зависимостей npm run build # Компиляция TypeScript npm run dev # Dev-режим (tsx, .env) npm start # Запуск из dist/ (.env) npm test # Тесты (vitest) ``` ## Файлы данных | Путь | Описание | |---|---| | `~/.picogent/` | Домашняя директория picogent | | `~/.picogent/models.json` | Конфигурация моделей (создаётся автоматически) | | `~/.picogent/auth.json` | Хранилище API ключей | | `~/.picogent/sessions/` | Сессии по умолчанию | | `~/.picogent/skills/` | Глобальные скилы | ## Происхождение Проект извлечён из двух соседних проектов: - **OpenClaw** (`openclaw/`) — паттерн in-process agent loop через Pi Agent Core (`createAgentSession`, `AuthStorage`, `ModelRegistry`, `codingTools`, event subscription) - **NanoClaw** (`nanoclaw/`) — паттерн pino-логгера, структура "получи сообщение -> запусти агента -> отправь результат" Сознательно выброшено: каналы, контейнеры, плагины, auth profiles, MCP, subagents и прочая сложность. Picogent — это голый agent loop + транспорт.