---
title: "2026.08.27"
date: 2026-08-27
extra:
  version: "2026.08.27"
  build: 15
  change_id: mlqwrkzuzutr
  highlights:
    - text: "Every conversation shows what it truly cost, with a full spend breakdown"
    - text: "The embedded engine now runs your local models on Android"
    - text: "Fetch tools reshape responses with jq, model and template filters"
      path: "/tools"
    - text: "Ask your other devices for a missing API key"
      path: "/settings/devices"
    - text: "Unsent drafts are kept, and follow you between devices"
      path: "/conversations"
---

This release is about trust and reach: costs you can verify down to a single
tool call, local models on Android through the embedded engine, fetch tools
that reshape a response before your agent reads it, and API keys and unsent
drafts that move between your devices. As always, BYLM is a constructor — you
bring the provider account or the model file, the tools, and the prompts.

## Costs you can trust

Every assistant reply, title, summary, tool call and sub-agent run now records
its spend durably, so a conversation's cost no longer changes with scroll
position or shrinks when a failed reply is retried. A one-time migration
brings your existing conversations' recorded costs in too.

The conversation's total now includes what its tools spent, itemised on its
own row. A new per-conversation spend page breaks the total down by purpose,
model (input/cache/output tokens and per-phase price), tool, and
sub-conversation — and a Steps view shows each request with what answering it
cost, endpoint fees and filter stages priced apart. Each tool tile shows its
call's duration, tokens and dollars, ticking live while it runs.

Money stopped leaking at the edges as well: a call that spends and then fails,
parks for your input, or runs as a single-shot (non-streaming) completion now
counts what it charged, and parallel OpenRouter calls no longer swap or
double-count their costs.

## Local models on Android

The embedded llama.cpp engine now works on Android: point it at a model file
and generate on the phone's own CPU. On every platform the engine gained
device-local tuning — context size, KV-cache quantization and flash attention,
settable per provider and overridable per model — plus a thinking budget that
stops a reasoning model from spending the whole turn thinking.

Speculative decoding grew past Gemma-style MTP heads: DSpark and DFlash draft
heads pair in the bundle form, speculation now works on tool-calling and
structured-output turns too, and the response's performance panel shows the
draft head's speed-up and acceptance histogram. The pinned llama.cpp moved
forward, bringing upstream's newer model architectures and backend fixes, and
the engine's per-token debug chatter no longer floods the log.

## Fetch tools that shape their own responses

A fetch tool can now run its response through a chain of output filters before
the agent reads it:

- A **jq filter** reshapes a JSON response — `.items | map(.name)` instead of
  a paid summarisation step — and can read the response headers.
- A **model filter** runs the response past any configured model, one question
  and no loop, with an input cap, a timeout, and an optional JSON schema to
  hold the answer's shape. Its prompts can quote the response headers.
- **Template filters** can declare their output as text, Markdown or JSON,
  render the response headers and the request, and treat an empty render as an
  error.

The form warns while you build a chain whose stages cannot read each other,
instead of letting a paid call discover it. Error handling is configurable per
endpoint: which HTTP statuses count as errors, and an optional error template
that turns a raw 500 body into a clear failure message. A tool can pin the
response content-type it expects, advertise it in the Accept header, and
refuse anything else.

Diagnosis got a real home: every fetch call keeps its raw response, each
filter stage's output, timings, and the exact prompt a model filter sent —
opened from a Response details row on the tile, syntax highlighted, with
re-indent, line-wrap and render-as-Markdown switches. A running call says
which stage it is on ("Template · step 2 of 4"), a waiting one names the
failure and the attempt ("Rate-limited — retrying in 42s, attempt 2 of 4"),
and a paid endpoint's own fee can be read from its response and counted with
everything else. The tool test screen runs through the production retry loop
and shows the same captures, attempts and spend.

## API keys and drafts across your devices

A device missing a provider's or fetch tool's API key can now ask your other
devices for it — from the key field, the detail page, or in batch from a
banner on the provider and tool lists. The device holding the key approves or
declines on its Devices page (several asks in one tap), and the key arrives
right under the field you asked from, ready to accept. Missing keys are
flagged on lists and detail pages before a request fails, a 401/403 points at
the key rather than dumping a raw error, and a provider that needs no
authentication can say so.

