<h2>The cache problem nobody talks about</h2><p>Every time you send a message to Claude, Elyra includes your system prompt, tool definitions, pinned files, and the full conversation history. Anthropic caches this content so you don't pay full price for the same prefix on every request. The cache works on prefixes — if the first N bytes of your request match a previous request, those bytes are served from cache at a 90% discount.</p><p>Elyra was leaving money on the table. Here's why.</p><p>The first message in every conversation contained two things: your pinned files and the current date. They were packed into the same content block, date first:</p><pre><code>[
  { "type": "text", "text": "Current date: 2026-05-23" },
  { "type": "text", "text": "[Pinned: src/schema.ts]\n```\n...800 lines...\n```" }
]
</code></pre><p>The date changes at midnight. When it does, the entire cache for everything after the system prompt is invalidated — including those 800 lines of pinned schema that haven't changed in weeks. On a project with several pinned files, that's thousands of tokens re-processed at full price every morning for no reason.</p><p>The fix is embarrassingly simple: put the stable content first.</p><pre><code>[
  { "type": "text", "text": "[Pinned: src/schema.ts]\n```\n...800 lines...\n```" },
  { "type": "text", "text": "Current date: 2026-05-23" }
]
</code></pre><p>Now the pinned files form a stable prefix. Even when the date changes, the cache still covers system prompt + tools + pinned files.</p><p>We also added a fourth cache breakpoint. Anthropic allows up to four, and we were only using three (system prompt, last tool, last user message). The new breakpoint sits on the first user message — the one containing pinned files — so the stable context prefix gets its own explicit cache boundary.</p><p>The result: fewer cache misses, lower costs, no behaviour change. You won't notice anything different except a slightly smaller bill.</p><h2>Teaching the agent to read code, not guess at it</h2><p>When Elyra's agent needs to find where a function is defined, it runs <code>grep</code>. When it needs to understand who calls a method, it runs <code>grep</code> again. Grep is fast and usually good enough. But "usually" isn't "always."</p><pre><code>&gt; Find all callers of validateUserInput

Agent runs:    grep -r "validateUserInput" src/
Agent reads:   14 results across 8 files
Agent reads:   4 of those files to understand context
Agent realises: 3 results were comments, 2 were imports, 1 was a type definition
Actual callers: 4
Tokens spent:  ~12,000
</code></pre><p>A TypeScript language server already knows the answer. It has the full type graph in memory. "Find references" is a single RPC call that returns exactly the four call sites, with zero false positives.</p><p><code>@elyracode/lsp-typescript</code> bridges that gap. Install it, and the agent gets four new tools:</p><pre><code class="language-bash">elyra install @elyracode/lsp-typescript
</code></pre><p>Tool What it does <code>lsp_definitions</code> Go to definition — resolve where a symbol is declared <code>lsp_references</code> Find all references — every usage across the project <code>lsp_diagnostics</code> Get compiler errors for a file without running the build <code>lsp_hover</code> Get the resolved type signature and JSDoc for a symbol</p><p>The extension starts <code>typescript-language-server</code> in the background when your session begins (if it finds a <code>tsconfig.json</code>), and shuts it down when the session ends. The agent uses these tools instead of grep when it needs semantic precision.</p><p>Here's what the same "find callers" task looks like with LSP:</p><pre><code>&gt; Find all callers of validateUserInput

Agent runs:     lsp_references(file: "src/validation.ts", line: 42, column: 17)
Agent receives: 4 locations with file paths and line numbers
Tokens spent:   ~800
</code></pre><p>Same answer. 15× fewer tokens. No false positives from comments, imports, or type annotations.</p><h3>When it helps most</h3><p>The token savings are largest on tasks that involve understanding how code connects:</p><ul><li><p><strong>Refactoring</strong> — rename a function and update all call sites. With <code>lsp_references</code>, the agent finds every usage on the first try instead of iterating through grep results.</p></li><li><p><strong>Bug investigation</strong> — trace a value through the codebase. <code>lsp_definitions</code> jumps straight to the source instead of scanning for string matches.</p></li><li><p><strong>Type errors</strong> — <code>lsp_diagnostics</code> gives the same errors as <code>tsc --noEmit</code> but for a single file, without running the full type checker. The agent can check its work after each edit.</p></li><li><p><strong>Understanding unfamiliar code</strong> — <code>lsp_hover</code> shows the resolved type of any expression. No need to read the entire file to understand what a variable holds.</p></li></ul><h3>Prerequisites</h3><p>Your project needs two things:</p><ol><li><p>A <code>tsconfig.json</code> (the extension skips activation without one).</p></li><li><p><code>typescript-language-server</code> installed — either locally or globally:</p></li></ol><pre><code class="language-bash">npm i -D typescript-language-server
</code></pre><p>The extension finds the binary automatically. If it's not installed, it logs a message and the agent continues working with its standard tools. No breakage, no popups.</p><h3>It's an extension, not core</h3><p>We deliberately built this as a separate package rather than baking it into Elyra's core. Language servers are heavy — <code>tsserver</code> uses 100–500 MB of RAM and takes a few seconds to start. If you're working on a Python project or writing shell scripts, you shouldn't pay that cost.</p><p>The extension pattern also means the community can build <code>lsp-python</code>, <code>lsp-go</code>, or <code>lsp-rust</code> without waiting for us. The only thing these extensions need from core is <code>registerTool()</code> and the session lifecycle events, both of which are already stable.</p><h2>Get it</h2><pre><code class="language-bash">elyra update
elyra install @elyracode/lsp-typescript
</code></pre><p>The cache optimisation applies automatically — no action needed.</p><hr><p><em>Elyra v0.7.7 — </em><a target="_blank" rel="noopener noreferrer nofollow" href="https://elyracode.com/changelog"><em>changelog</em></a></p>