{"id":1105,"date":"2026-10-12T09:30:00","date_gmt":"2026-10-11T22:30:00","guid":{"rendered":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/"},"modified":"2026-11-03T20:28:10","modified_gmt":"2026-11-03T09:28:10","slug":"telegram-ai-agent-local-llms","status":"publish","type":"post","link":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/","title":{"rendered":"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11)"},"content":{"rendered":"\n<p class=\"has-pale-cyan-blue-background-color has-background wp-block-paragraph\">We ran a Telegram AI agent on local models in our lab. It gave bad answers, then refused to start, then refused every request. Each time, the cause was the part of the prompt nobody types. Here is what happened and how to build one that works.<\/p>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<p class=\"wp-block-paragraph\"><strong>Where this fits \u00b7 Running Local AI in Production \u00b7 Part 9 of 11<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:17px\">You are reading Part 9 of 11 in a series where we built a private AI server in our lab and ran realistic test workloads on it for seven weeks. Each part stands on its own. The previous part covered a multi-agent stock-analysis experiment and how we scored the agents; this one covers a Telegram AI agent on local models, and why its fixed prompt became the budget.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:16px\"><a href=\"https:\/\/catharsis.net.au\/blog\/multi-agent-stock-analysis-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">\u2190 Part 8: Can Local AI Agents Analyse Stocks? How We Tested and Scored Them<\/a> &nbsp;\u00b7&nbsp; <a href=\"https:\/\/catharsis.net.au\/blog\/running-local-ai-in-production-series-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">Series guide<\/a> &nbsp;\u00b7&nbsp; <a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-business-workflows\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 10: Can AI Automate Business Workflows Without Sending Data Out? \u2192<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:16px\">Just want it working? Follow the <a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-litellm-setup-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">step-by-step setup guide<\/a>: local AI with Ollama and LiteLLM, from a bare server to a secure gateway.<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>See all 11 parts of the series<\/summary>\n\n<ol class=\"wp-block-list\">\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/why-run-ai-on-your-own-hardware\/\" target=\"_blank\" rel=\"noreferrer noopener\">Local AI or Cloud AI? Why We Built a Private AI Server<\/a>: why we built the lab on our own hardware, what ran on it and what that choice cost<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/llm-gateway-one-door-for-every-model\/\" target=\"_blank\" rel=\"noreferrer noopener\">How Do You Control Access to Local AI Models? Use a Gateway<\/a>: one LLM gateway as the only way to reach a model: keys, budgets and tracing<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/\" target=\"_blank\" rel=\"noreferrer noopener\">Why Does a Local AI Server Freeze? Sizing Memory for LLMs<\/a>: five hard freezes and the memory budget that ended them<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/local-llm-context-budget\/\" target=\"_blank\" rel=\"noreferrer noopener\">What Happens When a Prompt Is Too Big for a Local LLM?<\/a>: fitting every prompt to a local model&#8217;s context window<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/smart-routing-single-gpu-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">How Do You Run Several AI Models on One GPU Without Slowdowns?<\/a>: routing requests across models on a single GPU without constant model swaps<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/gitops-for-a-gpu-ai-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">How Do You Keep an AI Server Stable? GitOps for Local AI<\/a>: running the server from a Git repository: deploys, drift, pinning and safe AI agents<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/observability-for-local-ai\/\" target=\"_blank\" rel=\"noreferrer noopener\">What Is Your Local AI Server Actually Doing? Observability Basics<\/a>: making the server observable: traces, dashboards, usage and heat<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/multi-agent-stock-analysis-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">Can Local AI Agents Analyse Stocks? How We Tested and Scored Them<\/a>: a multi-agent stock-analysis experiment and how we scored the agents<\/li>\n\n\n<li><strong>Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost<\/strong> (you are here): a Telegram AI agent on local models, and why its fixed prompt became the budget<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-business-workflows\/\" target=\"_blank\" rel=\"noreferrer noopener\">Can AI Automate Business Workflows Without Sending Data Out?<\/a>: document, email and knowledge-base workflows that keep data on the server<\/li>\n\n\n<li><a href=\"https:\/\/catharsis.net.au\/blog\/private-ai-lab-lessons-and-whats-next\/\" target=\"_blank\" rel=\"noreferrer noopener\">Is Private AI Worth It? Lessons From Seven Weeks in Our Lab<\/a>: the lessons from seven weeks, the honest limits and what comes next<\/li>\n\n<\/ol>\n\n<\/details>\n\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\" style=\"font-size:16px\"><em>This series documents a private AI server we built and stress-tested in our lab. Workloads and data are synthetic or generalised; the problems, measurements and fixes are real.<\/em><\/p>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<h3 class=\"wp-block-heading\">TL;DR<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>It was slow, and often refused outright, because of text nobody typed. About 90 unneeded tool descriptions, a developer guide loaded by accident and a feed of simulated events kept its prompts huge and its one GPU slot busy.<\/li>\n\n\n<li>We wanted a chat agent on Telegram that runs on local models only, so nothing it reads leaves the server. In testing it gave wrong answers, refused to start, refused every request, refused a simple &quot;hi&quot;, and took up to two minutes to reply.<\/li>\n\n\n<li>Rather than raise the server&#8217;s memory limits or move to a cloud model, we kept the limits and shrank what the agent sends on every turn: its instructions, its tool descriptions and anything it loads by accident.<\/li>\n\n\n<li>The fixed part of each prompt fell from 32\u201335k tokens to 14.9k, and replies that had been refused or took two minutes now take 3\u20137 seconds.<\/li>\n\n\n<li>The lesson is that an agent&#8217;s fixed prompt is a budget like any other, and every way into the agent needs its own test. The steps at the end show how to build one with both in place.<\/li>\n\n<\/ul>\n\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Jargon buster: 15 terms used in this post, explained in plain English<\/summary>\n\n<ul class=\"wp-block-list\">\n\n<li><strong>Context window<\/strong>: The maximum number of tokens a model can consider at once, covering both the prompt and its answer.<\/li>\n\n\n<li><strong>KV cache<\/strong>: Working memory a model keeps while it reads a prompt. It grows with the length of the context, so long contexts need a lot of memory.<\/li>\n\n\n<li><strong>Unified memory<\/strong>: A design where the CPU and GPU share one pool of memory instead of the GPU having its own. Flexible, but both compete for the same space.<\/li>\n\n\n<li><strong>Slot (parallel requests)<\/strong>: One request a model server can work on at the same time. More slots serve more people at once but reserve more memory.<\/li>\n\n\n<li><strong>Ollama<\/strong>: Free, open-source software that downloads and runs AI models on your own machine and answers requests over a local API.<\/li>\n\n\n<li><strong>LiteLLM<\/strong>: Open-source software that puts one front door in front of many AI models, with per-user keys, budgets, limits and logging.<\/li>\n\n\n<li><strong>LLM gateway<\/strong>: A single service every AI request must pass through, so access, budgets and logging are controlled in one place.<\/li>\n\n\n<li><strong>Trace<\/strong>: A detailed record of one request as it passes through each part of a system, used to find where time or errors come from.<\/li>\n\n\n<li><strong>Hermes Agent<\/strong>: An open-source AI agent framework that can run on local models and connect to chat apps such as Telegram.<\/li>\n\n\n<li><strong>Telegram bot<\/strong>: An automated account on the Telegram messaging app that people chat with; here, the front end for an AI agent.<\/li>\n\n\n<li><strong>Docker \/ container<\/strong>: A way of packaging an application with everything it needs so it runs the same anywhere; each packaged application runs in its own container.<\/li>\n\n\n<li><strong>Loopback<\/strong>: A network address that only the server itself can reach, so a service listening there isn&#8217;t exposed to the network.<\/li>\n\n\n<li><strong>Sandbox<\/strong>: An isolated environment that limits what a program can see or change, so a misbehaving program can&#8217;t affect the rest of the system.<\/li>\n\n\n<li><strong>systemd<\/strong>: The service manager on most Linux systems: it starts, stops and supervises background services.<\/li>\n\n\n<li><strong>Compaction<\/strong>: Shortening a long conversation (for example by summarising older messages) so it fits the model&#8217;s context window.<\/li>\n\n<\/ul>\n\n<\/details>\n\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<h3 class=\"wp-block-heading\">In this post<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li><a href=\"#the-problem-why-did-our-private-chat-agent-keep-failing\">The problem: why did our private chat agent keep failing?<\/a><\/li>\n\n\n<li><a href=\"#what-we-were-aiming-for\">What we were aiming for<\/a><\/li>\n\n\n<li><a href=\"#how-we-approached-it\">How we approached it<\/a><\/li>\n\n\n<li><a href=\"#what-we-built\">What we built<\/a><\/li>\n\n\n<li><a href=\"#challenges-we-hit\">Challenges we hit<\/a><\/li>\n\n\n<li><a href=\"#the-result\">The result<\/a><\/li>\n\n\n<li><a href=\"#do-it-yourself-a-chat-agent-on-local-models-with-a-measured-\">Do it yourself: a chat agent on local models with a measured prompt budget<\/a><\/li>\n\n\n<li><a href=\"#key-takeaways\">Key takeaways<\/a><\/li>\n\n<\/ul>\n\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-problem-why-did-our-private-chat-agent-keep-failing\">The problem: why did our private chat agent keep failing?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Plenty of businesses would like a chat assistant their staff can message from their phone, one that can look things up and use tools but never sends what it reads to a cloud provider. We built that in our lab with Hermes Agent, an open-source agent framework from Nous Research, running as a Telegram bot and a web dashboard on local models only. It answered questions over sample data and the two demo knowledge bases from <a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-business-workflows\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 10<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Over seven weeks of testing it failed in five different ways. It gave wrong answers. Then it refused to start. Then it refused every request, including the first message of a new conversation. Five days later the dashboard refused the word &quot;hi&quot;. Finally, replies took between 30 seconds and two minutes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wrong answers given confidently are a risk. Refusals that nobody notices mean work silently not getting done, and a two-minute wait means nobody uses the tool.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-we-were-aiming-for\">What we were aiming for<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Correct answers, with nothing quietly cut from the prompt.<\/li>\n\n\n<li>An agent that fits the server&#8217;s memory limits, without raising them, because raising them is what froze the server.<\/li>\n\n\n<li>Replies in seconds, not minutes.<\/li>\n\n\n<li>Data that stays on the server, with the agent holding only the access it needs.<\/li>\n\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"how-we-approached-it\">How we approached it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The agent runs on the lab&#8217;s NVIDIA DGX Spark, with roughly 120 GB of usable unified memory shared by the CPU and GPU. Every model call goes through a gateway, LiteLLM (<a href=\"https:\/\/catharsis.net.au\/blog\/llm-gateway-one-door-for-every-model\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 2<\/a>), which allows 26,000 input tokens per request. That limit protects the server, as <a href=\"https:\/\/catharsis.net.au\/blog\/local-ai-server-freezes-unified-memory\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 3<\/a> explains.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We had three options when the agent didn&#8217;t fit. Raising the budget would bring the freezes back, and we never raise a ceiling just to make one job fit. A cloud model with a bigger window would defeat the point of a private agent. So we chose the third option. We kept every real limit in place and made the agent smaller, by measuring the part of every prompt the user never types and cutting what the job didn&#8217;t need.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-we-built\">What we built<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The agent runs in a sandboxed container, only the lab&#8217;s test accounts can talk to it, and it has no access to the lab&#8217;s secrets. It never talks to a model directly. It calls the gateway with its own key and asks for the model <code>auto<\/code>, and the smart router from <a href=\"https:\/\/catharsis.net.au\/blog\/smart-routing-single-gpu-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 5<\/a> sends requests with tools to one of the two models kept loaded, in practice <code>gemma4<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It runs with a 32k context and one slot and takes 17.5 GB; the pair of resident models measures 37.8 GB. The gateway refuses anything over 26,000 input tokens with a clear <code>400 context_length_exceeded<\/code> error instead of letting the model server trim it quietly. That check is our own, because LiteLLM treats <code>max_input_tokens<\/code> as metadata unless you turn on its pre-call checks. The gateway also compacts long conversations, as <a href=\"https:\/\/catharsis.net.au\/blog\/local-llm-context-budget\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 4<\/a> explains, keeping recent turns and every tool call and result word for word and carrying the rest forward as a digest.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The agent&#8217;s tool set is cut to 24 tools, down from about 90 on one admin tool server plus 37 others. Its working directory is set explicitly, its event feed is parked, and the hourly guard script posts to the lab&#8217;s alert channel whenever any key has requests refused. Each of those came from a challenge below.<\/p>\n\n\n\n<div class=\"wp-block-group has-pale-cyan-blue-background-color has-background\" style=\"padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px;margin-top:32px;margin-bottom:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<p class=\"wp-block-paragraph\"><strong>Want AI to take on routine work, without sending your data to a public service?<\/strong> We build secure AI automations and agents that run on infrastructure you control, with a person reviewing what matters.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/ai-automation\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=local-ai-series&amp;utm_content=part-09-mid\" target=\"_blank\" rel=\"noreferrer noopener\">Explore AI Automation<\/a><\/div>\n\n<\/div>\n\n<\/div><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"challenges-we-hit\">Challenges we hit<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Wrong answers from silent truncation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A model&#8217;s <strong>context window<\/strong> is the most tokens (roughly, word-pieces) it can consider at once, prompt and answer together. Ollama, the model server, was running with a default of 16,384 tokens. Hermes sends a long system prompt, every tool description and the conversation, and together they went past 16k. Ollama doesn&#8217;t reject a prompt that is too long. It cuts it down and answers anyway, so the model never saw part of what it was asked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We raised the context built into the two main models to 65,536 tokens. That fixed the answers and set up the freezes. Ollama gives every parallel slot the full context and reserves <strong>KV cache<\/strong>, the working memory a model keeps for each token, for every slot. Four slots at 64k took <code>qwen3-coder<\/code>, the model serving the overnight stock-analysis run, to about 33 GB, roughly 19 GB of weights plus roughly 14 GB of KV cache, and the server froze one night with a 65,007-token prompt in flight. The reservation was the cause, not the prompt. That is why the setup above is 32k, one slot and a gateway that refuses.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The agent refused to start<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">With the budget in place, every start failed.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><code>Model auto has a context window of 26,000 tokens, which is below the minimum 64,000 required by Hermes Agent.<\/code><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Hermes asks the gateway for the window size and, in the version we ran, won&#8217;t run below 64k. We told it a number it accepts with one line of config, while the gateway kept enforcing 26,000.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>model:\n  context_length: 65536\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Reading the agent&#8217;s source first, we found a trap. Hermes compresses its own history at <code>max(context_length \u00d7 threshold, 64000)<\/code>, so lowering the threshold does nothing. Conversations grow towards 64k, and the gateway handles everything above 26,000. We tested that path. A 26,967-token conversation left the gateway at 23,147 tokens, with 69 of its 90 messages kept word for word, and got an answer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Every request refused, before anyone typed<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Then the gateway refused every request. Its refusal reports the count, and the fixed part of each Hermes request was 32,632 to 35,423 tokens. That fixed part is the instructions, the skills index and a <strong>tool schema<\/strong> for every tool, the JSON description of its name, purpose and parameters, which the model needs on every turn. Compaction couldn&#8217;t help because none of it was history, and the log said so: <code>compaction result rejected \u2026 over_budget<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most of the bulk was one MCP server. MCP, the Model Context Protocol, is a standard way to plug tool servers into an agent, and Hermes had been connected to the admin tool server of Langfuse, the lab&#8217;s tracing system. It publishes about 90 tools for creating dashboards, deleting datasets and the like. A chat assistant needs none of them. Without it, the fixed prompt fell to 17,206 tokens.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">&quot;Hi&quot; cost 26,484 tokens<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Five days later the dashboard refused &quot;hi&quot; at 26,484 tokens. The gateway had refused the agent 20 times over those days, with prompts of 26k to 61k, and no alert had fired. Our usual test, a one-shot command inside the container, showed about 17k. The dashboard took a different path. It started Hermes without a working directory, so the agent started in its install folder and read <code>AGENTS.md<\/code>, the guide for Hermes&#8217; own developers, about 6,000 tokens of it. One environment variable setting the working directory fixed it. We had tested the way in that was easy to script, not the one testers used.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We then trimmed the default toolsets. Some called cloud services, one spawned parallel sub-agents that would only queue on a one-slot GPU, and others made no sense in a container. We also switched off the unused &quot;list resources&quot; and &quot;list prompts&quot; helpers. That took the agent from 37 tools to 24.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A second copy, and an &quot;off&quot; switch that wasn&#8217;t<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A &quot;restart gateway&quot; button on the dashboard had started a second Telegram gateway with older settings. Two pollers shared one bot, Telegram logged <code>polling conflict \u2026 only one bot instance<\/code>, and the logs stopped adding up. We stopped the copy and removed the dashboard&#8217;s power to restart or update running services.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We had also connected the agent to a feed of simulated sensor readings, and every reading became an agent turn. Even after narrowing it, that was 442 events an hour, so we set its <code>enabled<\/code> flag to <code>false<\/code>. Days later, every agent call was a sensor event, each a 15k-token turn holding the one slot for 10\u201330 seconds while real messages waited. Hermes switches that integration on whenever its connection details are set, whatever the flag says. Renaming the watch lists to parked names finally stopped the events, and the on-demand tools still work.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-result\">The result<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\">\n<thead>\n<tr>\n<th><\/th>\n<th>Before<\/th>\n<th>After<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Fixed prompt, one-shot<\/td>\n<td>32,632\u201335,423 tokens<\/td>\n<td>14,882 tokens<\/td>\n<\/tr>\n<tr>\n<td>Dashboard &quot;hi&quot;<\/td>\n<td>26,484 tokens, refused<\/td>\n<td>about 13.8k, answered<\/td>\n<\/tr>\n<tr>\n<td>Tools<\/td>\n<td>about 90 + 37<\/td>\n<td>24<\/td>\n<\/tr>\n<tr>\n<td>Reply time<\/td>\n<td>refused, or 30 s to 2 min<\/td>\n<td>3\u20137 s warm, about 12 s if the model must load<\/td>\n<\/tr>\n<\/tbody>\n<\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The trade-offs are real. The agent can no longer speak, draw, spawn sub-agents or reach the tracing admin. About 11k tokens of headroom means long sessions lose older detail sooner than with a native 64k window. One giant pasted email still can&#8217;t be summarised away, so email workflows have to chunk and retrieve. And Hermes keeps its settings outside the deploy script, so every change there gets a copy beforehand and a changelog entry, and the guard alerts on any change.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We had tested the dashboard only by hand. A scheduled &quot;hi&quot; through every entry point would have caught the <code>AGENTS.md<\/code> problem on day one. Next we want an hourly digest instead of raw events, and tools chosen per conversation.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"do-it-yourself-a-chat-agent-on-local-models-with-a-measured-\">Do it yourself: a chat agent on local models with a measured prompt budget<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What you need:<\/strong> a Linux server with a GPU or unified memory that can hold a 20\u201330 GB model, Docker, Ollama, LiteLLM with its Postgres database (virtual keys need it), and an agent framework that speaks the OpenAI API. Allow half a day.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n\n<li>\n<p><strong>Run Ollama on loopback with one slot and a fixed context.<\/strong> Add a systemd override with <code>sudo systemctl edit ollama<\/code>, which reloads systemd for you, then <code>sudo systemctl restart ollama<\/code>. On a host that already runs GPU containers, a systemd reload can strip their GPU access, so do this in a maintenance window and check each one afterwards with <code>docker exec &lt;container&gt; nvidia-smi -L<\/code> (<a href=\"https:\/\/catharsis.net.au\/blog\/gitops-for-a-gpu-ai-server\/\" target=\"_blank\" rel=\"noreferrer noopener\">Part 6<\/a>).<\/p>\n<pre><code class=\"language-ini\">[Service]\nEnvironment=&quot;OLLAMA_HOST=127.0.0.1:11434&quot;\nEnvironment=&quot;OLLAMA_NUM_PARALLEL=1&quot;\nEnvironment=&quot;OLLAMA_CONTEXT_LENGTH=32768&quot;\n<\/code><\/pre>\n<p>Check: after one request, <code>curl -s 127.0.0.1:11434\/api\/ps<\/code> shows the model&#8217;s <code>size_vram<\/code> and <code>context_length<\/code>. Write the size down, because it is your real footprint.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Put the gateway in front.<\/strong> In LiteLLM&#8217;s <code>config.yaml<\/code>, add the model under <code>model_list<\/code> as <code>chat<\/code>, with the <code>ollama_chat\/<\/code> provider (the chat endpoint, so tool calls work). Set <code>OLLAMA_API_BASE<\/code> to Ollama&#8217;s loopback address, <code>http:\/\/127.0.0.1:11434<\/code>.<\/p>\n<pre><code class=\"language-yaml\">model_list:\n  - model_name: chat\n    litellm_params:\n      model: ollama_chat\/gemma4-32k\n      api_base: os.environ\/OLLAMA_API_BASE\n    model_info:\n      max_input_tokens: 26000\n<\/code><\/pre>\n<p>Check: <code>curl -s 127.0.0.1:4000\/v1\/models -H &quot;Authorization: Bearer $LITELLM_MASTER_KEY&quot;<\/code> lists <code>chat<\/code>.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Give the agent its own key, limited to that model.<\/strong><\/p>\n<pre><code class=\"language-bash\">curl -s 127.0.0.1:4000\/key\/generate \\\n  -H &quot;Authorization: Bearer $LITELLM_MASTER_KEY&quot; -H &quot;Content-Type: application\/json&quot; \\\n  -d '{&quot;key_alias&quot;: &quot;chat-agent&quot;, &quot;models&quot;: [&quot;chat&quot;], &quot;rpm_limit&quot;: 30}'\n<\/code><\/pre>\n<p>Check: the response contains a <code>key<\/code>, and a call with it to any other model is refused.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Enforce an input budget below the context.<\/strong> Keep <code>max_input_tokens<\/code> in the model&#8217;s <code>model_info<\/code> and turn on <code>enable_pre_call_checks<\/code> under <code>router_settings<\/code>, or put your own check in front as we did. Leave room for the answer.<\/p>\n<p>Check: a prompt over the budget gets an error, not a truncated answer.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Measure the fixed prompt with every tool loaded.<\/strong> Send &quot;hi&quot; as the agent and read <code>prompt_tokens<\/code> for its key in the gateway&#8217;s logs or your tracing tool.<\/p>\n<p>Check: it should sit well under half your budget. If not, go to step 6.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Cut tools to what the job needs.<\/strong> Remove admin tool servers, cloud-calling toolsets and sub-agent spawners, and repeat step 5 after each change.<\/p>\n<p>Check: the number drops each time, and the agent still does its job.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Sandbox it.<\/strong> Pin the image by digest, run as a non-root user with a read-only filesystem, no Docker socket, no published ports, and only its own key and bot token. A read-only root filesystem needs writable places for temporary files and the agent&#8217;s own state, or most agents fail at start-up. Restrict which chat accounts may talk to it in the agent&#8217;s own settings.<\/p>\n<pre><code class=\"language-yaml\">services:\n  agent:\n    image: your-agent@sha256:&lt;digest&gt;\n    user: &quot;1000:1000&quot;\n    read_only: true\n    cap_drop: [ALL]\n    security_opt: [&quot;no-new-privileges:true&quot;]\n    tmpfs: [&quot;\/tmp&quot;]\n    volumes: [&quot;agent-data:\/home\/agent\/.hermes&quot;]   # whatever path your agent writes\n    restart: unless-stopped\nvolumes:\n  agent-data:\n<\/code><\/pre>\n<p>Check: <code>docker inspect --format '{{.Config.User}}'<\/code> on the container shows <code>1000:1000<\/code>, the agent keeps its conversation state after a restart (so it can write to its volume), and an unknown chat account gets no reply.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Test every way in, and time it.<\/strong> Send &quot;hi&quot; through the chat app, the dashboard and the command line, and record prompt tokens and reply time for each.<\/p>\n<p>Check: the counts agree within a few hundred tokens, and warm replies come back in seconds.<\/p>\n<\/li>\n\n\n<li>\n<p><strong>Alert on refusals per key.<\/strong> Have a scheduled job count <code>context_length_exceeded<\/code> errors per key and notify you when any appear.<\/p>\n<p>Check: send one oversized prompt and confirm the alert arrives.<\/p>\n<\/li>\n\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"key-takeaways\">Key takeaways<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>An agent&#8217;s fixed prompt is a budget line. Here it went from 35k to 15k tokens, so measure it before the conversation starts.<\/li>\n\n\n<li>History compaction can&#8217;t fix a bloated fixed prompt, because it trims turns, not tools.<\/li>\n\n\n<li>Silent truncation is worse than a refusal. A refusal tells you something is wrong, while truncation gives you confident wrong answers.<\/li>\n\n\n<li>Test every way in. Telegram, the command line and the dashboard each built a different prompt, and only one was broken.<\/li>\n\n\n<li>&quot;Disabled&quot; in a config file is a claim, not a fact. Watch the traffic: at 15k tokens per event, a chatty feed fills a one-slot GPU.<\/li>\n\n\n<li>Give agents only the tools they need, and alert on refusals per key.<\/li>\n\n<\/ul>\n\n\n\n<div class=\"wp-block-group has-light-green-cyan-background-color has-background\" style=\"padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px;margin-top:40px;margin-bottom:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<h2 class=\"wp-block-heading\">Planning private AI?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Catharsis Cyber Security is a Sydney cyber security company. We design, build and secure private AI platforms like the one in this lab, and help you decide where local or cloud AI fits.<\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/contact-us\/?type=contact&amp;service=ai-automation&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=local-ai-series&amp;utm_content=part-09-contact\" target=\"_blank\" rel=\"noreferrer noopener\">Talk to us about AI<\/a><\/div>\n\n\n<div class=\"wp-block-button is-style-outline is-style-outline--1\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/secure-ai\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=local-ai-series&amp;utm_content=part-09-end\" target=\"_blank\" rel=\"noreferrer noopener\">Explore Secure AI<\/a><\/div>\n\n<\/div>\n\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group has-background\" style=\"background-color:#f4f6f8;padding-top:28px;padding-right:32px;padding-bottom:28px;padding-left:32px\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-container-core-group-is-layout-40de7cf3 wp-block-group-is-layout-constrained\">\n\n<p class=\"wp-block-paragraph\"><strong>Keep reading the series<\/strong><\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n\n<div class=\"wp-block-button is-style-outline is-style-outline--2\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/blog\/multi-agent-stock-analysis-local-llm\/\" target=\"_blank\" rel=\"noreferrer noopener\">\u2190 Part 8<\/a><\/div>\n\n\n<div class=\"wp-block-button is-style-outline is-style-outline--3\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/blog\/running-local-ai-in-production-series-guide\/\" target=\"_blank\" rel=\"noreferrer noopener\">Series guide<\/a><\/div>\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/catharsis.net.au\/blog\/local-ai-business-workflows\/\" target=\"_blank\" rel=\"noreferrer noopener\">Next: Part 10 \u2192<\/a><\/div>\n\n<\/div>\n\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>We ran a Telegram AI agent on local models in our lab. It gave bad answers, then refused to start, then refused every request. Each time, the cause was the part of the prompt nobody types. Here is what happened and how to build one that works.<\/p>\n","protected":false},"author":2,"featured_media":1104,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[69],"tags":[96,83,91,115,81,75,117,80,116,114],"class_list":["post-1105","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","tag-ai-agents","tag-ai-lab","tag-context-window","tag-hermes-agent","tag-litellm","tag-local-llm","tag-mcp","tag-ollama","tag-telegram-bot","tag-tool-calling"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11) - Catharsis | Blog<\/title>\n<meta name=\"description\" content=\"Why was our Telegram AI agent so slow? The hidden prompt cost behind it, how we cut 35k tokens to 15k for 3\u20137 s replies, and steps to build your own.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11) - Catharsis | Blog\" \/>\n<meta property=\"og:description\" content=\"Why was our Telegram AI agent so slow? The hidden prompt cost behind it, how we cut 35k tokens to 15k for 3\u20137 s replies, and steps to build your own.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/\" \/>\n<meta property=\"og:site_name\" content=\"Catharsis | Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-11T22:30:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-11-03T09:28:10+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-09.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Sajal Jain\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sajal Jain\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/\"},\"author\":{\"name\":\"Sajal Jain\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/person\\\/f0826efb92a7aaf8d46b24715990e099\"},\"headline\":\"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11)\",\"datePublished\":\"2026-10-11T22:30:00+00:00\",\"dateModified\":\"2026-11-03T09:28:10+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/\"},\"wordCount\":3231,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-09.jpg\",\"keywords\":[\"AI agents\",\"AI lab\",\"context window\",\"Hermes Agent\",\"LiteLLM\",\"local LLM\",\"MCP\",\"Ollama\",\"Telegram bot\",\"tool calling\"],\"articleSection\":[\"Artificial Intelligence\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/\",\"name\":\"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11) - Catharsis | Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-09.jpg\",\"datePublished\":\"2026-10-11T22:30:00+00:00\",\"dateModified\":\"2026-11-03T09:28:10+00:00\",\"description\":\"Why was our Telegram AI agent so slow? The hidden prompt cost behind it, how we cut 35k tokens to 15k for 3\u20137 s replies, and steps to build your own.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#primaryimage\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-09.jpg\",\"contentUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/local-ai-series-part-09.jpg\",\"width\":1280,\"height\":720,\"caption\":\"A smartphone showing a chat conversation\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/telegram-ai-agent-local-llms\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/\",\"name\":\"Catharsis | Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#organization\",\"name\":\"Catharsis | Blog\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/catharsis_au.jpg\",\"contentUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/catharsis_au.jpg\",\"width\":215,\"height\":60,\"caption\":\"Catharsis | Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/#\\\/schema\\\/person\\\/f0826efb92a7aaf8d46b24715990e099\",\"name\":\"Sajal Jain\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/Sajal-copy-96x96.jpg\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/Sajal-copy-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/wp-content\\\/uploads\\\/2019\\\/01\\\/Sajal-copy-96x96.jpg\",\"caption\":\"Sajal Jain\"},\"description\":\"Cyber Security Enthusiast | OSCP | CEH | CHFI | CNSS | Master of IT Security &amp; Master of IT Management\",\"url\":\"https:\\\/\\\/catharsis.net.au\\\/blog\\\/author\\\/sajal-jain\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11) - Catharsis | Blog","description":"Why was our Telegram AI agent so slow? The hidden prompt cost behind it, how we cut 35k tokens to 15k for 3\u20137 s replies, and steps to build your own.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/","og_locale":"en_US","og_type":"article","og_title":"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11) - Catharsis | Blog","og_description":"Why was our Telegram AI agent so slow? The hidden prompt cost behind it, how we cut 35k tokens to 15k for 3\u20137 s replies, and steps to build your own.","og_url":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/","og_site_name":"Catharsis | Blog","article_published_time":"2026-10-11T22:30:00+00:00","article_modified_time":"2026-11-03T09:28:10+00:00","og_image":[{"width":1280,"height":720,"url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-09.jpg","type":"image\/jpeg"}],"author":"Sajal Jain","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Sajal Jain","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#article","isPartOf":{"@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/"},"author":{"name":"Sajal Jain","@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/person\/f0826efb92a7aaf8d46b24715990e099"},"headline":"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11)","datePublished":"2026-10-11T22:30:00+00:00","dateModified":"2026-11-03T09:28:10+00:00","mainEntityOfPage":{"@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/"},"wordCount":3231,"commentCount":0,"publisher":{"@id":"https:\/\/catharsis.net.au\/blog\/#organization"},"image":{"@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#primaryimage"},"thumbnailUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-09.jpg","keywords":["AI agents","AI lab","context window","Hermes Agent","LiteLLM","local LLM","MCP","Ollama","Telegram bot","tool calling"],"articleSection":["Artificial Intelligence"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/","url":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/","name":"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11) - Catharsis | Blog","isPartOf":{"@id":"https:\/\/catharsis.net.au\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#primaryimage"},"image":{"@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#primaryimage"},"thumbnailUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-09.jpg","datePublished":"2026-10-11T22:30:00+00:00","dateModified":"2026-11-03T09:28:10+00:00","description":"Why was our Telegram AI agent so slow? The hidden prompt cost behind it, how we cut 35k tokens to 15k for 3\u20137 s replies, and steps to build your own.","breadcrumb":{"@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#primaryimage","url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-09.jpg","contentUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2026\/11\/local-ai-series-part-09.jpg","width":1280,"height":720,"caption":"A smartphone showing a chat conversation"},{"@type":"BreadcrumbList","@id":"https:\/\/catharsis.net.au\/blog\/telegram-ai-agent-local-llms\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/catharsis.net.au\/blog\/"},{"@type":"ListItem","position":2,"name":"Why Was Our Telegram AI Agent So Slow? The Hidden Prompt Cost (Part 9 of 11)"}]},{"@type":"WebSite","@id":"https:\/\/catharsis.net.au\/blog\/#website","url":"https:\/\/catharsis.net.au\/blog\/","name":"Catharsis | Blog","description":"","publisher":{"@id":"https:\/\/catharsis.net.au\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/catharsis.net.au\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/catharsis.net.au\/blog\/#organization","name":"Catharsis | Blog","url":"https:\/\/catharsis.net.au\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/catharsis_au.jpg","contentUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/catharsis_au.jpg","width":215,"height":60,"caption":"Catharsis | Blog"},"image":{"@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/catharsis.net.au\/blog\/#\/schema\/person\/f0826efb92a7aaf8d46b24715990e099","name":"Sajal Jain","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/Sajal-copy-96x96.jpg","url":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/Sajal-copy-96x96.jpg","contentUrl":"https:\/\/catharsis.net.au\/blog\/wp-content\/uploads\/2019\/01\/Sajal-copy-96x96.jpg","caption":"Sajal Jain"},"description":"Cyber Security Enthusiast | OSCP | CEH | CHFI | CNSS | Master of IT Security &amp; Master of IT Management","url":"https:\/\/catharsis.net.au\/blog\/author\/sajal-jain\/"}]}},"_links":{"self":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts\/1105","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/comments?post=1105"}],"version-history":[{"count":4,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts\/1105\/revisions"}],"predecessor-version":[{"id":1221,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/posts\/1105\/revisions\/1221"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/media\/1104"}],"wp:attachment":[{"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/media?parent=1105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/categories?post=1105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/catharsis.net.au\/blog\/wp-json\/wp\/v2\/tags?post=1105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}