← All AI Engineer talks

AI Engineer World's Fair 2026

Your Agent Is Wasting Tokens and You Don't Know It

[REDACTED:username]· Amazon Web Services5:55

Read the talk

Your Agent Is Wasting Tokens and You Don’t Know It

Repeated prompts, oversized tool results, unchecked loops, and growing histories all add to an agent’s bill. Five controls target those costs at different points in execution.

From a talk by [REDACTED:username]

Before you start: You should be familiar with system prompts, model context windows, and the way an agent alternates between model calls and tool execution.

Cache repeated prompts

Your agent sends a large system prompt on its first call. On the next call, the instructions are unchanged: why pay to process them from scratch again? This is the opening example in Erik Hanchett’s five controls for agent token costs. Hanchett introduces himself as a senior developer advocate at AWS and demonstrates the controls using Strands Agents, an SDK that supports different model providers.

The demonstration places cache_prompt="default" on BedrockModel and supplies the repeated instructions through the agent’s system_prompt. The following Python preserves that configuration pattern:

python

from strands import Agent
from strands.models import BedrockModel

SYSTEM_PROMPT = """
You are a support assistant. Use the supplied product documentation
when answering questions. Ask for missing details before diagnosing
an issue, and distinguish documented behavior from your suggestions.
"""

agent = Agent(
    model=BedrockModel(cache_prompt="default"),
    system_prompt=SYSTEM_PROMPT,
)

The short prompt makes the wiring visible; actual cache eligibility depends on the model’s minimum prefix length. Hanchett describes subsequent calls as sending a much smaller system prompt. More precisely, Bedrock prompt caching reuses computation for an eligible, unchanged prefix and discounts cache reads; it does not necessarily reduce the prompt transmitted. Cache expiration and possible cache-write premiums affect the savings. The demonstrated cache_prompt setting belongs to the Bedrock provider and is now deprecated in favor of cache_config.

Slide titled “Cache the System Prompt” shows Agent and BedrockModel code with cache_prompt="default" and system_prompt=BIG_SYSTEM_PROMPT, alongside a presenter inset.
Cache the system prompt: the code example sets cache_prompt="default".

System instructions are only the first candidate. Repeated tool definitions and stable message content can also be cached where the provider supports it. Cache the content that stays the same across calls so repeated work can benefit from reuse.

0:000:18
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:00 · section reference included

Route tasks by difficulty

A demanding task may justify a newer frontier model. A simpler task may not need that expense. Hanchett’s comparison uses Claude Haiku for cheaper, simpler work and Claude Sonnet for more difficult work, without specifying model versions or a price ratio.

TaskModel choice in the example
Simpler workClaude Haiku
More difficult workClaude Sonnet

The useful distinction is the capability the task requires. An agent does not need to send every operation to its most expensive model.

Routing can begin with an ordinary if statement. This function accepts two already configured Strands agents and chooses between them using a difficulty decision supplied by the application:

python

from strands import Agent


def route_task(
    task: str,
    difficult: bool,
    cheap_agent: Agent,
    capable_agent: Agent,
):
    if difficult:
        return capable_agent(task)
    return cheap_agent(task)

Alternatively, a separate inexpensive model can classify the task and select the destination. In either case, the routing decision becomes an explicit part of the agent’s workflow, allowing different use cases to reach different models.

1:011:15
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

1:01 · section reference included

Offload large tool results

A tool can return far more information than the model needs for its next decision. Hanchett introduces a manual Strands approach: store the large result locally or in cloud storage, then supply a summary. He also mentions supporting APIs without naming them.

The cost appears repeatedly when that large result remains in the context carried through the agent loop. The model can receive the same bulky output again on each subsequent call, even after the useful facts have already been extracted.

  1. Persist the full tool result outside the model context.
  2. Summarize the information needed for the next decision.
  3. Carry that compact representation into subsequent calls instead of repeatedly including the full result.

Offloading separates retaining the data from repeatedly paying to include it in context. Keeping a copy in storage alone does not achieve the goal if the full result still travels through every model call.

1:512:00
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

1:51 · section reference included

Cap loops and inspect tool behavior

Summarizing tool output reduces the size of repeated calls. The next control limits how often those calls happen. Hanchett reports encountering agents that invoke the same tool over and over. He warns that an uncapped tool loop might run ten or twenty times, or continue indefinitely. These are failure examples, not measured workload results.

Set an explicit maximum iteration count so the agent cannot continue without a bound. Hanchett supplies no recommended limit; the appropriate budget depends on the work the agent needs to complete.

Before deployment, inspect each tool with observability tooling:

  • Call duration: How long does each execution take?
  • Repetition: How many times does the agent call the tool or cycle through the loop?

Inspecting both reveals whether the expense comes from slow individual calls, repeated calls, or both. Those observations give you a basis for judging tool efficiency and changing the workflow.

2:413:00
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

2:41 · section reference included

Trim history while preserving a summary

A multi-turn conversation creates another source of repeated input. Each exchange grows the history, and subsequent model calls can resend everything that came before. Hanchett describes whole-history resending as consuming hundreds or thousands of tokens as conversations grow. The issue is cumulative: an old exchange can keep contributing to the input long after it stops helping the current task.

A SlidingWindowConversationManager bounds the recent history retained for the model. Hanchett uses a configurable ten-message window as his example. Set that value explicitly to express the example in Python:

python

from strands import Agent
from strands.agent.conversation_manager import (
    SlidingWindowConversationManager,
)

agent = Agent(
    conversation_manager=SlidingWindowConversationManager(
        window_size=10,
    ),
)

Ten messages is the talk’s example, not the current SDK default: the current Python reference defaults to 40 and accounts for valid tool-use/result relationships during reduction.

