O que llm-scan faz?
Este skill mapeia todos os locais de chamada de LLM e logs de uso de um repositório em work/<repo>/routes.json. É somente leitura: nunca edite, formate, faça commit ou execute nada dentro do repositório alvo.
0. configuração
- Detecte qual agente de codificação você é: Claude Code ou Codex (ou qualquer outro agente de codificação). Leia apenas o arquivo correspondente,
delegation/claude.mdoudelegation/codex.md, neste pacote. Ele informa qual etapa vai para um ajudante rápido e barato e qual fica com você. - Defina
<pack>como a pasta que contémscripts/calc.py(dois níveis acima deste arquivo) e<repo>como o nome da pasta do repositório alvo. Crie<pack>/work/<repo>/; todas as saídas vão para lá. Nunca escreva dentro do repositório alvo.
1. encontre todos os locais de chamada
Pesquise todo o repositório (pule node_modules, .venv, dist, build, .git, lockfiles). Conte todos os seguintes:
- Chamadas de SDK: qualquer chamada de biblioteca cliente que envia um prompt para um modelo (chat, messages, completions, responses, embeddings, helpers de streaming, frameworks de agente).
- Chamadas CLI via subprocesso: um agente ou modelo CLI executado a partir do código em modo não interativo (uma flag de impressão como
-p,exec,--prompt), incluindo workers aquecidos de longa duração e pipes stream-json. - Chamadas HTTP: requisições diretas para uma URL de API de modelo, um gateway, um proxy ou um endpoint auto-hospedado.
- Modelos de decisão, gate, classificador, roteador, reranker e juiz, mesmo que pequenos ou baratos. Eles também são chamadas de LLM.
- Chamadas de aquecimento, keepalive e health-check que atingem um modelo: registre-as como rotas (muitas vezes não têm uso nos logs; veja
usage_gaps). - Chamadas em testes, scripts, notebooks e cron jobs: liste-as, mas marque
"live": falsese nunca forem executadas em produção. - Chamadas de modelo não LLM (speech-to-text, text-to-speech, OCR, serviços de visão cobrados por minuto ou por imagem): estão fora do escopo para precificação. Liste-as com
"kind": "non_llm"para que o relatório possa dizer que foram vistas e não precificadas.
Pesquise por imports de cliente, hostnames de API, strings model= / "model":, max_tokens, stream, cache_control e spawns de subprocesso de CLIs de modelo. Em seguida, abra cada ocorrência e leia a função ao redor dela.
2. registre cada rota
Escreva uma entrada por local de chamada. O id da rota é relative/path.ext:function_name; para um método, relative/path.ext:Class.method; use <module> se estiver no nível superior. Use a mesma grafia de id em todos os lugares (routes.json, linhas, relatório).
| campo | significado |
|---|---|
id | file:function ou file:Class.method |
kind | sdk, cli, http, non_llm |
provider | conforme mostrado no código, senão null |
model | a string do modelo exatamente como escrita, ou a chave de configuração / variável de ambiente que a define (então também model_source). Quando o modelo de uma rota varia em tempo de execução, escreva "varies" e nomeie a configuração ou fonte em model_source |
streaming | true / false / null |
cache_markers | explicit (o código marca pontos de cache de prompt), implicit (sem marcas, mas um prefixo estável, processo aquecido ou padrão do provedor pode armazená-lo em cache), none (nada sugere cache), unknown |
max_tokens | o número, ou null se não definido |
retries | contagem e onde (padrão do SDK, wrapper, loop), ou 0 |
user_waits | true se uma pessoa está esperando pela resposta (chat, voz, UI ao vivo); false para batch, background, cron; "unknown" se não for possível determinar |
decision_model | true para gates, roteadores, classificadores, juízes |
decision_shaped | true se a resposta é um veredito pequeno que alimenta um ramo de código (um enum, um booleano, um rótulo, uma pontuação) e a rota é executada por evento ou por item; false se a resposta é texto livre ou saída estruturada longa; "unknown" se não for possível determinar. Registre para cada rota; o calc também detecta a partir dos logs (p50 de saída de 5 tokens ou menos em 50+ chamadas) |
tools | onde as definições de ferramenta ou função são construídas e enviadas (file:function, e quantas são enviadas por chamada se o código mostrar), ou null se a rota não envia nenhuma. Apenas fatos; os números vêm dos logs |
live | true; false se apenas em teste; "unknown" se não for possível determinar |
stateless | true se cada chamada é independente (um gate ou classificador por evento que não envia turnos anteriores); false se uma conversa ou memorando cresce entre chamadas; "unknown" |
notes | uma linha curta, apenas fatos observados |
Use null (ou "unknown" onde a tabela permitir) quando não for possível determinar. Nunca adivinhe um valor.
3. encontre os logs de uso
Encontre onde o aplicativo já registra o uso (tokens, custo, latência, tempo até o primeiro token, sucesso). Procure por arquivos de log, JSONL, CSV, SQLite ou tabelas de banco de dados, chamadas de tracing e métricas e campos de uso do provedor salvos de respostas. Para cada um, registre:
- o caminho ou tabela e o formato;
- os NOMES dos campos, nunca os valores;
- se algum campo contém texto do prompt ou resposta (
has_text_fields); - quais ids de rota ele cobre.
Não abra valores de log além das primeiras linhas necessárias para aprender os nomes dos campos, e não copie nenhum texto deles.
Observe também, apenas pelo NOME do campo, se os logs registram definições de ferramentas ou uso de ferramentas por chamada (uma contagem de ferramentas enviadas, o tamanho das definições de ferramentas em tokens, uma contagem de chamadas de ferramenta na resposta); o llm-capture transforma esses em tools_defined, tool_schema_tokens e tool_calls. Se os logs não os tiverem, mencione isso em usage_gaps.
Registre também usage_gaps: notas curtas e simples (uma linha cada, apenas fatos) onde as chamadas ocorrem mas os logs não carregam uso de tokens ou os números registrados não podem ser confiados como estão. Exemplos: "chamadas de aquecimento na rota X são registradas sem uso", "custo registrado é um total acumulado por processo", "rota Y não é registrada de forma alguma". Contagens são bem-vindas ("visto N vezes") quando você as lê apenas a partir de nomes e contagens de campos.
4. escreva routes.json
Escreva <pack>/work/<repo>/routes.json:
{
"repo": "<repo>",
"root": "<caminho absoluto do repositório alvo>",
"scanned": "<YYYY-MM-DD>",
"routes": [
{"id": "path/file.py:Class.method", "kind": "cli", "provider": null, "model": "<string>", "model_source": null,
"streaming": true, "cache_markers": "implicit", "max_tokens": null, "retries": 0,
"user_waits": true, "decision_model": false, "decision_shaped": false, "tools": null, "live": true, "stateless": false, "notes": ""},
{"id": "path/stt.py:transcribe", "kind": "non_llm", "live": true, "notes": "speech-to-text, não precificado"}
],
"usage_logs": [
{"path": "<caminho relativo ou tabela>", "format": "jsonl", "fields": ["<apenas nomes>"],
"has_text_fields": true, "covers_routes": ["path/file.py:Class.method"]}
],
"usage_gaps": ["<uma nota curta cada>"]
}
5. finalize
Informe ao usuário em algumas linhas quantas rotas você encontrou, quais são voltadas ao usuário, quais logs de uso existem e quaisquer usage_gaps. Não estime custos ou velocidades aqui; números vêm apenas do scripts/calc.py.
Em seguida, execute o próximo skill, llm-capture.