Elyra · · 5 min read

Teaching the Agent How to Work: Elyra 0.9.38

Elyra 0.9.38 shifts the model from having good tools to using them well: a working-method section in the system prompt, verification commands derived from your stack, smarter edit-failure handling, per-turn thinking levels, and pruning of stale tool output.

Teaching the Agent How to Work: Elyra 0.9.38

For most of this year, we've been building infrastructure: a model registry that tracks every provider, smart routing, a decision log, cost receipts, compaction that runs before disaster instead of after. Solid plumbing. Then someone reviewed Elyra with fresh eyes and asked a question that stung a little:

"The infrastructure is in order. But where do you tell the model how to actually work?"

They were right. Elyra 0.9.38 is our answer — six changes that shift the model from having good tools to using them well.

Why this release

Here's what our system prompt said about working method before this release: "Be concise in your responses." "Show file paths clearly." That was essentially it. A role, a tool list, and two lines of etiquette.

Everything else — read before you edit, verify after, don't gold-plate, ask when unsure — we left to the model's judgment. And frontier models do have judgment. But judgment without instruction is inconsistent: one session the agent reads the file first, the next it edits from memory and fails three times in a row on the same oldText.

The reviewer's sharpest observation was that thirty lines of prompt would deliver more than three thousand lines of code. So we wrote the thirty lines — and then built the code that makes each line concrete.

How to work

The system prompt now has a section called exactly that. Eight rules:

How to work:
- Understand before you change: read the code you are about to modify
  and the code that calls it. Never edit a file you have not read in
  this session.
- Explore deliberately: search for symbols and usages before assuming
  structure. Read only the regions you need from large files.
- Prefer small, targeted edits over rewrites. Match the surrounding
  style; do not rename, reformat, or restructure beyond what the task
  requires.
- When the intent is ambiguous or a change would touch behavior beyond
  the request, ask before proceeding rather than guessing.
- Verify your work: after changing code, run the project's own checks
  when they exist. Do not report success you have not observed.
- Stop when the task is done. Do not add features, abstractions, or
  tests that were not asked for. Mention follow-ups instead.
- When something fails twice the same way, change approach instead of
  retrying the same action.

The rules are tool-aware: a read-only session doesn't get editing rules, and without bash the "run the checks" line becomes "re-read what you edited." The prompt never tells the model to do something it can't.

But "run the project's own checks" raises an obvious question: which checks?

The prompt now names the commands

Elyra has known for a while whether you're in a Laravel, pnpm, or Cargo project. It just never turned that knowledge into instructions. Now the stack detector derives the verification commands and puts them right in the prompt:

# Technology Stack

TALL stack project (Tailwind, Alpine.js, Laravel, Livewire, Flux UI). Laravel 12.0, Livewire 4.0, Flux UI 2.1, Tailwind CSS 4.0, Vite 6.0

Project checks (run the relevant ones after changes, before reporting done):

  • typecheck: vendor/bin/phpstan analyse (composer.json)
  • lint: vendor/bin/pint --test (composer.json)
  • test: vendor/bin/pest (composer.json)
  • build: npm run build (package.json scripts.build)

It reads package.json scripts and picks the right package manager from your lockfile, understands composer.json well enough to prefer your composer scripts over raw vendor binaries, and handles Cargo, Go, and Python projects — including bare Rust repos with no "framework" at all. The model that sees twelve clippy warnings before saying "done" ships better code than the one that doesn't.

Skills got the same treatment. If your project is Laravel + Livewire and you have a livewire-testing skill, it's now listed first with a note: "Skills relevant to this project's stack (Laravel, Livewire): livewire-testing. Read these first when the task touches that area." No more hoping the model picks the right one from a flat list.

Failing smarter

Everyone who has watched an agent work has seen this: edit fails with "text not unique," the model tries again with slightly more context, fails again, tries a third time. Blind retries.

Two fixes. First, the errors themselves now point somewhere:

Found 3 occurrences of the text in src/Billing.php at lines 12, 48, 97.
The text must be unique - include a distinguishing line above or below.
Could not find the exact text in src/Billing.php. Closest match: line 42
contains the first line of your oldText; the following lines differ.
Re-read around line 42 before retrying.

Second, Elyra counts. On the second consecutive failure against the same file, the tool result gains an instruction the model can't miss:

[Elyra] This is failure #2 editing src/Billing.php in a row. Stop retrying
blind: read the file region you intend to change and rebuild oldText from
the fresh content.

A success resets the counter. The escalation is in the tool result, not the prompt — so it arrives exactly when it's needed and nowhere else.

Spending less on what doesn't matter

Two changes attack cost from different angles.

Thinking per turn. Smart routing already picked a cheaper model for simple turns. Now it also picks a cheaper thinking level. A directory listing on a fast-tier turn runs at minimal; a refactor on the powerful tier gets your full session level. Your setting is a ceiling — routing only ever turns the dial down, never up, and the footer and /thinking still show what you chose. /route tells you what will happen:

/route

Next turn tier: fast — short read-only request Thinking: medium → minimal for this turn (session level unchanged) ▶ fast: gemini-3.8-flash balanced: glm-5.3 powerful: claude-sonnet-5

Stale tool output pruning. That 50 KB file you read on turn 3 was sitting verbatim in the context on turn 40. Both Anthropic and OpenAI say old tool output is the cheapest thing to drop, so we drop it — at request time only:

[read src/models.generated.ts, 21400 lines – pruned from context; re-read if needed]

Results older than six assistant turns and larger than 2000 characters get this treatment. Errors are never pruned (they're diagnostic), images are never pruned, and your session history and compaction are completely untouched — this is purely what goes over the wire. Because read output carries per-line hashes, re-reading a file the model thinks changed is cheap and certain.

Get it

elyra update

You'll notice the difference in the first session: the agent reads before it edits, names the check it's about to run, and stops when it's done. If it feels too diligent for a quick throwaway task, that's worth telling us — the rules are meant to be a floor, not a ceremony.