Unsent messages stopped being disposable: leave a conversation or the whole
app mid-sentence and the draft — attachments and caret included — is waiting
when you come back, marked on the conversation list. With sync on, a draft
started on one device is offered on the next, named after the device it came
from, with "Use here" and "Discard".

Multi-device conversations got honest, too: a conversation being answered on
another device says so (and for how long), the list marks rows still
generating, opening a running turn mid-flight replays what has already been
produced, and a second device asks before re-running a turn another device
already owns — so you are never billed twice for one reply.

## Reading, selecting, and quoting

Text selection in conversations now works the way you expect: drag past the
edge of the screen and the list scrolls, one selection spans several messages,
tables and code blocks select with the text around them, and a finished
reply's last paragraph joins the selection. Copies keep their Markdown — bold
markers, table pipes, fenced code — and a partial table selection pastes as a
table under the headings it came from. Select any passage and Quote it into
the composer as a Markdown quote.

Tool results render by content type — Markdown, formatted JSON, inline image
and file previews — with syntax highlighting, and the assistant's thinking
renders as Markdown like the reply it precedes. Links in messages and tool
results open behind a confirmation naming the real destination. The
conversation header's cost figure, the centred jump-to-bottom button, and a
progress line that names the running tools round out the reading experience.

## Context under your control

Compacting a conversation now asks first: the dialog spells out the cut, lets
you keep the last few turns in context, and can tell the summarizer what
matters in the messages being dropped. A running compaction is visible and
cannot be started twice. And a compaction can be taken back — from the
snackbar right after, or from the boundary divider long after — releasing the
cut and cancelling the summary it started. When compaction is configured to
summarize, the manual action now actually summarizes; the bare cut is named
"Clear context" for what it does.

## Tools you can tell apart, everywhere they appear

Every tool can wear an icon — a glyph, an emoji, or artwork fetched from a
URL, which the app can find from the endpoint itself — shown in the lists, the
picker, an agent's tools, and on each call in a conversation. The tools list
gained search and kind filters, agent tool-picking became a searchable
full-screen picker, and deleting a tool first names the agents and counts the
conversations still using it.

A tool synced from a newer app version no longer vanishes (taking its whole
kind with it): it is listed under "Not available on this device" with the
reason, and a conversation names the tools it would run without, above the
composer. The tools that ship with the app are labelled Built-in rather than
Global.

## Providers and agents

Star the models you actually use on a provider and they sort to the top of
every model list, synced across devices. Copy a provider or a fetch tool into
a pre-filled create form — asking first whether the copy carries its API key.
Agents gained an optional short description, shown on the list and detail
pages and to calling agents; the agents list gained search.

Sub-agent calls became first-class: the spawned conversation streams to
whoever opens it and its Stop button works, the open link appears the moment
the run starts, the tile reports each step, and the run's tokens and cost land
on the call that ordered it.

Agent-built tools got sturdier rails: a mistyped config field is rejected by
name instead of silently ignored or crashing opaquely, values outside a
field's range are refused at save time, and an agent can reuse a secret one
tool already holds — after you approve — without ever seeing its value.

## The app tells you what changed

Settings → What's new lists every shipped release's highlights and full notes,
readable offline, opening on the release you are running — and highlights
navigate straight to the screen they describe. After an update, the
conversation list greets you once with what the new version changed. Settings
→ Open source credits every component this build actually contains, with its
license in full; the same inventory is published on the website.

## And the rest

- The app opens to the conversation list about a second faster on cold start.
- On wide screens the navigation drawer becomes a permanent, collapsible
  sidebar, and the menu button badges the jobs, unread conversations and key
  offers waiting behind it.
- Back on a top-level page opens the navigation menu; leaving the app takes a
  second, deliberate press.
- Settings that cascade (global → workspace → agent) now merge field by field,
  show the value they inherit in the field itself, and say what a reset would
  restore. The app-wide layer lives on one Global settings page beside the
  workspaces.
- Conversation titles and summaries stopped breaking: a truncated or fenced
  enrichment reply no longer becomes the title, thinking models get room to
  think, and the reply cap fits the summary length you allow.
- Prices in a reply no longer render the words between them as a math formula.
- An image attached to an unsent draft survives the orphan-blob cleanup.
