feat(config): per-agent models and task delegation for subagents #97

Closed
opened 2026-08-17 04:32:09 +03:00 by slaid098 · 0 comments
Owner

Контекст

Зачем: subagent'ы наследуют модель вызывающей сессии — нельзя оптимизировать стоимость/качество (быстрая flash для простых задач, мощная pro для кода и ревью). Плюс найден конфликт правил: AGENTS.md предписывает main-chat оркестратору создавать плановые issues сам («Исключение: плановые issues создаёт main-chat оркестратор сам, последовательными вызовами create-issue»), а скиллы feature-spec и issue запрещают оркестратору это и делегируют subagent'у.
Контекст: секция agent в .opencode/opencode.json (строки ~410–440) содержит только steps и tools — полей model и permission.task нет. Встроенный провайдер ollama-cloud (проверено opencode models, версия 1.18.18) уже содержит deepseek-v4-flash и deepseek-v4-pro — регистрация в provider не нужна. Субагентам task tool фактически запрещён (дефолт opencode: task: deny, подтверждено логами).

Задача

  1. .opencode/opencode.json, секция agent (строки ~410–440):
    • Добавить model шести агентам: plan, explore, scout, memory-syncer → "model": "ollama-cloud/deepseek-v4-flash"; general, reviewer → "model": "ollama-cloud/deepseek-v4-pro".
    • Добавить general и reviewer: "permission": { "task": { "*": "deny", "explore": "allow", "scout": "allow" } } (glob-паттерны, последний матч побеждает).
    • memory-syncer — permission.task НЕ добавлять (deny по умолчанию остаётся).
    • Существующие steps: 150 и tools-блоки НЕ менять.
  2. tests/test_permissions.py (там уже есть _load_config()["agent"]["general"]["tools"], строка ~333, и steps == 150, строка ~338) — добавить 4 теста:
    • test_agents_have_models — у всех 6 агентов есть model, формат ^[a-zA-Z0-9._-]+\/[a-zA-Z0-9:._-]+$
    • test_agent_models_exact — точные значения: flash у plan/explore/scout/memory-syncer, pro у general/reviewer
    • test_general_reviewer_task_permissions — у general и reviewer permission.task == {"*": "deny", "explore": "allow", "scout": "allow"}
    • test_memory_syncer_no_task — у memory-syncer нет permission.task
  3. .opencode/skills/configure-opencode/SKILL.md, секция 6 (Permissions) — задокументировать permission.task: glob-семантика, последний матч побеждает, "*": "deny" первым (сейчас описаны только read/bash).
  4. .opencode/skills/feature-spec/SKILL.md — в секции «## 4. Handoff» и в разделе «Правила» заменить «Не создавай issues сам — только планируй. Issues через issue скилл» на: после согласования плана (юзер сказал «создай issue») оркестратор создаёт issue сам, последовательными вызовами create-issue (выход спеки = body, 8 секций 1:1) — согласовано с исключением в AGENTS.md.
  5. .opencode/skills/issue/SKILL.md — разделы «Использование subagent для создания issue» и «Батчевое создание»: плановые issues (после согласованного плана, декомпозиция) создаёт main-chat оркестратор сам, последовательными вызовами create-issue; subagent-делегирование оставить только для задач, найденных в ходе исполнения (bug-discovery: «Найденное в ходе исполнения — создаёт сабагент сам»). Убрать категоричное «Main agent НЕ запускает create-issue».

Контракты

  • Model ID: ollama-cloud/deepseek-v4-flash (plan/explore/scout/memory-syncer), ollama-cloud/deepseek-v4-pro (general/reviewer). Обе — встроенные в opencode, в provider НЕ регистрировать. deepseek-v4-flash:0731 (с суффиксом) НЕ использовать.
  • permission.task — объект glob→action, правила оцениваются по порядку, последний матч побеждает ("*": "deny" первым, конкретные агенты после).
  • Все поля — только в opencode.json секции agent, НЕ в frontmatter .md-агентов (ADR-020: unknown top-level поля frontmatter форвардятся провайдеру и ломают строгие провайдеры).

Инварианты

  • memory-syncer остаётся без permission.task.
  • Существующие tools/steps агентов не меняются.
  • «Не запускай /run-pipeline — юзер делает это сам» и «Не создавай файлы» в feature-spec остаются.
  • Путь bug-discovery (сабагент создаёт issue сам) в issue-скилле сохраняется.
  • Модели не дублируются в provider-секцию.

Граничные случаи

  • Bare-модель deepseek-v4-flash (без :0731) резолвится встроенным реестром opencode; кастомные options из конфига (reasoningEffort: max, лимиты 200k/65k) к ней не применяются — ожидаемо для простых задач (explore/дистилляция/планирование).
  • После рестарта контейнера — smoke-тест: вызвать explore и general, в ~/.local/share/opencode/log/opencode.log проверить modelID=deepseek-v4-flash у explore и deepseek-v4-pro у general.
  • Если агент указан с неизвестной моделью — opencode упадёт при старте/вызове; критерии приемки покрывают это точными тестами.

