API e SDKGuia
Rastreie o custo de tokens de agentes de IA em Python: usage, orçamento, parada
Registre o campo usage de cada requisição, some por tarefa e pare o agente em um orçamento em dólares. Exemplo funcional em Python para uma API compatível com OpenAI.

Nesta página
Seu agente rodou por dez minutos e a conta é maior que a tarefa. Para ver por quê, leia o objeto usage em cada resposta da API, some por tarefa e multiplique pelo preço do modelo por 1M de tokens. Para limitar, compare esse total acumulado com um orçamento após cada passo e pare o loop quando for ultrapassado. Abaixo está uma pequena classe Python que faz exatamente isso.
O exemplo usa o endpoint compatível com OpenAI https:/ e o id do modelo deepseek- (contexto de 380K, até 32.768 tokens de saída por resposta). Se você quer estimar uma execução antes de iniciá-la, isso é outra tarefa, e Como estimar o custo de um agente de IA cobre isso. Este artigo é sobre medir e limitar enquanto a execução está acontecendo.
Onde estão os números: o objeto usage#
Toda conclusão de chat não-streaming retorna com um objeto usage. A referência da API do DeepSeek (verificada em 26 de outubro de 2026) lista estes campos:
prompt_tokens— tudo que você enviou desta vez: prompt de sistema, histórico, resultados de ferramentas.completion_— o que o modelo escreveu de volta.tokens total_tokens— os dois somados.
O DeepSeek também documenta extras opcionais: prompt_ e prompt_ (eles somam prompt_tokens), e completion_ para modelos de raciocínio. A página não mostra data de publicação, e esses extras são extensões do formato OpenAI, então o código abaixo os trata como opcionais e depende apenas dos dois primeiros campos.
Por que registrar cada passo e não apenas o último? Porque um agente reenvia seu contexto crescente a cada vez. O passo 1 pode enviar 2.000 tokens de entrada, o passo 30 pode enviar 9.000, e a conta é a soma de todos eles. O motivo é explicado em por que um chat longo custa mais, e a divisão entrada/saída em tokens de entrada vs saída.
Um medidor que para o agente#
Aqui está tudo: um medidor que soma tokens, imprime uma linha por passo e lança um erro quando o orçamento é ultrapassado, além de um loop de agente simples em volta dele. Instale o SDK com pip install openai e coloque sua chave em CHEAPTOKENS_.
import os
from openai import OpenAI
client = OpenAI(
base_url='https://api.cheaptokens.dev/v1',
api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'deepseek-ai/DeepSeek-V4-Flash-0731'
# example prices, USD per 1M tokens: use the current ones from the pricing table
PRICE_IN = 0.10
PRICE_OUT = 0.40
class BudgetExceeded(Exception):
pass
class TaskMeter:
def __init__(self, budget_usd):
self.budget = budget_usd
self.steps = 0
self.tokens_in = 0
self.tokens_out = 0
self.reasoning = 0
@property
def cost(self):
return (self.tokens_in * PRICE_IN + self.tokens_out * PRICE_OUT) / 1_000_000
def add(self, usage):
self.steps += 1
self.tokens_in += usage.prompt_tokens
self.tokens_out += usage.completion_tokens
details = getattr(usage, 'completion_tokens_details', None)
self.reasoning += getattr(details, 'reasoning_tokens', 0) or 0
print(f'step {self.steps}: in={usage.prompt_tokens} '
f'out={usage.completion_tokens} task=${self.cost:.4f}')
if self.cost > self.budget:
raise BudgetExceeded(
f'budget ${self.budget:.2f} crossed at step {self.steps}: '
f'${self.cost:.4f}')
def run_task(goal, budget_usd=0.50, max_steps=40):
meter = TaskMeter(budget_usd)
messages = [
{'role': 'system', 'content': 'Work step by step. Reply DONE when finished.'},
{'role': 'user', 'content': goal},
]
for _ in range(max_steps):
resp = client.chat.completions.create(
model=MODEL, messages=messages, max_tokens=1024)
meter.add(resp.usage) # log first, then decide
reply = resp.choices[0].message.content or ''
messages.append({'role': 'assistant', 'content': reply})
if 'DONE' in reply:
break
messages.append({'role': 'user', 'content': 'Continue.'})
return meter
try:
meter = run_task('Summarise the main risks of a database migration.')
print(f'finished: {meter.steps} steps, ${meter.cost:.4f}')
except BudgetExceeded as err:
print('stopped:', err)Três escolhas ali valem a pena copiar.
Registre antes de decidir. meter.add registra o passo primeiro e só então verifica o orçamento, então uma execução interrompida ainda deixa um rastro completo. A verificação acontece após a chamada que cruzou a linha, então você pode ultrapassar em no máximo um passo. max_tokens=1024 limita a saída desse último passo.
Duas paradas rígidas, não uma. max_steps captura um agente que faz loop sem gastar muito; o orçamento em dólares captura um que gasta muito por passo. Você quer ambos.
Preços vivem em um só lugar. PRICE_IN e PRICE_OUT são números de exemplo. Copie os valores atuais para o seu modelo da página de preços; agora mesmo o DeepSeek-V4-Flash é $0.015 por 1M de tokens de entrada e $0.10 por 1M de tokens de saída.
Quanto soma uma execução de 40 passos#
Digamos que seu agente leva 40 passos, e como o contexto cresce, um passo médio envia 6.000 tokens de entrada e recebe 400 tokens de volta. Isso é 40 × 6.000 = 240.000 tokens de entrada e 40 × 400 = 16.000 tokens de saída para a tarefa.

No DeepSeek-V4-Flash isso custa $0.0052. A tabela executa a mesma carga de trabalho nos outros modelos e coloca o preço de referência do OpenRouter ao lado do nosso:
| Modelo | Entrada $/1M | Saída $/1M | Custo | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.0054 | $0.0111 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0052 | $0.0139 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.0144 | $0.0912 |
240.000 tokens de entrada e 16.000 tokens de saída no total. Os preços por 1M de tokens são atuais e mudam junto com nossas tarifas; a coluna OpenRouter mostra preços de referência para a mesma carga de trabalho.
No total, com entrada e saída contadas juntas, o DeepSeek-V4-Flash sai mais barato que o OpenRouter para esta tarefa. Observe também onde estão os tokens: 240.000 dos 256.000 são de entrada. O contexto que seu agente carrega junto é a conta, e é por isso que o número de in= por passo no seu log é o que deve ser observado. Um orçamento de $0,50 por tarefa no exemplo acima é um limite para uma execução descontrolada, não uma meta.
Trocar de modelo significa apenas mudar MODEL. Escolha o id na documentação do CheapTokens: os nomes diferem entre provedores, e um id curto de um rótulo de preço não funcionará na API. Para loops longos de agente, o DeepSeek-V4-Flash tem um preço a qualquer hora do dia, então uma tarefa custa o mesmo ao meio-dia e às 3 da manhã. Veja a página do DeepSeek para seus limites.
Quando o modelo está pensando#
Se uma resposta for muito mais longa em tokens do que o texto que você vê, olhe reasoning_tokens. Tokens de raciocínio contam como saída, então um passo com muito raciocínio pode produzir muito mais tokens de saída do que o texto visível sugere, e eles são cobrados como saída. O medidor acima os coleta em meter.reasoning quando a API retorna o campo e o deixa em 0 quando não retorna, então nunca quebra por uma chave ausente. Imprima-o ao lado de out= se quiser ver quanto da saída foi raciocínio. Esforço de raciocínio e tokens de pensamento explica por quê.
Streaming: o usage vem por último#
Se seu agente faz streaming, não há usage nos chunks normais. No formato OpenAI você o solicita com stream_. A referência do DeepSeek (verificada em 26 de outubro de 2026) diz que a opção funciona apenas junto com stream=True (caso contrário, a API responde 400), que usage é null em todos os chunks menos um, e que o último chunk antes de data: [DONE] carrega os totais de toda a requisição. Então, em um loop de streaming, chame meter.add uma vez, no chunk onde usage não estiver vazio. O loop não-streaming acima é o lugar mais simples para começar; streaming em Python tem o loop em si.
Se os números parecerem errados#
usageé None. Você está fazendo streaming seminclude_usage. Adicione-o, ou mude para uma chamada não-streaming.- O total é menor que a queda do saldo. Verifique se toda chamada passa pelo medidor: retentativas, uma chamada de sumarização ou uma chamada de escolha de ferramenta feita fora de
run_tasksão fáceis de esquecer. Envolvaclient.em uma função e encaminhe tudo por ela.chat. completions. create - O custo por passo continua subindo. Isso é normal para um loop que anexa tudo a
messages. Corte saídas antigas de ferramentas ou resuma o histórico; saída de ferramenta fora do contexto mostra a ideia. BudgetExceededdispara no passo 2. Seu orçamento é menor que um passo. Verifique sePRICE_INé por 1M de tokens, não por 1K.
Para armazenar os números, escreva meter.steps, meter.tokens_in, meter.tokens_out e meter.cost como uma linha JSON por tarefa. Uma semana dessas linhas lhe diz os tokens reais por passo para o seu agente, que é o número a colocar em toda estimativa depois. Modelos, preços e a primeira requisição estão na documentação; chamadas de ferramentas são abordadas em function calling em Python.



