Buffer .brainstorm/interns.md → .archive/2026-05-05-interns.md after
ingesting concepts/interns-design.md into claude-skills (commits
30c329fd+035e4dd5+3deaa357) and creating 4 follow-up tasks across
claude-skills (interns-skills-mvp, ready), common (interns-mcp-mvp ready;
unify-llm-secrets blocked), and projects-meta-mcp (migrate-to-common-lib
blocked).
Domain spec for delegated cheap-LLM workers via local MCP server. Three
layers (config / runtime / skills), MVP catalog of two interns
(bulk_text_read + transcript_distill) on DeepSeek Flash via ollama_cloud.
Permission model mirrors project-discipline Rule 4 (per-session grant);
always-ask paths enforced server-side. Lives at .common/lib/interns-mcp/.
Target promote: claude-skills wiki + tasks via meeting-room-promote-brainstorm.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add .gitignore (settings.local.json)
- Drop stale "before self-promotion" pointer; keep architecture link
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 14:56:19 +03:00
4 changed files with 306 additions and 2 deletions
Каталог специализированных «интернов» — дешёвых LLM/тулзов, которым Claude Code делегирует bulk I/O и предсказуемую генерацию, чтобы экономить твою Anthropic квоту. Доступ — через локальный MCP-сервер. Использование защищено per-session permission grant (зеркало `project-discipline` Rule 4). Каталог расширяется без переписывания скила.
## Context
Triggered by Reddit thread (May 2026) и Medium-статьёй того же автора, обе в `.wiki/raw/research/tokens-economy/`. Pattern: `expensive manager (Claude) + cheap intern (DeepSeek/Kimi/Ollama)`. ~23× cheaper end-to-end на summarization задачах, ~125× per-call на bulk read. Без этого OP упирался в weekly Pro limit к среде.
Локальный сигнал из selected line `.brainstorm/modulair-rag.md:134` — `Marker лучше PDF, Repomix лучше код, Firecrawl лучше JS-сайты` — определил выбор архитектуры (b) специализированных интернов вместо одного universal cheap-LLM.
Слои ортогональны. Добавить интерна = одна запись в config + один файл в `interns/`. Skills и setup-flow не трогаются.
## MVP catalog
| ID | Описание | Endpoint | Модель | Когда вызывать |
|---|---|---|---|---|
| `bulk_text_read` | Прочитать N файлов и ответить на вопрос | `ollama_cloud` | `deepseek-v4-flash` | Когда Claude собирался прочесть 3+ файлов или один >400 строк ради контекста |
| `transcript_distill` | Сжать session-transcript / лог в action-list | `ollama_cloud` | `deepseek-v4-flash` | Перед обновлением `.wiki/log.md` или summary документации по сессии |
Оба на одном endpoint и модели — демонстрируют разделение **по классу задачи**, не по провайдеру. Дальнейшие интерны (PDF/web/code) — следующий релиз.
## Layer 1 — Config
`.common/config/interns/config.yaml`:
```yaml
endpoints:
ollama_cloud:
base_url:https://ollama.com/v1
api_key_env:OLLAMA_CLOUD_API_KEY
request_defaults:
extra_body:
reasoning:{enabled:false}# обязательно для DeepSeek V4 — иначе max_tokens уходит в silent thinking
interns:
bulk_text_read:
description:"Read N files and answer a focused question. Returns concise summary."
endpoint:ollama_cloud
model:deepseek-v4-flash
max_tokens:4096
temperature:0.2
system_prompt:|
You are a careful reader. Answer ONLY what the user asks, citing
file:line refs. Do not hallucinate file contents. If unsure, say so.
transcript_distill:
description:"Compress a session transcript/log into a structured action-list."
endpoint:ollama_cloud
model:deepseek-v4-flash
max_tokens:2048
temperature:0.1
system_prompt:|
Extract action items, decisions, and unresolved questions from the
transcript. Output structured markdown sections. Be terse.
```
`.common/secrets/interns.env` (gitignored):
```dotenv
OLLAMA_CLOUD_API_KEY=...
```
Сервер на startup: загружает `.env` через `python-dotenv` → читает `config.yaml` → берёт ключ из `os.environ[api_key_env]`. Если ключа нет — `setup-interns` интерактивно спрашивает и пишет в `.env` (с preview-confirmation gate перед записью).
## Layer 2 — MCP server
`.common/lib/interns-mcp/`:
```
interns-mcp/
├── pyproject.toml
├── README.md
├── interns_mcp/
│ ├── __init__.py
│ ├── server.py — FastMCP app, tool registration
│ ├── registry.py — load config.yaml → list of Intern objects
-На startup `registry.load()` проходит config, для каждого интерна делает `@mcp.tool()`с typed signature.
- Tool name = `<intern_id>` — Claude harness сформирует `mcp__interns__<id>` (где `interns` — имя сервера в `~/.claude.json`).
- Каждый tool принимает `paths: list[str]`, `question: str`, опционально `max_tokens: int`.
- **MCP-сервер сам читает файлы из переданных `paths`** — Claude передаёт пути, не содержимое. Это критично для safety: сервер видит пути и применяет always-ask matcher до того как файл уйдёт в endpoint. Если бы Claude слал content, политика могла бы быть обойдена случайно (Claude прочитал `.env`, переслал содержимое — поздно).
- Persistent HTTP client per-endpoint — для prefix-cache discount если endpoint его поддерживает (OpenRouter да, Ollama Cloud TBD).
**Safety enforcement:**`safety.py` проверяет каждый input `path` против always-ask glob-списка. Match → возвращает `BlockedByPolicy` объект с указанием matched-pattern; Claude получает structured ответ и сам спрашивает пользователя. Безопасность на стороне сервера — Claude может «забыть» политику в длинной сессии, MCP не забудет.
**Cross-platform:** Python 3.11+. Установка `pip install -e .common/lib/interns-mcp/`. Запуск как stdio: `python -m interns_mcp.server`. Без bash/PowerShell зависимостей в hot path.
## Layer 3 — Skills
Два скила, по prior art (`setup-context7` + `using-context7`, `setup-projects-meta` + `using-projects-meta`).
### setup-interns (v0.1.0)
**When:** «set up interns», «настрой интернов», «install interns», или когда `mcp__interns__*` отсутствуют в сессии где они нужны.
**Steps:**
1. Проверить `.common/lib/interns-mcp/` существует. Если нет — инициализировать pустой через template (TBD: см. open question про source repo).
2.`pip install -e .common/lib/interns-mcp/` через активный Python interpreter.
3. Прочитать `.common/config/interns/config.yaml`, для каждого `endpoint.<name>.api_key_env` проверить наличие в `.common/secrets/interns.env`. Отсутствующие — спросить интерактивно, preview перед записью, write.
4. Зарегистрировать `mcpServers.interns` в `~/.claude.json`:
```json
"interns": {
"command": "python",
"args": ["-m", "interns_mcp.server"]
}
```
Путь к Python — через `shutil.which("python")` или `where`/`which` в зависимости от платформы.
5. Попросить пользователя перезапустить Claude Code.
**Migration mode:** detect устаревший layout (например, переезд с `~/.local/interns-mcp/` если когда-то такой был) и предложить миграцию.
### using-interns (v0.1.0)
**When:** активируется триггером `delegate to interns when allowed` в `CLAUDE.md`. Также явные команды: «use interns», «delegate this to an intern».
**Policy:**
1. **Старт сессии = ask-mode.** Перед первым вызовом `mcp__interns__*` Claude спрашивает:
> «Я бы делегировал чтение `<files>` интерну `bulk_text_read` (DeepSeek Flash, ~$0.002 за вызов). Ок?»
2. **Conversational grant.**
- «разреши интернов» / «allow interns» / «use interns» → grant до конца сессии.
- **Любой путь, который Claude в текущей сессии прочитал из такого пути и теперь хочет передать интерну** (transitive — нельзя обойти, прочитав файл сам и переслав содержимое).
2. **Добавить запись** в `.common/config/interns/config.yaml` под `interns:`:
```yaml
pdf_read:
description: "Extract text from PDF (tables, formulas)."
endpoint: null # local subprocess, нет endpoint
# OR:
# endpoint: ollama_cloud
# model: deepseek-v4-flash
max_tokens: 8192
```
3. **(Если новый endpoint)** — добавить в `endpoints:` секцию + ключ в `interns.env`.
4. **Зарегистрировать tool в `server.py`** (для MVP — explicit, см. open question про auto-discovery):
```python
from interns_mcp.interns.pdf_read import PdfRead
register_tool(mcp, PdfRead())
```
5. **Restart Claude Code** — новый MCP tool появится как `mcp__interns__pdf_read`.
6. **Routing-подсказки** в `using-interns/SKILL.md` — добавить строку «если задача XYZ → `pdf_read`».
7. **(Опц.) Test** в `tests/test_interns_pdf_read.py`. Минимум — проверка happy-path и safety-block для `**/.env*`.
Если интерн использует local CLI (Marker, Repomix, etc.) вместо LLM API — `endpoint: null` в config, и реализация в `interns/<id>.py` вызывает subprocess.
- [ ] **`.common`:** реализовать `interns-mcp/` MVP с двумя интернами (`bulk_text_read`, `transcript_distill`); написать `README.md` с секцией «Как добавить» (см. выше); pyproject.toml + минимум tests.
- [ ] **`projects-meta-mcp`:** мигрировать в `.common/lib/projects-meta-mcp/` для унификации (отложенный backlog item, отдельная задача).
- [ ] **`.meeting-room`:** вынести `ollama_cloud.api_key` из `config/config.yaml` в `.common/secrets/interns.env` (или отдельный `.common/secrets/llm-providers.env` если хочется общую точку для всех потребителей этого endpoint — meeting-room runner + interns-mcp + future).
## Open questions
- **Source repo для `.common/lib/interns-mcp/`.** Inline в `.common` или отдельный repo на Gitea + git-subtree/submodule? Текущее склонение — inline (это часть `.common`, не самостоятельный продукт).
- **Auto-discovery интернов** в `registry.py` (через `pkgutil.iter_modules`) vs explicit `register_tool` в `server.py`. Auto проще для расширения, explicit прозрачнее. Текущее склонение — explicit для MVP.
- **Cost tracking.** В первом релизе — нет. Если оботрётся в реальной работе — добавим в `safety.py` per-call estimate из config (`tokens_used × price_per_M`) и блокировку >$X через always-ask механизм.
- **Sharing endpoint между meeting-room runner и interns-mcp.** Сейчас `.meeting-room/config/config.yaml` имеет свой `providers.ollama_cloud` с собственным ключом; interns-mcp будет иметь свой в `.common/secrets/interns.env`. Дублирование. Унификация — отдельная задача (см. action item #4).
- **Persistent prefix-cache benefit с Ollama Cloud.** Документация Ollama Cloud не подтверждает prefix-cache discount явно (как делает OpenRouter). Если измерения покажут что cache не работает — рассмотреть переключение на OpenRouter как primary endpoint.
- [.wiki/raw/research/tokens-economy/i-was-burning-through-...html](../.wiki/raw/research/tokens-economy/i-was-burning-through-claude-codes-weekly-limit-in-3-days-here-s-how-i-fixed-it.html) — Medium-статья от автора Reddit-поста.
2026-05-05 promoted modulair-rag → .wiki/concepts/modulair-rag-brainstorm-trace.md (tasks_create skipped: target projects modulair-rag/meeting-room not yet registered in projects-meta; 3 actions deferred in trace)
2026-05-05 promoted modulair-rag → .wiki/concepts/modulair-rag-brainstorm-trace.md (tasks_create skipped: target projects modulair-rag/meeting-room not yet registered in projects-meta; 3 actions deferred in trace)
2026-05-05 promoted meeting-room-redesign → .wiki/concepts/meeting-room-architecture.md (no tasks; plan executed during this same session — implementation plan archived separately as 2026-05-05-meeting-room-redesign-plan.md)
2026-05-05 promoted meeting-room-redesign → .wiki/concepts/meeting-room-architecture.md (no tasks; plan executed during this same session — implementation plan archived separately as 2026-05-05-meeting-room-redesign-plan.md)
- После self-promotion: `.wiki/concepts/meeting-room-architecture.md`
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.