The trade-off appears when the window drops the beginning of the conversation. Earlier requirements or decisions may disappear along with less useful exchanges. Hanchett’s remedy is to summarize the older history and put that smaller representation into the context when the window boundary is reached. The retained context then combines recent detail with a compact account of what came before. A sliding window alone does not supply that summary; summarization is an additional step.

3:373:42
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

3:37 · section reference included

Use observations to guide the next change

The closing recap brings the controls back to the agent as a whole: reuse stable prompt content, choose models by difficulty, and keep bulky tool data out of repeated context. Hanchett then returns to measurement—inspect tool durations and loop counts, and iterate from what they show. For longer conversations, keep checking what history gets carried forward as new messages arrive. The practical work is to examine the repeated model call: which content still belongs there, which model should handle it, and whether another iteration is justified.

Recap slide lists Cache the System Prompt, Route by Difficulty, Offload Big Tool Results, Cap Your Tool Loops, and Trim the History, with a presenter inset at lower right.
“Same Agent. Smaller Bill.” recaps five fixes for agent token costs.
4:515:05
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

4:51 · section reference included

Resources

From the talk

Updates since the talk

Read the complete timestamped transcript
  1. 0:00

    Hey everyone. My name is [REDACTED:username]. I am a senior developer advocate at AWS, and I'm gonna talk to you about how you can save on token costs. Now I'm gonna show you five ways that you can reduce your token costs while using and creating agents.

  2. 0:18

    So the first way you can do that is to cache your system prompt. Let me show you some code. Now I'm using AWS's Strands Agents. This works with all different providers.

  3. 0:33

    This is a little bit of pseudocode, but the idea is that you can add cache_prompt=default, and what that'll do is on the first call of your agent, it will send the full system prompt over, and then on every subsequent call, it will have a much reduced system prompt being sent over.

  4. 0:54

    So it'll be cached. You can also cache the tool prompts and messages as well.

  5. 1:01

    This may sound obvious, but you want to look into routing your different messages based on the difficulty. So here's a code example. Let's imagine that you have a task that's very difficult.

  6. 1:15

    You may wanna use one of the newer frontier models. However, if it's something simpler, you want to use a cheaper model. In this case, maybe we use Claude Haiku for a cheap-- something cheap, and then use Claude Sonnet for something a little bit more difficult.

  7. 1:30

    And then you can use an if statement. You can even have another model that's very cheap decide which model to use. So you can play around with this, but I highly recommend don't use the most expensive model for everything you're doing.

  8. 1:43

    You want to use multiple different models based on the use case, and then try to route to it inside your agent.

  9. 1:51

    Another good tip is to offload the tool result. Let me show you some code on here. Once again, I'm using Strands Agents. This is a, a manual way to do it.

  10. 2:00

    There is some additional APIs that the Strands Agents offers to do this. If you have a large tool result that's coming back, you can store it locally or in the cloud and then use some kind of summarization that saves on tokens.

  11. 2:18

    So that way when it's being called over and over again, the tool result isn't added into the context every time, every time the tool loops or every time the agent loops.

  12. 2:30

    So if you can find any way that where you have this tool result that you don't necessarily send it on every single call back to the large language model, that will save a lot of tokens for you.

  13. 2:41

    And like I said, there's a few APIs to do this, but e-essentially you can do the summarization technique. You can also cap your tool loops. So when you're dealing with the agent loop and it decides to do a tool call, I've had this happen often where it calls the tool over and over and over again.

  14. 3:00

    And if you don't cap that tool call, then it might run ten, twenty times. It might get into an infinite loop, which would be very bad for your token usage.

  15. 3:10

    So always set a max iterations of how many times it will loop. A, a good thing you can do before you deploy your agent is to run some observability tools and take a look at the tool call use for every single tool, and then see how long each one of them is running and how many times they're

  16. 3:30

    looping. And that way you can get an idea of how efficient the tool call is.

  17. 3:37

    Last but not least, we can trim the history.

  18. 3:42

    So if we're using a, a multi-turn agent and we are talking back and forth, you will find at times that the conversation history will get very large. On every single call, that whole conversation history will be sent back to the large language model, and this can eat through hundreds if not thousands of tokens.

  19. 4:03

    In Strands Agents, we have something called Sliding Window Conversation Manager, which, which this does is it looks back at the last ten messages and only sends those back, and you can set this to whatever you want.

  20. 4:16

    And that way you're not sending these huge message histories back to the agent every single time a new message comes in. The downfall of this, or the trade-off of this I should say, is that you will lose the message history from the beginning.

  21. 4:33

    The way you wanna deal with that is you can use, uh, some sort of summarization of the history and then put that into the context window. So rather than sending all of it, you may send a small amount once you hit this sliding window.

  22. 4:46

    Uh, this will save you a lot of tokens.

  23. 4:51

    So in conclusion, we have five things. Cache the system prompt, and if you can, maybe the tool prompt to messages. Route by difficulty. Don't use the same expensive model for everything you're doing, for every single task.

  24. 5:05

    Offload these big tool results. So if you have a large tool result, you can summarize it and not have it being sent in the agent loop and overloading your context.

  25. 5:16

    You can cap those tool loops. Make sure you use observability tools to see how long tool calls are taking and how many loops they're, they're doing and, and then try to iterate over that.

  26. 5:27

    And then of course trim the history if you're using a multi-turn conversation with your agent, so that way the whole conversation isn't being sent over and over again for very long conversations.

  27. 5:37

    Thank you for listening to my very quick almost lightning talk today. If you'd like to go deeper, find me on LinkedIn at [REDACTED:username]. I also blog at programwitherik.com, and then you can find me on social media at [REDACTED:username].

  28. 5:52

    Love to talk to you guys more. Thanks.