Recettes de capture

Faire entrer la consommation de tokens dans le registre, stack par stack. Le principe : capturer aux goulots d'étranglement, pas application par application. Une intégration à la frontière d'un fournisseur couvre tout ce qui se trouve derrière.

Claude Code

Intégré — rien à configurer.

npx carbon-md sync claude-code

Lit les transcriptions locales, déduplique par id de message, conserve un état pour que les relances soient sans danger. Voir sync.

LiteLLM

LiteLLM voit chaque fournisseur que vous routez à travers lui. Ajoutez un callback qui écrit une ligne d'usage :

import json, datetime, litellm

def log_usage(kwargs, response, start, end):
    u = response.usage
    with open("usage.jsonl", "a") as f:
        f.write(json.dumps({
            "ts": datetime.datetime.utcnow().isoformat() + "Z",
            "model": response.model,
            "provider": kwargs.get("custom_llm_provider"),
            "input_tokens": u.prompt_tokens,
            "output_tokens": u.completion_tokens,
        }) + "\n")

litellm.success_callback = [log_usage]
npx carbon-md ingest usage.jsonl

OpenRouter / toute API compatible OpenAI

Chaque réponse porte un objet usage. Une ligne par appel, et l'intégration est faite :

const res = await client.chat.completions.create({ model, messages });
appendFileSync("usage.jsonl", JSON.stringify({
  ts: new Date().toISOString(),
  model: res.model,
  provider: "openrouter",
  input_tokens: res.usage.prompt_tokens,
  output_tokens: res.usage.completion_tokens,
}) + "\n");

OpenTelemetry (tout agent instrumenté)

Si votre agent exporte des métriques OTel, c'est déjà fait — ingest aplatit *.token.usage et gen_ai.client.token.usage.

# configuration du collector — écrire les métriques dans un fichier lisible par carbon-md
exporters:
  file:
    path: /var/log/otel/usage.json
service:
  pipelines:
    metrics:
      receivers: [otlp]
      exporters: [file]
npx carbon-md ingest /var/log/otel/usage.json

Hermes (agent persistant auto-hébergé)

Intégré. Hermes enregistre déjà sa propre consommation de tokens par session, modèle et fournisseur de facturation — sync hermes lit cette base en lecture seule et n'ingère que ce qui est nouveau.

npx carbon-md sync hermes              # par défaut ~/.hermes/state.db
npx carbon-md sync hermes --db /chemin/vers/state.db --dry-run

Comme les compteurs de l'agent sont des totaux cumulés et non des événements en append-only, l'ingestion se fait par delta : sans danger à lancer toutes les heures depuis le cron de Hermes, en cours de session, sans double comptage. Les configurations multi-fournisseurs (Nous Research, OpenAI/Codex, Kimi, OpenRouter…) sont attribuées automatiquement par fournisseur. Voir sync pour ce qui compte et ce qui ne compte pas.

Votre propre agent

Émettez le format usage-report et ingérez-le. Quatre champs — ts, model, input_tokens, output_tokens — suffisent.

C'est aussi le chemin pour un agent qui veut rendre compte de lui-même : écrire une ligne par appel, ingérer périodiquement. Voir Pour les agents.

Compatibilité des agents

Agent / outilChemin de captureNotes
Claude Codesync claude-codenatif, livré
LiteLLMcallback → ingestcouvre tous les fournisseurs derrière lui
OpenRouterusage de la réponse → ingest
LangGraph / CrewAIcallback → ingestcallback SDK Python prévu
Tout agent OTelOTLP → ingestaucun code spécifique
Codex CLIingest depuis les logs de sessionjournalise des événements token_count dans ~/.codex/sessions
Hermessync hermesnatif — lit sa propre base d'usage, en lecture seule, par delta
CursorAdmin API uniquementpas de journal d'usage local
Assistants fermésnon capturableaucun usage exposé

Choisir une granularité

Les événements par appel donnent les ventilations les plus riches. Des lignes agrégées (par session, par modèle, par jour) conviennent aussi — le registre s'en moque, et status rapportera simplement moins d'événements, plus gros.

Éviter le double comptage

Utilisez un seul chemin par flux de trafic. Si LiteLLM journalise déjà un appel, n'ingérez pas en plus l'export du même appel par le fournisseur. Les sources sont suivies séparément dans .carbon-md/sources/, mais deux sources différentes décrivant le même trafic compteront toutes les deux.

Estimations, pas des mesures — les fourchettes sont voulues. carbon.md ne revendique jamais la neutralité carbone.

Porté par Agentic Realism · MIT · Éditer sur GitHub