Control cost
Four things drive what an agent costs: model tokens, compute for the deployed service, judge calls during evaluation, and telemetry storage. Measure first, then change one setting at a time and check with your evals that quality holds. Snippets and measurement details are ADK Python.
How do I measure token usage?#
- Cloud Trace: ADK exports a
generate_content {model.name}span for each model call. It carriesgen_ai.request.model,gen_ai.usage.input_tokensandgen_ai.usage.output_tokens. ADK Go emits the same span. The Claude template emits aninvoke_agentspan per turn instead. See ADK traces and Cloud Trace. - BigQuery Agent Analytics: the
v_llm_responseview exposesusage_prompt_tokens,usage_completion_tokens,usage_cached_tokens,usage_thinking_tokensandcontext_cache_hit_rate. The query in BigQuery Agent Analytics sums tokens per agent and model.
How do I pick a model?#
Let your evals decide. Run the same dataset against a few current Gemini models and keep the one with the best balance of eval score and cost for the task:
- Change
model=inapp/agent.py. New agents start ongemini-3.8-flash. - Run
agents-cli eval run, thenagents-cli eval compareagainst the previous results. - Weigh the scores against the token usage from the previous section.
Each agent in a multi-agent app can use its own model, so a simple routing or summarizing agent can run on a Flash-Lite model while the main agent stays on Flash or Pro. See Google models for the current lineup and the Evaluation guide for the eval loop.
How do I cut input tokens?#
Cache long, stable context. ContextCacheConfig applies to all agents in the App and is experimental. Caching starts on the second turn, so single-turn sessions are never cached. Cached context incurs storage charges (context cache overview). ADK documents caching for Python, Java and Kotlin, so it doesn't apply to Go or TypeScript agents (ADK context caching).
from google.adk.apps import App
from google.adk.agents.context_cache_config import ContextCacheConfig
app = App(
name="app",
root_agent=root_agent,
context_cache_config=ContextCacheConfig(
min_tokens=4096, # Gemini 3 and 4 minimum
ttl_seconds=1800, # cache lifetime (default 1800)
cache_intervals=10, # reuse a cache at most N times
),
)
To check that caching works, look for gen_ai.usage.cache_read.input_tokens on the span or context_cache_hit_rate in v_llm_response.
Compact long sessions. Token-based compaction summarizes older events once the prompt reaches token_threshold and keeps the last event_retention_size events raw. ADK Java uses an interval and overlap pair instead (ADK compaction). Each compaction is a summarizer LLM call. Pass summarizer=LlmEventSummarizer(llm=Gemini(model=...)) to use a cheaper model.
from google.adk.apps.app import App, EventsCompactionConfig
app = App(
name="app",
root_agent=root_agent,
events_compaction_config=EventsCompactionConfig(
token_threshold=32000,
event_retention_size=5,
),
)
How do I cap output tokens?#
Set max_output_tokens in the agent's generate config:
from google.genai import types as genai_types
from google.adk.agents import Agent
agent = Agent(
name="my_agent",
model="gemini-3.8-flash",
instruction="...",
generate_content_config=genai_types.GenerateContentConfig(max_output_tokens=1024),
)
Leave room for thinking tokens, or a thinking model can return an empty response with finish_reason=MAX_TOKENS (python-genai#782).
How do I scale to zero?#
On create, agents-cli deploy defaults to --min-instances 0 on Agent Runtime and Cloud Run. On an existing service it keeps the current value. A Terraform-provisioned service stays at min_instances = 1 until you change it in Terraform or pass --min-instances 0. The Agent Runtime Terraform also sets 4 vCPU and 8Gi, against CLI defaults of 1 and 4Gi, so edit deployment/terraform/ to size down. Use --min-instances 1 when a cold start is not acceptable, for example for live and voice agents.
| Target | Cost model | Pricing |
|---|---|---|
| Agent Runtime | vCPU-hours and memory-hours. Idle time between turns isn't billed. A warm minimum instance may be. | Gemini platform pricing |
| Cloud Run | CPU and memory while handling requests (default) or for the instance lifetime. Minimum instances bill at the idle rate. | Cloud Run pricing |
| GKE | Node costs plus a cluster management fee. The generated Terraform keeps at least 2 replicas. | GKE pricing |
The --min-instances flag applies to Agent Runtime and Cloud Run only. See Deployment.
How do I keep eval spend down?#
A run spends agent tokens on every case as well as judge tokens.
- Run a small dataset with
--datasetwhile you iterate, and the full set before you merge. Use--metrics a,bto run a subset of metrics. - On custom LLM-judge metrics (
prompt_template), setjudge_modelto a cheaper model and lowerjudge_model_sampling_count(1 to 32). Use 3 to 5 only for noisy judges, such as multimodal ones. For the scaffolded judge, change themodel=line intests/eval/response_quality.py. - A rule-based
custom_function(counts, regex, schema checks) runs in the CLI process and makes no model call. The scaffoldedcustom_response_qualityis an LLM judge, so it does. - Run
agents-cli eval optimizeonly when you need prompt optimization. It's ADK Python only, makes many LLM calls and can take a long time.
How do I cut telemetry cost?#
- Keep message content out of trace spans and log events.
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTdoes that when it'sNO_CONTENT(the Python default) or, in Go, unset orfalse. - Terraform-provisioned deployments upload full prompts and responses to GCS and BigQuery. To stop that, remove the
OTEL_INSTRUMENTATION_GENAI_COMPLETION_HOOK,OTEL_INSTRUMENTATION_GENAI_UPLOAD_BASE_PATHandLOGS_BUCKET_NAMEenv blocks. RemovingLOGS_BUCKET_NAMEmoves ADK artifacts to in-memory storage. On Agent Runtime, do this before the firstinfra ... --apply. See Cloud Trace and Security and trust. - Reduce BigQuery retention, and leave out the BigQuery Agent Analytics plugin (
create --bq-analytics) if you don't need it.
Last updated