Сборка промпта
VibeOS намеренно разделяет:
- кэшированное состояние системного промпта
- эфемерные дополнения на момент вызова API
Это одно из важнейших архитектурных решений в проекте, поскольку оно влияет на:
- использование токенов
- эффективность кэширования промптов
- непрерывность сессии
- корректность памяти
Основные файлы:
run_agent.pyagent/prompt_builder.pytools/memory_tool.py
Слои кэшированного системного промпта
Кэшированный системный промпт собирается из трёх упорядоченных уровней (см. agent/system_prompt.py):
- стабильный — идентичность (
SOUL.mdили запасной вариант), инструкции по инструментам/моделям, промпт навыков, подсказки окружения, подсказки платформы - контекст — предоставленное вызывающей стороной
system_messageплюс файлы контекста проекта (.vibeos.md/AGENTS.md/CLAUDE.md/.cursorrules) - изменчивый — встроенный снимок памяти (
MEMORY.md), снимок профиля пользователя (USER.md), блок внешнего провайдера памяти, строка с меткой времени/сессии/модели/провайдера
Итоговый системный промпт затем объединяется как: стабильный → контекст → изменчивый.
Этот порядок важен для обсуждения приоритетов:
- навыки являются частью стабильного уровня
- снимки памяти/профиля являются частью изменчивого уровня
- оба всё ещё находятся в кэшированном системном промпте (они не внедряются как ad-hoc наложения в середине оборота)
Когда установлен skip_context_files (например, при делегировании субагенту), SOUL.md не загружается, и вместо него используется жёстко заданный DEFAULT_AGENT_IDENTITY.
Конкретный пример: собранный системный промпт
Вот упрощённый вид итогового системного промпта, когда присутствуют все слои (комментарии показывают источник каждого раздела):
# Слой 1: Идентичность агента (из ~/.vibeos/SOUL.md)
Вы — VibeOS, ИИ-ассистент, созданный Nous Research.
Вы — эксперт в программной инженерии и исследованиях.
Вы цените корректность, ясность и эффективность.
...
# Слой 2: Поведенческие инструкции с учётом инструментов
У вас есть постоянная память между сессиями. Сохраняйте долговечные
факты с помощью инструмента памяти: предпочтения пользователя, детали
окружения, особенности инструментов и стабильные соглашения. Память
внедряется в каждый оборот, поэтому храните её компактной и
сфокусированной на фактах, которые будут важны позже.
...
Когда пользователь ссылается на что-то из прошлого разговора или вы
подозреваете, что существует релевантный межсессионный контекст,
используйте session_search, чтобы вспомнить его, прежде чем просить
пользователя повторяться.
# Принудительное использование инструментов (только для моделей GPT/Codex)
Вы ОБЯЗАНЫ использовать свои инструменты для действий — не описывайте,
что вы бы сделали или планируете сделать, не выполняя этого.
...
# Слой 3: Статический блок Honcho (когда активен)
[Данные личности/контекста Honcho]
# Слой 4: Опциональное системное сообщение (из конфига или API)
[Пользовательское переопределение системного сообщения]
# Слой 5: Замороженный снимок MEMORY
## Постоянная память
- Пользователь предпочитает Python 3.12, использует pyproject.toml
- Редактор по умолчанию: nvim
- Работает над проектом «atlas» в ~/code/atlas
- Часовой пояс: US/Pacific
# Слой 6: Замороженный снимок профиля USER
## Профиль пользователя
- Имя: Алиса
- GitHub: alice-dev
# Слой 7: Индекс навыков
## Навыки (обязательно)
Перед ответом просмотрите навыки ниже. Если один из них явно
соответствует вашей задаче, загрузите его с помощью skill_view(name)
и следуйте его инструкциям.
...
<available_skills>
software-development:
- code-review: Структурированный процесс ревью кода
- test-driven-development: Методология TDD
research:
- arxiv: Поиск и обобщение статей arXiv
</available_skills>
# Слой 8: Файлы контекста (из директории проекта)
# Контекст проекта
Следующие файлы контекста проекта были загружены и им следует следовать:
## AGENTS.md
Это проект atlas. Для тестирования используйте pytest. Основная
точка входа — src/atlas/main.py. Перед коммитом всегда выполняйте
`make lint`.
# Слой 9: Метка времени + сессия
Текущее время: 2026-03-30T14:30:00-07:00
Сессия: abc123
# Слой 10: Подсказка платформы
Вы — CLI-агент. Старайтесь не использовать Markdown, а отображать
простой текст, читаемый в терминале.
Настройка подсказок платформы
Подсказка платформы (Слой 10 выше) — это руководство для конкретного интерфейса, которое VibeOS внедряет для Telegram, WhatsApp, Slack, CLI и других платформ — например, «вы работаете в терминале, избегайте Markdown». Встроенные значения по умолчанию находятся в PLATFORM_HINTS (agent/system_prompt.py); платформы, предоставленные плагинами, передают свои подсказки через реестр платформ.
Администратор может дополнить или заменить подсказку для одной платформы из config.yaml с помощью ключа верхнего уровня platform_hints, не затрагивая другие платформы:
platform_hints:
whatsapp:
append: >
Когда табличный вывод был бы полезен, вызывайте навык
table_formatting вместо создания Markdown-таблицы.
slack:
replace: "Вы работаете в Slack. Делайте ответы краткими и избегайте широких таблиц."
telegram: "Предпочитайте короткие сообщения; разбивайте длинные ответы." # сокращение = append
append— сохранить встроенную подсказку и добавить дополнительный текст после неё.replace— полностью заменить встроенную подсказку.- Простая строка — сокращение для
append. replaceимеет приоритет надappend, если присутствуют оба.- Некорректная запись игнорируется защитно и возвращается к неизменённому значению по умолчанию, поэтому плохое значение конфига никогда не сломает сборку промпта или не просочится на другие платформы.
Переопределение разрешается при построении системного промпта (начало сессии, а также при уплотнении, поскольку оно перестраивает промпт). Для фиксированного конфига оно создаёт байт-стабильную подсказку, поэтому находится в стабильном уровне вместе со встроенной подсказкой и не нарушает кэширование промпта — это не живая мутация замороженного промпта в середине сессии.
Как SOUL.md отображается в промпте
SOUL.md находится в ~/.vibeos/SOUL.md и служит идентичностью агента — самый первый раздел системного промпта. Логика загрузки в prompt_builder.py работает следующим образом:
# Из agent/prompt_builder.py (упрощённо)
def load_soul_md() -> Optional[str]:
soul_path = get_vibeos_home() / "SOUL.md"
if not soul_path.exists():
return None
content = soul_path.read_text(encoding="utf-8").strip()
content = _scan_context_content(content, "SOUL.md") # Проверка безопасности
content = _truncate_content(content, "SOUL.md") # Ограничение по умолчанию 20 тыс. символов, настраивается
return content
Когда load_soul_md() возвращает содержимое, оно заменяет жёстко заданный DEFAULT_AGENT_IDENTITY. Затем вызывается функция build_context_files_prompt() с skip_soul=True, чтобы предотвратить появление SOUL.md дважды (один раз как идентичность, второй раз как файл контекста).
Если SOUL.md не существует, система использует запасной вариант:
Вы — VibeOS, интеллектуальный ИИ-ассистент, созданный Nous Research.
Вы полезны, знающи и прямолинейны. Вы помогаете пользователям с широким
спектром задач, включая ответы на вопросы, написание и редактирование кода,
анализ информации, творческую работу и выполнение действий с помощью ваших
инструментов. Вы общаетесь ясно, признаёте неуверенность, когда это уместно,
и ставите приоритет на реальную полезность, а не на многословие, если не
указано иное. Будьте целенаправленны и эффективны в своих исследованиях.
Как внедряются файлы контекста
build_context_files_prompt() использует систему приоритетов — загружается только один тип контекста проекта (первый подходящий):
# Из agent/prompt_builder.py (упрощённо)
def build_context_files_prompt(cwd=None, skip_soul=False):
cwd_path = Path(cwd).resolve()
# Приоритет: первый подходящий — загружается ТОЛЬКО ОДИН контекст проекта
project_context = (
_load_vibeos_md(cwd_path) # 1. .vibeos.md / VIBEOS.md (поднимается до корня git)
or _load_agents_md(cwd_path) # 2. AGENTS.md (только текущая директория)
or _load_claude_md(cwd_path) # 3. CLAUDE.md (только текущая директория)
or _load_cursorrules(cwd_path) # 4. .cursorrules / .cursor/rules/*.mdc
)
sections = []
if project_context:
sections.append(project_context)
# SOUL.md из VIBEOS_HOME (независимо от контекста проекта)
if not skip_soul:
soul_content = load_soul_md()
if soul_content:
sections.append(soul_content)
if not sections:
return ""
return (
"# Контекст проекта\n\n"
"Следующие файлы контекста проекта были загружены "
"и им следует следовать:\n\n"
+ "\n".join(sections)
)
Детали обнаружения файлов контекста
| Приоритет | Файлы | Область поиска | Примечания |
|---|---|---|---|
| 1 | .vibeos.md, VIBEOS.md | От текущей директории до корня git | Нативная конфигурация проекта VibeOS |
| 2 | AGENTS.md | Только текущая директория | Общий файл инструкций для агента |
| 3 | CLAUDE.md | Только текущая директория | Совместимость с Claude Code |
| 4 | .cursorrules, .cursor/rules/*.mdc | Только текущая директория | Совместимость с Cursor |
Все файлы контекста:
- Проверяются на безопасность — проверяются на паттерны инъекций промптов (невидимый юникод, «игнорируй предыдущие инструкции», попытки кражи учётных данных)
- Усекаются — ограничиваются
context_file_max_charsсимволами (по умолчанию 20 000) с соотношением головы/хвоста 70/20 и маркером усечения - Очищаются от YAML-фронтматерии — фронтматерия
.vibeos.mdудаляется (зарезервирована для будущих переопределений конфига)
Слои только на момент вызова API
Эти слои намеренно не сохраняются как часть кэшированного системного промпта:
ephemeral_system_prompt- сообщения prefill
- наложения контекста сессии, полученные от шлюза
- последующие вызовы Honcho/внешнего извлечения, внедрённые в сообщение пользователя текущего оборота
Контекст плагина pre_llm_call также попадает в этот путь на момент вызова API: он добавляется к сообщению пользователя текущего оборота, а не записывается в кэшированный системный промпт. Когда несколько плагинов возвращают контекст, VibeOS объединяет эти блоки контекста (см. Хуки → pre_llm_call).
Это разделение сохраняет стабильный префикс стабильным для кэширования.
Снимки памяти
Данные локальной памяти и профиля пользователя захватываются в изменчивом уровне системного промпта. Записи в середине сессии обновляют состояние на диске, но не изменяют уже построенный кэшированный системный промпт до тех пор, пока не будет запущен путь перестроения (новая сессия или явный поток инвалидации/перестроения, например, перестроение, вызванное сжатием).
Файлы контекста
agent/prompt_builder.py сканирует и очищает файлы контекста проекта, используя систему приоритетов — загружается только один тип (первый подходящий):
.vibeos.md/VIBEOS.md(поднимается до корня git)AGENTS.md(текущая директория при запуске; поддиректории обнаруживаются прогрессивно в течение сессии черезagent/subdirectory_hints.py)CLAUDE.md(только текущая директория).cursorrules/.cursor/rules/*.mdc(только текущая директория)
SOUL.md загружается отдельно через load_soul_md() для слота идентичности. Когда он успешно загружается, build_context_files_prompt(skip_soul=True) предотвращает его появление дважды.
Длинные файлы усекаются перед внедрением.
Индекс навыков
Система навыков добавляет компактный индекс навыков в промпт, когда доступен инструментарий навыков.
Поддерживаемые поверхности настройки промпта
Большинству пользователей следует рассматривать agent/prompt_builder.py как код реализации, а не поверхность конфигурации. Поддерживаемый путь настройки — изменять входные данные промпта, которые VibeOS уже загружает, а не редактировать Python-шаблоны на месте.
Используйте эти поверхности в первую очередь
~/.vibeos/SOUL.md— замените встроенный блок идентичности по умолчанию на свою собственную персону агента и постоянное поведение.~/.vibeos/MEMORY.mdи~/.vibeos/USER.md— предоставьте долговечные межсессионные факты и данные профиля пользователя, которые должны быть сняты в новые сессии.- Файлы контекста проекта, такие как
.vibeos.md,VIBEOS.md,AGENTS.md,CLAUDE.mdили.cursorrules— внедрите специфичные для репозитория рабочие правила. - Навыки — упакуйте переиспользуемые рабочие процессы и ссылки без редактирования основного кода промпта.
- Опциональная конфигурация системного промпта / переопределения API — добавьте текст инструкций, специфичный для развёртывания, без форка VibeOS.
- Эфемерные наложения, такие как
VIBEOS_EPHEMERAL_SYSTEM_PROMPTили сообщения prefill — добавьте руководство в рамках оборота, которое не должно становиться частью кэшированного префикса промпта.
Когда вместо этого редактировать код
Редактируйте agent/prompt_builder.py только если вы намеренно поддерживаете форк или вносите изменения в поведение для вышестоящего репозитория. Этот файл собирает инфраструктуру промпта, границы кэша и порядок внедрения для каждой сессии. Прямые правки там — это глобальные изменения продукта, а не настройка промпта для конкретного пользователя.
Другими словами:
- если вам нужна другая идентичность ассистента, редактируйте
SOUL.md - если вам нужны другие правила репозитория, редактируйте файлы контекста проекта
- если вам нужны переиспользуемые процедуры работы, добавьте или измените навыки
- если вы хотите изменить то, как VibeOS собирает промпты для всех, меняйте Python и рассматривайте это как вклад в код
Почему сборка промпта разделена именно так
Архитектура намеренно оптимизирована для:
- сохранения кэширования промптов на стороне провайдера
- избежания ненужного изменения истории
- сохранения понятной семантики памяти
- предоставления шлюзу/ACP/CLI возможности добавлять контекст без отравления постоянного состояния промпта