{"slug": "my-agent-kept-hitting-context-limits-this-one-function-fixed-it", "title": "My agent kept hitting context limits. This one function fixed it.", "summary": "A developer created `agent-message-trim`, a Python library that solves context window limits in AI agents by intelligently trimming conversation history while preserving paired tool_use and tool_result messages. The function ensures trimmed message histories remain valid for Anthropic's API, preventing request rejections that occur when tool calls are separated from their results. The library supports multiple trimming strategies, including dropping oldest messages or removing from the middle of conversations.", "body_md": "*This is a submission for the Hermes Agent Challenge.*\n\nMy Hermes research agent was failing after about 40 turns. The cause: conversation history growing past the context window. The fix everyone reaches for is \"just drop old messages\" — but if you drop a `tool_use`\n\nwithout its matching `tool_result`\n\n, Anthropic's API rejects the whole request.\n\nI needed something smarter. That's `agent-message-trim`\n\n.\n\n``` python\nfrom agent_message_trim import trim_messages\n\nresult = trim_messages(messages, max_tokens=4000)\n\n# Send result.messages to the model — it's safe.\nresponse = client.messages.create(\n    model=\"claude-sonnet-4-5\",\n    messages=result.messages,\n    ...\n)\n\nprint(f\"Dropped {result.dropped_count} messages to fit\")\n```\n\nThis is the part that matters. If your history looks like this:\n\n```\n[\n    {\"role\": \"user\", \"content\": \"search for X\"},\n    {\"role\": \"assistant\", \"content\": [{\"type\": \"tool_use\", \"id\": \"call_001\", ...}]},\n    {\"role\": \"user\", \"content\": [{\"type\": \"tool_result\", \"tool_use_id\": \"call_001\", ...}]},\n    {\"role\": \"assistant\", \"content\": \"Here is what I found.\"},\n]\n```\n\n`trim_messages`\n\nnever drops the `tool_use`\n\nwithout also dropping its `tool_result`\n\n. They move as a unit. The conversation you get back is always API-valid.\n\n```\nresult = trim_messages(messages, max_tokens=4000, keep_system=True)\n# system-role messages are pinned — never dropped, not counted toward drop candidates\n# Default: drop from the front (oldest messages go first)\nresult = trim_messages(messages, max_tokens=4000, strategy=\"drop_oldest\")\n\n# Keep first + last, remove from the middle\nresult = trim_messages(messages, max_tokens=4000, strategy=\"drop_middle\")\n```\n\n`drop_middle`\n\nis useful when you want to keep the original task context AND the most recent exchange, but can sacrifice the middle of a long conversation.\n\nThe built-in estimator is `max(1, (len(text)+3)//4)`\n\n. Plug in your own:\n\n``` python\nimport tiktoken\nenc = tiktoken.encoding_for_model(\"gpt-4o\")\n\nresult = trim_messages(\n    messages,\n    max_tokens=4000,\n    count_tokens=lambda text: len(enc.encode(text)),\n)\nresult = trim_messages(messages, max_tokens=4000)\nresult.messages        # trimmed list\nresult.token_count     # estimated tokens used\nresult.original_count  # how many messages came in\nresult.dropped_count   # how many were removed\nresult.ok              # True if nothing was dropped\nresult.kept_count      # len(result.messages)\npython\nfrom agent_message_trim import trim_to_fit\n\ntrimmed = trim_to_fit(messages, max_tokens=4000)\n# returns the list directly\n```\n\nStandard library only: `json`\n\n, `dataclasses`\n\n. Nothing else.\n\n```\npip install agent-message-trim\n```\n\n", "url": "https://wpnews.pro/news/my-agent-kept-hitting-context-limits-this-one-function-fixed-it", "canonical_source": "https://dev.to/mukundakatta/my-agent-kept-hitting-context-limits-this-one-function-fixed-it-3a42", "published_at": "2026-05-25 21:21:11+00:00", "updated_at": "2026-05-25 21:33:54.133905+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "large-language-models", "artificial-intelligence"], "entities": ["Anthropic", "Claude Sonnet 4.5", "agent-message-trim"], "alternates": {"html": "https://wpnews.pro/news/my-agent-kept-hitting-context-limits-this-one-function-fixed-it", "markdown": "https://wpnews.pro/news/my-agent-kept-hitting-context-limits-this-one-function-fixed-it.md", "text": "https://wpnews.pro/news/my-agent-kept-hitting-context-limits-this-one-function-fixed-it.txt", "jsonld": "https://wpnews.pro/news/my-agent-kept-hitting-context-limits-this-one-function-fixed-it.jsonld"}}