Elyra · · 5 min read

Elyra 0.9.55: Being Easy to Work With When Nobody’s Watching

JSON mode now exits 1 on failure, --session no longer eats your prompt in scripts, and the JSON stream is finally documented the way it actually behaves.

Elyra 0.9.55: Being Easy to Work With When Nobody’s Watching

Most of the time Elyra has an audience. You type, it answers, and you see everything it does. But more and more, Elyra runs with nobody looking: in CI jobs, in scripts, and under daemons that hand it a task and collect the result.

This release is for that audience. It’s small, but every line in it comes from a real failure.

A story from the queue

We have a project called Félagi. It’s a work portal with a small daemon that runs on a couple of Mac minis. When an issue is assigned to an agent, the daemon picks it up, starts Elyra, streams the output back, and reports the outcome.

Last week, the first task this workspace ever had went into the queue. The daemon claimed it in under a second and failed one second later:

Error: Unknown option: --output-format

The daemon’s adapter was speaking an older dialect of Elyra’s CLI. That part was on the daemon’s side to fix. But while tracing it end to end, we found two things on our side that would have bitten anyone driving Elyra from a program. Both are fixed in 0.9.55.

Fix 1: a failed run now looks like a failure

Why

When you run Elyra in JSON mode, it streams every event as a line of JSON:

echo "Fix the failing test" | elyra --mode json

If the model request failed (bad API key, provider down, rate limit after all retries), the error was right there in the stream. But the process exited with code 0.

For a human that’s fine; you’d see the error. For a script, exit code 0 means “all good”. A CI job would turn green. A daemon would mark the task done and bill the time.

Text mode already got this right. JSON mode didn’t.

How it works now

If the final request fails or is aborted, JSON mode exits with code 1 and writes the error to stderr, exactly like text mode:

$ echo "Say hi" | elyra --mode json --api-key sk-ant-invalid > run.jsonl
401 invalid x-api-key
$ echo $?
1

The stream itself is unchanged, so anything that already reads it keeps working. You just also get a truthful exit code:

if ! elyra --mode json < task.md > run.jsonl; then
  echo "Agent run failed" >&2
  exit 1
fi

A small detail, but checking $? is exactly what a careful script does.

Fix 2: --session no longer swallows your prompt

Why

You can continue an earlier session with --session and an id or a unique prefix:

echo "Now add tests" | elyra --mode json --session 01a15593

If that session was started in a different directory, interactive Elyra helpfully asks:

Session found in different project: /work/other
Fork this session into current directory? [y/N]

That question is read from stdin. In a script, stdin is where your prompt is. So Elyra read the first line of your prompt as the answer, decided it wasn’t “y”, printed “Aborted.”, and exited 0. No output, no error, and no idea what happened.

How it works now

In print, JSON, and RPC mode, Elyra doesn’t ask. It fails clearly with exit code 1 and tells you what to do:

Session 01a15593 belongs to /work/other.
Use --fork 01a15593 to copy it into this directory.

If you meant to bring it over:

echo "Now add tests" | elyra --mode json --fork 01a15593

Interactive mode still asks, because there a question is the friendly thing to do.

The JSON stream, documented properly

Why

The Félagi adapter broke partly because it guessed at field names. That’s on us too: docs/json.md described the stream as it was a few versions ago. It was missing half the event types and said nothing about how to actually read a run.

What’s there now

The documentation lists every event the stream emits, including the session-level ones (auto_retry_start, compaction_start, smart_routing, and friends), and has a new section on reading a run:

  • Session id: only in the first line, the header. Events don’t repeat it.

    {"type":"session","version":3,"id":"01a15593-…","cwd":"/work/shop"}
    
  • Tool calls: tool_execution_start has toolName and args; tool_execution_end has the result and isError.

  • The final answer: there’s no separate result event. It’s the last assistant message in agent_end.

  • Failure: that last message has stopReason "error" or "aborted", and the process exits 1.

  • Cost: every assistant message carries usage with cost.total already priced in dollars. Tools that call a model themselves, like the oracle, report theirs as details.modelUsage. Add them up and you have the cost of a run.

  • Noise: message_update fires for every streamed chunk. Most consumers only want message_end.

A quick way to get just the final answer with jq:

echo "What does this repo do?" | elyra --mode json \
  | jq -r 'select(.type == "agent_end")
           | [.messages[] | select(.role == "assistant")] | last
           | .content[] | select(.type == "text") | .text'

And the total cost of a run:

elyra --mode json < task.md \
  | jq -s '[.[] | select(.type == "message_end" and .message.role == "assistant")
            | .message.usage.cost.total] | add'

With that page in hand, the Félagi adapter was rewritten against the real stream, tested against recorded runs, and is now picking up work. The whole recording cost about a fifth of a cent.

Fresh models

As usual, the model registry has been refreshed:

  • New: Meta Muse Spark Open (open weights, $1.25/$4.25 per million tokens), NVIDIA Nemotron 3.5 Super VL (vision and reasoning, with a free tier on OpenRouter), Reflection Beam 1.0, Inception Mercury 3, a new DeepSeek V4.1 Flash snapshot, and FLUX 3 and Krea K3 image models on OpenRouter.

  • Gone from OpenRouter: Claude Sonnet 4 and DeepSeek R1.

  • Price moves on OpenRouter: GPT-5.6 Sol doubled; Kimi K3 got noticeably cheaper.

Your default models are unchanged.

Upgrade

elyra update

If you drive Elyra from scripts, CI, or your own tools, this is a release worth having: failures now look like failures, a stray session id can’t eat your prompt, and the stream you’re reading is finally documented the way it actually behaves.

It’s not a flashy release. It’s a dependable one, and when nobody’s watching, that matters more.

Happy building.

— The Elyra team