Влияние на связанные компоненты

  • tests/test_permissions.py — paired update (пункт 2 Задачи).
  • .opencode/skills/configure-opencode/SKILL.md — paired update (пункт 3 Задачи).
  • Oracle-скрипты (pipeline-status.py, spec-status.py, project-status.py, check-permissions.py — читает только permission.bash) — не затронуты, секцию agent не читают.
  • TS-инструменты (.opencode/tools/*.ts) — не затронуты (конфиг не читают).
  • tests/test_agent_frontmatter.py — не затронут (поля добавляются в opencode.json, не в .md frontmatter).
  • CI (.github/workflows/ci.yml, permissions-check.yml) — триггерятся автоматически, пройдут.
  • Агентские .md (reviewer.md, memory-syncer.md), AGENTS.md, skills (run-pipeline, audit, bug-discovery) — не затронуты. Явного запрета subagent→subagent в правилах нет.

Вне scope

  • Модель main chat (оркестратор выбирает в UI вручную).
  • Модель эмбеддингов RAG (OPENAI_EMBEDDING_MODEL) — отдельный контур.
  • Регистрация deepseek-v4-flash/deepseek-v4-pro в provider.ollama-cloud.
  • Тесты на markdown-скиллы (не нужны — инструкции, не код).
  • Модели для встроенных системных агентов (compaction/title/summary).

Критерии приемки

  • opencode.json содержит model у 6 агентов: flash у plan/explore/scout/memory-syncer, pro у general/reviewer.
  • general и reviewer имеют permission.task == {"*": "deny", "explore": "allow", "scout": "allow"}; у memory-syncer permission.task нет.
  • Существующие steps: 150 и tools-блоки не изменены.
  • uv run pytest tests/test_permissions.py — зелёный, 4 новых теста проходят.
  • feature-spec/SKILL.md и issue/SKILL.md говорят: плановые issues создаёт оркестратор сам; bug-issues — сабагент (bug-discovery).
  • configure-opencode/SKILL.md секция 6 документирует permission.task (glob, последний матч побеждает).
  • После синка (commit+push → git pull на хосте → docker compose restart opencode): smoke-тест — explore работает, в логах modelID=deepseek-v4-flash у explore и deepseek-v4-pro у general.
  • CI (.github/workflows/ci.yml, permissions-check.yml) зелёный.
## Контекст Зачем: subagent'ы наследуют модель вызывающей сессии — нельзя оптимизировать стоимость/качество (быстрая flash для простых задач, мощная pro для кода и ревью). Плюс найден конфликт правил: AGENTS.md предписывает main-chat оркестратору создавать плановые issues сам («Исключение: плановые issues создаёт main-chat оркестратор сам, последовательными вызовами create-issue»), а скиллы feature-spec и issue запрещают оркестратору это и делегируют subagent'у. Контекст: секция `agent` в `.opencode/opencode.json` (строки ~410–440) содержит только `steps` и `tools` — полей `model` и `permission.task` нет. Встроенный провайдер `ollama-cloud` (проверено `opencode models`, версия 1.18.18) уже содержит `deepseek-v4-flash` и `deepseek-v4-pro` — регистрация в `provider` не нужна. Субагентам task tool фактически запрещён (дефолт opencode: `task: deny`, подтверждено логами). ## Задача 1. `.opencode/opencode.json`, секция `agent` (строки ~410–440): - Добавить `model` шести агентам: `plan`, `explore`, `scout`, `memory-syncer` → `"model": "ollama-cloud/deepseek-v4-flash"`; `general`, `reviewer` → `"model": "ollama-cloud/deepseek-v4-pro"`. - Добавить `general` и `reviewer`: `"permission": { "task": { "*": "deny", "explore": "allow", "scout": "allow" } }` (glob-паттерны, последний матч побеждает). - `memory-syncer` — `permission.task` НЕ добавлять (deny по умолчанию остаётся). - Существующие `steps: 150` и `tools`-блоки НЕ менять. 2. `tests/test_permissions.py` (там уже есть `_load_config()["agent"]["general"]["tools"]`, строка ~333, и `steps == 150`, строка ~338) — добавить 4 теста: - `test_agents_have_models` — у всех 6 агентов есть `model`, формат `^[a-zA-Z0-9._-]+\/[a-zA-Z0-9:._-]+$` - `test_agent_models_exact` — точные значения: flash у plan/explore/scout/memory-syncer, pro у general/reviewer - `test_general_reviewer_task_permissions` — у general и reviewer `permission.task == {"*": "deny", "explore": "allow", "scout": "allow"}` - `test_memory_syncer_no_task` — у memory-syncer нет `permission.task` 3. `.opencode/skills/configure-opencode/SKILL.md`, секция 6 (Permissions) — задокументировать `permission.task`: glob-семантика, последний матч побеждает, `"*": "deny"` первым (сейчас описаны только read/bash). 4. `.opencode/skills/feature-spec/SKILL.md` — в секции «## 4. Handoff» и в разделе «Правила» заменить «Не создавай issues сам — только планируй. Issues через `issue` скилл» на: после согласования плана (юзер сказал «создай issue») оркестратор создаёт issue сам, последовательными вызовами `create-issue` (выход спеки = body, 8 секций 1:1) — согласовано с исключением в AGENTS.md. 5. `.opencode/skills/issue/SKILL.md` — разделы «Использование subagent для создания issue» и «Батчевое создание»: плановые issues (после согласованного плана, декомпозиция) создаёт main-chat оркестратор сам, последовательными вызовами `create-issue`; subagent-делегирование оставить только для задач, найденных в ходе исполнения (bug-discovery: «Найденное в ходе исполнения — создаёт сабагент сам»). Убрать категоричное «Main agent НЕ запускает `create-issue`». ## Контракты - Model ID: `ollama-cloud/deepseek-v4-flash` (plan/explore/scout/memory-syncer), `ollama-cloud/deepseek-v4-pro` (general/reviewer). Обе — встроенные в opencode, в `provider` НЕ регистрировать. `deepseek-v4-flash:0731` (с суффиксом) НЕ использовать. - `permission.task` — объект glob→action, правила оцениваются по порядку, последний матч побеждает (`"*": "deny"` первым, конкретные агенты после). - Все поля — только в `opencode.json` секции `agent`, НЕ в frontmatter `.md`-агентов (ADR-020: unknown top-level поля frontmatter форвардятся провайдеру и ломают строгие провайдеры). ## Инварианты - `memory-syncer` остаётся без `permission.task`. - Существующие `tools`/`steps` агентов не меняются. - «Не запускай /run-pipeline — юзер делает это сам» и «Не создавай файлы» в feature-spec остаются. - Путь bug-discovery (сабагент создаёт issue сам) в issue-скилле сохраняется. - Модели не дублируются в `provider`-секцию. ## Граничные случаи - Bare-модель `deepseek-v4-flash` (без `:0731`) резолвится встроенным реестром opencode; кастомные options из конфига (`reasoningEffort: max`, лимиты 200k/65k) к ней не применяются — ожидаемо для простых задач (explore/дистилляция/планирование). - После рестарта контейнера — smoke-тест: вызвать explore и general, в `~/.local/share/opencode/log/opencode.log` проверить `modelID=deepseek-v4-flash` у explore и `deepseek-v4-pro` у general. - Если агент указан с неизвестной моделью — opencode упадёт при старте/вызове; критерии приемки покрывают это точными тестами. ## Влияние на связанные компоненты - `tests/test_permissions.py` — paired update (пункт 2 Задачи). - `.opencode/skills/configure-opencode/SKILL.md` — paired update (пункт 3 Задачи). - Oracle-скрипты (`pipeline-status.py`, `spec-status.py`, `project-status.py`, `check-permissions.py` — читает только `permission.bash`) — не затронуты, секцию `agent` не читают. - TS-инструменты (`.opencode/tools/*.ts`) — не затронуты (конфиг не читают). - `tests/test_agent_frontmatter.py` — не затронут (поля добавляются в opencode.json, не в `.md` frontmatter). - CI (`.github/workflows/ci.yml`, `permissions-check.yml`) — триггерятся автоматически, пройдут. - Агентские `.md` (`reviewer.md`, `memory-syncer.md`), AGENTS.md, skills (run-pipeline, audit, bug-discovery) — не затронуты. Явного запрета subagent→subagent в правилах нет. ## Вне scope - Модель main chat (оркестратор выбирает в UI вручную). - Модель эмбеддингов RAG (`OPENAI_EMBEDDING_MODEL`) — отдельный контур. - Регистрация `deepseek-v4-flash`/`deepseek-v4-pro` в `provider.ollama-cloud`. - Тесты на markdown-скиллы (не нужны — инструкции, не код). - Модели для встроенных системных агентов (compaction/title/summary). ## Критерии приемки - [ ] `opencode.json` содержит `model` у 6 агентов: flash у plan/explore/scout/memory-syncer, pro у general/reviewer. - [ ] `general` и `reviewer` имеют `permission.task == {"*": "deny", "explore": "allow", "scout": "allow"}`; у `memory-syncer` `permission.task` нет. - [ ] Существующие `steps: 150` и `tools`-блоки не изменены. - [ ] `uv run pytest tests/test_permissions.py` — зелёный, 4 новых теста проходят. - [ ] `feature-spec/SKILL.md` и `issue/SKILL.md` говорят: плановые issues создаёт оркестратор сам; bug-issues — сабагент (bug-discovery). - [ ] `configure-opencode/SKILL.md` секция 6 документирует `permission.task` (glob, последний матч побеждает). - [ ] После синка (commit+push → `git pull` на хосте → `docker compose restart opencode`): smoke-тест — explore работает, в логах `modelID=deepseek-v4-flash` у explore и `deepseek-v4-pro` у general. - [ ] CI (`.github/workflows/ci.yml`, `permissions-check.yml`) зелёный.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/opencode-config#97
No description provided.