Конфиг и разрешения
Если AGENTS.md задает смысл и правила проекта, то opencode.json задает механику. Именно здесь определяется, какие инструкции грузятся, какие subagents доступны, как работают разрешения и где проходит граница между «агенту можно доверять» и «здесь нужен контроль».
Почему opencode.json — это control plane
В документации OpenCode прямо сказано, что конфиги объединяются, а не заменяют друг друга. Это значит, что проектный opencode.json — не просто локальная настройка отдельного разработчика, а один из главных уровней repo-level truth. Он должен описывать не личные предпочтения, а то, как OpenCode должен вести себя в рамках конкретного репозитория.
Хороший проектный конфиг обычно задает как минимум четыре вещи: набор инструкций, ограничения на skills, правила работы встроенных primary agents и общую permission policy для чувствительных действий.
Минимально полезный конфиг
Самый важный базовый шаг — подключить не только AGENTS.md, но и проектные спецификации. Иначе агент знает «правила», но не знает реальный intent и контракты.
{
"$schema": "https://opencode.ai/config.json",
"instructions": [
"AGENTS.md",
"docs/specs/*.md"
]
}
Это уже сильный старт, потому что модель получает не только описание структуры проекта, но и содержание спецификаций, лежащих рядом с кодом.
Как это сделано в репозитории-примере
{
"$schema": "https://opencode.ai/config.json",
"instructions": [
"AGENTS.md",
"docs/specs/*.md"
],
"permission": {
"skill": {
"*": "deny",
"delivery-planning": "allow",
"requirements-spec": "allow",
"dbt-modeling": "allow",
"python-etl": "allow"
}
},
"agent": {
"build": {
"permission": {
"task": {
"*": "deny",
"project-manager": "allow",
"system-analyst": "allow",
"data-engineer": "allow"
},
"bash": {
"*": "allow",
"git push*": "ask",
"docker compose down*": "ask",
"rm -rf *": "ask"
}
}
}
}
}
Этот пример хорошо показывает, что зрелый конфиг — это не только про модель или тему интерфейса. Он задает и knowledge layer, и orchestration layer, и safety layer.
Почему instructions важнее, чем кажется
Очень частая ошибка — пытаться засунуть всё знание проекта в один большой AGENTS.md. Но гораздо лучше использовать instructions как механизм композиции. Тогда AGENTS.md остается главным проектным контрактом, а спецификации, дополнительные гайды и другие durable instructions подключаются отдельно и не превращают один файл в нечитабельный монолит.
Для монорепозиториев и evolving products это особенно полезно: можно постепенно наращивать instruction layer, не ломая базовую структуру.
Разрешения: теория и практическая политика
Базовая модель разрешений в документации очень проста: allow, ask, deny. Но в реальном проекте важно решить не только «что вообще можно», а где проходит разумная граница доверия. Если всё открыто, вы быстро теряете контроль. Если всё через ask, вы получаете permission fatigue и начинаете подтверждать действия на автомате.
| Тип действий | Здоровый дефолт | Почему |
|---|---|---|
| Read/search инструменты | allow |
Без этого analysis phase становится мучительно медленным. |
| Обычные локальные правки | allow или agent-specific |
Иначе build-mode начинает вязнуть на каждом изменении. |
| Внешние или опасные bash-команды | ask / deny |
Push, destructive cleanup и остановка сервисов требуют отдельной осторожности. |
| Доступ к skills | Whitelist | Так агенту проще выбирать и меньше риск загружать неподходящие навыки. |
Паттерн: позволять широкую работу, но страховать опасные границы
В проекте-примере выбран очень практичный компромисс: bash в целом разрешён, но отдельные рискованные шаблоны идут через ask. Это хороший баланс между скоростью и контролем.
"bash": {
"*": "allow",
"git push*": "ask",
"docker compose down*": "ask",
"rm -rf *": "ask"
}
Такая схема обычно работает лучше, чем полный запрет всего. Агент не вязнет на каждом harmless действии, но чувствительные операции всё еще требуют подтверждения.
Паттерн: ограничивать task routing
Еще одна сильная идея — использовать permission.task как routing guardrail. Это позволяет не только ограничивать, кого агент может вызвать, но и делать orchestration более ясным. В результате build-agent не расползается по всем возможным ролям, а работает в рамках заданного проектом маршрута.
"task": {
"*": "deny",
"project-manager": "allow",
"system-analyst": "allow",
"data-engineer": "allow"
}
Рекомендуемые defaults для команды
- Всегда указывать
$schema. - Подключать
AGENTS.mdиdocs/specs/*.mdчерезinstructions. - Явно описывать whitelist для
permission.skill. - Переопределять
agent.build.permissionхотя бы для опасных bash-patterns. - Использовать task permissions как механизм маршрутизации, а не только как ограничение безопасности.
Чего не стоит класть в project config
Плохая идея
Секреты
Не храните API keys напрямую в opencode.json. Лучше использовать env vars или file substitution.
Плохая идея
Всё знание в одном JSON
Не превращайте конфиг в склад инструкций. Конфиг должен оркестрировать, а не заменять собой docs и правила.