20 KiB
date, status, source_brainstorm, topic, title, type, ingested_at, ingested_by, source_project
| date | status | source_brainstorm | topic | title | type | ingested_at | ingested_by | source_project |
|---|---|---|---|---|---|---|---|---|
| 2026-05-05 | design-approved | .meeting-room/.brainstorm/interns.md | interns | interns-design | concept | 2026-05-05T13:58:59.608Z | OpeItcLoc03@DESKTOP-NSEF0UK | .meeting-room |
Interns — Design Spec
Каталог специализированных «интернов» — дешёвых LLM/тулзов, которым Claude Code делегирует bulk I/O и предсказуемую генерацию, чтобы экономить Anthropic квоту. Доступ — через локальный MCP-сервер. Использование защищено per-session permission grant (зеркало project-discipline Rule 4). Каталог расширяется без переписывания скила.
Context
Triggered by Reddit thread (May 2026) и Medium-статьёй того же автора, обе в .meeting-room/.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 к среде.
Локальный сигнал из .meeting-room/.brainstorm/modulair-rag.md:134 — Marker лучше PDF, Repomix лучше код, Firecrawl лучше JS-сайты — определил выбор архитектуры (b) специализированных интернов вместо одного universal cheap-LLM.
Architecture (three layers)
┌──────────────────────────────────────────────────────────────┐
│ Layer 3 — Policy (skills) │
│ using-interns — runtime policy + permission grant │
│ setup-interns — one-time install/build/register │
│ CLAUDE.md trigger: "delegate to interns when allowed" │
└──────────────────────────────────────────────────────────────┘
↑ читает / соблюдает Claude
┌──────────────────────────────────────────────────────────────┐
│ Layer 2 — Runtime (MCP server) │
│ .common/lib/interns-mcp/ (Python + FastMCP, stdio) │
│ ├── interns_mcp/server.py — MCP entry point │
│ ├── interns_mcp/registry.py — load catalog from config │
│ ├── interns_mcp/client.py — OpenAI-compatible HTTP │
│ ├── interns_mcp/safety.py — always-ask path matcher │
│ └── interns_mcp/interns/ — one file per intern impl │
│ ├── base.py │
│ ├── bulk_text_read.py │
│ └── transcript_distill.py │
│ Tools exposed: │
│ mcp__interns__bulk_text_read │
│ mcp__interns__transcript_distill │
└──────────────────────────────────────────────────────────────┘
↑ читает on startup
┌──────────────────────────────────────────────────────────────┐
│ Layer 1 — Config (data, no code) │
│ .common/config/interns/config.yaml — endpoints + tools │
│ .common/secrets/interns.env — API ключи (gitignored) │
└──────────────────────────────────────────────────────────────┘
Слои ортогональны. Добавить интерна = одна запись в 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:
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):
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
│ ├── client.py — OpenAI-compatible HTTP client (per-endpoint, persistent)
│ ├── safety.py — always-ask path matcher
│ └── interns/
│ ├── __init__.py
│ ├── base.py — Intern protocol/dataclass
│ ├── bulk_text_read.py
│ └── transcript_distill.py
└── tests/
├── test_safety.py — path matcher tests
└── test_registry.py
Server contract:
- На 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:
- Проверить
.common/lib/interns-mcp/существует. Если нет — инициализировать пустой через template (TBD: см. open question про source repo). pip install -e .common/lib/interns-mcp/через активный Python interpreter.- Прочитать
.common/config/interns/config.yaml, для каждогоendpoint.<name>.api_key_envпроверить наличие в.common/secrets/interns.env. Отсутствующие — спросить интерактивно, preview перед записью, write. - Зарегистрировать
mcpServers.internsв~/.claude.json:Путь к Python — через"interns": { "command": "python", "args": ["-m", "interns_mcp.server"] }shutil.which("python")илиwhere/whichв зависимости от платформы. - Попросить пользователя перезапустить 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:
-
Старт сессии = ask-mode. Перед первым вызовом
mcp__interns__*Claude спрашивает:«Я бы делегировал чтение
<files>интернуbulk_text_read(DeepSeek Flash, ~$0.002 за вызов). Ок?» -
Conversational grant.
- «разреши интернов» / «allow interns» / «use interns» → grant до конца сессии.
- «отзови интернов» / «revoke interns» / «делай сам» → возврат в ask-mode.
-
Always-ask paths (даже с активным grant'ом). Полный список:
**/.env,**/.env.*— environment files со секретами**/secrets/**— каноническая папка секретов (включая.common/secrets/)**/credentials*— credentials.json и подобные**/*.key— private keys любого формата**/*.pem— PEM-encoded keys/certs**/.ssh/**— SSH ключи**/.aws/credentials,**/.aws/config— AWS credentials**/.netrc,**/.npmrc,**/.pypirc— registry credentials- Любой путь, который Claude в текущей сессии прочитал из такого пути и теперь хочет передать интерну (transitive — нельзя обойти, прочитав файл сам и переслав содержимое).
- Любой intern call с estimated cost >$0.10 (sanity-check, по-конфигу:
tokens × price).
Поведение: matched call → MCP возвращает
BlockedByPolicy{path, pattern, reason}. Claude формулирует пользователю явный вопрос: «Файл<path>matched always-ask pattern<pattern>. Передавать интерну на endpoint<endpoint>?» -
Что НЕ делегируется (рекомендации в SKILL.md, не enforced):
- Архитектурные / design-решения
- Debugging — cheap model теряет тонкие баги
- Auth / payments / PII / deletion / production data (даже если файлы не в always-ask списке)
- Final commit messages, PR descriptions
- Финальный текст ответа пользователю
-
Конец сессии = reset на ask-mode. Persistent grant отвергнут как менее безопасный (зеркало Rule 4
project-discipline). -
Routing-подсказки (внутри SKILL.md, чтобы Claude знал когда уместно):
- Файл >400 строк и не центральный для редактирования →
bulk_text_read. - ≥3 файлов нужно прочитать ради контекста →
bulk_text_read. - Перед обновлением
.wiki/log.mdили session-summary →transcript_distill.
- Файл >400 строк и не центральный для редактирования →
Bootstrap integration
project-bootstrap v1.5.0 → v1.6.0 (MINOR — capability added):
assets/CLAUDE.md.template— добавить строкуdelegate to interns when allowedсразу послеfollow project discipline.bootstrap-manifest.md— новые строкиusing-interns+setup-internsсо своими version'ами.- Step 5 commentary — параграф с объяснением (по образцу commentary для
follow project discipline). - Idempotent merge — существующие
CLAUDE.mdполучат строку при следующем bootstrap (bootstrap-claude-md-merge.mdуже умеет).
Cross-platform
| Слой | Windows | Linux | macOS |
|---|---|---|---|
.common/lib/interns-mcp/ (Python 3.11+) |
✅ | ✅ | ✅ |
.common/secrets/interns.env (python-dotenv) |
✅ | ✅ | ✅ |
setup-interns install (python -m pip) |
✅ | ✅ | ✅ |
| MCP registration — путь к Python | where python |
which python |
which python |
Always-ask matcher (pathlib.PurePath.match) |
✅ POSIX-style globs работают везде | ✅ | ✅ |
active-platform скил уже знает что показывать пользователю в каждой платформе для shell команд, никаких дублей.
Как добавить нового интерна
-
Создать файл
.common/lib/interns-mcp/interns_mcp/interns/<intern_id>.py. Шаблон:from .base import Intern, InternResponse class PdfRead(Intern): id = "pdf_read" description = "Extract text from PDF, including tables." def run(self, paths: list[str], question: str, **kwargs) -> InternResponse: # 1. Validate paths existence # 2. Optionally call safety.check(paths) — base.Intern может делать это в __call__ # 3. Call external (LLM endpoint via self.client, or local subprocess like Marker) # 4. Return InternResponse(text=..., usage={tokens_in, tokens_out, cost_usd}) ... -
Добавить запись в
.common/config/interns/config.yamlподinterns::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 -
(Если новый endpoint) — добавить в
endpoints:секцию + ключ вinterns.env. -
Зарегистрировать tool в
server.py(для MVP — explicit, см. open question про auto-discovery):from interns_mcp.interns.pdf_read import PdfRead register_tool(mcp, PdfRead()) -
Restart Claude Code — новый MCP tool появится как
mcp__interns__pdf_read. -
Routing-подсказки в
using-interns/SKILL.md— добавить строку «если задача XYZ →pdf_read». -
(Опц.) 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.
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 explicitregister_toolвserver.py. Auto проще для расширения, explicit прозрачнее. Текущее склонение — explicit для MVP. - Cost tracking. В первом релизе — нет. Если оботрётся в реальной работе — добавим в
safety.pyper-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. Дублирование. Унификация — отдельная задача. - Persistent prefix-cache benefit с Ollama Cloud. Документация Ollama Cloud не подтверждает prefix-cache discount явно (как делает OpenRouter). Если измерения покажут что cache не работает — рассмотреть переключение на OpenRouter как primary endpoint.
References
.meeting-room/.wiki/raw/research/tokens-economy/2026-05-05-i-gave-claude-code-a-$0.02call-coworker-and-stopped-hitting-pro-limits---here's-the-full-setup.md— оригинальный Reddit thread, паттерн + ~125× cost reduction цифры..meeting-room/.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-поста.claude-skills/.wiki/concepts/project-discipline-design.md— Rule 4 (commit-yes-push-no per-session) — прототип permission-grant механизма дляusing-interns.claude-skills/.wiki/concepts/skill-vs-plugin.md— обоснование bare SKILL.md.claude-skills/.wiki/concepts/repo-layout.md— конвенцииclaude-skillsrepo для скилов..meeting-room/.brainstorm/modulair-rag.md:134— selected line, повлияла на выбор архитектуры (b) специализированных интернов.