Skip to content

Platform

Changelog

What shipped, newest first. This page is rendered from CHANGELOG.md in the repository at build time.

Releases of the Lobstack app are marked App; the rest are the website, the Console and the API. Entries below the current line of work carry the version numbers they shipped under, dated by the day the last change in them landed. Anything not yet cut into a version sits under Unreleased. For what is deployed rather than what is written down, the security page is the more useful read.


Unreleased

Work that is written and not yet merged to main. It is here rather than in a version because a branch is not a release, and dating it as one would make this file say something the deployment does not.

Fixed

  • The Console was paywalling accounts that had already paid. Overview rendered "No subscription yet — Subscribe to get a key and an allowance" across the whole surface, and two independent bugs put it there. /api/agent/status only answered hasSubscription inside its if (!agent) branch, so an account WITH a runtime got a response that omitted the field entirely, and !!undefined is false — a customer with an active subscription and a running agent was shown a paywall on their own Console. The read is one helper called on every path now, and it returns boolean | null so a failed read says "I could not tell" rather than "you have not paid".
  • A database label was missing, and some new accounts could not be created. The account status written on every new row since the agent-VM runtime was retired had no matching value in the database, so the insert was refused. A migration adds it, and every place that reads the status list now imports one shared list instead of keeping its own copy.
  • Two Stripe webhook bugs, found while proving the above. A renewal reset keyed on user_id where its own comment said "this subscription", which zeroed an older row's counter on every renewal; and a cancellation lookup whose maybeSingle() had no limit(1), so a subscription with two rows cancelled neither, silently.
  • The favicon was correct and still unreadable at the size anyone sees it. favicon.ico carried the real mark at seven sizes, and the mark's lower stroke is a gradient falling to about 47% luminance where the fold turns away from the light — which is the point of it at 512px and fatal at 16, where that end lands within a few levels of the tile behind it and disappears. A tab, a bookmark row and a search-result favicon are all 16 or 32. Those three sizes are redrawn from the silhouette, filled flat white and set larger in the tile; 48 and up are untouched. The shape does not change, and the shading is dropped only where shading cannot be resolved.

Changed

  • A key is free, so the Console stopped selling one. PLANS[0] is Free — a key, a receipt on every call, and $1 of credit every week — and POST /api/v1/keys wants a signed-in admin of an org, never a subscription. The subscription gate on Overview was selling something that was already free. It is gone: an account with no traffic lands on the first-call on-ramp that was already built for exactly that, and the shell's matching banner keeps only the one variant it can state truthfully.

App 0.11.5 2026-10-03

Read a bot’s branch in the canvas, and pair a phone by typing a code.

In the app

  • A Code tab in the canvas: this conversation’s branch with uncommitted files, a file tree marked with what changed, each file’s diff, and search.
  • Terminal shows its name in the top bar, and a Canvas button beside it puts the canvas away and brings it back (Ctrl/⌘+\).
  • Phone approvals: 15 minutes to pair instead of 5, a warning before pairing when phones can’t be notified, and a short code to type beside the QR once lobstack.ai’s matching update is live.
  • Settings section names are in Title Case.

App 0.11.4 2026-10-03

Merge a bot’s work into your own folder in one click.

In the app

  • Changes › Merge into main puts a coding bot’s work in your folder. It never overwrites edits you have not committed, and when the same lines changed it merges nothing and says so.
  • The terminal opens again for the person at the computer. 0.11.3 refused everyone.
  • Settings has a cog icon and Conversations a speech bubble, and Repository hides its label on narrower windows.

App 0.11.3 2026-10-02

A canvas with tabs, a browser you can drive, and workflows. Read the post.

In the app

  • The canvas has tabs: files, a bot’s browser, routines and runs open side by side, and a file posted while you read another opens behind it.
  • Designs show at their real size, with their palette and fonts. Ask for options and they appear side by side.
  • The browser, live: every click a bot makes is marked on the page, you can take over with an address bar and every key, and a bot asks for you at a sign-in or a payment instead of guessing.
  • Routines and triggers read as a recipe, with a history of every run. Dry Run does the real look-ups and changes nothing.
  • Workflows: a routine can have steps, each with its own bot, tools, approval, Only if and For each, and a failed step can resume from where it stopped.
  • A terminal under the view, which also shows every command a bot runs as it runs.
  • Bots have a tool for what they are asked to do, including adding rows to an existing table.
  • 0.11.1 and 0.11.2 were never released; 0.11.3 includes everything they were to carry.

App 0.11.0 2026-10-01

Hand a bot a whole job, and work on files side by side.

In the app

  • Delegate a whole job: the bot writes a plan, nothing runs until you approve it, and it works in the background.
  • A canvas beside the conversation for the files a bot makes.
  • Settings › Memory lists what your bots remember, and what they know about you stays on this computer.
  • Each bot keeps a list of its past conversations.
  • Quick, Deliberate or Deep thinking.
  • Watch a bot’s browser, and take over.

App 0.10.1 2026-09-30

Triggers from webhooks, folders and tables.

In the app

  • Triggers start a bot from a webhook, a folder or a table.
  • Ask a bot to set one up for you.
  • Schedules follow your time zone, and a missed run offers Catch up instead of firing late.

App 0.10.0 2026-09-30

Approve from your phone, and share bots with your team. Read the post.

In the app

  • Approve from your phone.
  • Share bots with your team.
  • Bots make designs, decks and spreadsheets, not only documents.
  • Tables, and every file in the app in one place.
  • What every run cost, step by step, and who pays for it.

App 0.9.0 2026-09-29

Bots search the web and read pages, with nothing to set up.

In the app

  • Web search and page reading are built in.
  • Most connectors connect with one Sign in button, and there are twenty more of them.
  • A library of skills to add to your bots.

App 0.8.0 2026-09-28

Lob Bot becomes Lobstack. Read the post.

In the app

  • Lob Bot is now called Lobstack. Nothing else changes.

App 0.7.0 2026-09-28

Sign in with Lobstack, and $5 of credit to start. Read the post.

In the app

  • Sign in with Lobstack, with credit to start.
  • Home and Library.
  • A coding bot’s changes, and a pull request from them.
  • Connectors sign in instead of asking for pasted tokens.

App 0.6.0 2026-09-27

Bots wake when a CI run fails or an issue is assigned.

In the app

  • Bots react to something happening, not just to a clock.
  • A bot can split work between several colleagues and wait for them.
  • Commands no longer reach the whole internet by default.
  • Skills can be edited.

App 0.5.0 2026-09-27

Every bot gets its own browser.

In the app

  • Every bot has its own browser.
  • The app tells you when there is a new version.
  • Bots hand you files, and read the ones you send.
  • Memory has a budget you can see.

App 0.3.0 2026-09-20

Pick the engine: Lobstack, Copilot or your own key.

In the app

  • Choose the engine.
  • It keeps running when you close the window.
  • Bots can talk to each other in a channel.
  • Workspaces.

0.26.0 2026-09-18

Fixed

  • Webhooks were unreachable twice over. The surface was gated on plan_tier being performance or enterprise — tiers no current plan writes — so the gate could never open for an account created after the pivot. Behind it the route answered 404 regardless: getAgentForUser filtered on a hand-written status list that omitted no_machine, which is the status every agent row born since checkout stopped building machines carries. Both sides read one entitlement predicate now, planAllowsWebhooks in src/lib/entitlements.ts, derived from PLANS rather than typed — including lib/webhooks.ts, the dispatcher, which was still resolving plan_tier against the retired messages-per-month catalogue and would have silently skipped an endpoint the Console had just accepted. Three of the four event types have no dispatcher at all; they are marked in the UI and dropped from the default selection rather than deleted, because the API still accepts and stores them.
  • The Settings key-storage sentence was backwards. It said a provider key "is sent securely to your VM and never stored in our database in plain text". The routing route writes it verbatim to agent_instances.ai_api_key, a plain TEXT column the Gateway reads back on every call. There is no application-layer encryption, so the page says that now and asks for a key you can scope and revoke.
  • /terms and /privacy still described the retired VM line as the Service. Terms promised, in its security section, "a dedicated virtual machine for each agent that has one deployed". No agent can have one — src/lib/account.ts creates every row no_machine and never provisions — so the Service description, the SLA scope, the cancellation, termination and API-key clauses were rescoped to what is actually operated: a stateless API route, with nothing of yours running on our infrastructure between requests. No pricing number changed.
  • "Name a model and you get it" was never what the router did. selectModel walks tiers upward from nano and a named model sets the ceiling, not the answer — ask for a flagship with a one-line greeting and the nano lead model serves it, which /docs/gateway/routing already tabulated. /about says ceiling now, and /gateway, whose routing diagram only ever showed auto, says what naming a model does at all.
  • A migration had been applied to production with no row in the ledger. 20260910_spend_metering.sql was run as raw SQL rather than through apply_migration, and nothing noticed because nothing looked. All 18 objects it declares were verified present in production and the migration is idempotent by construction, so a row was inserted at its chronological position — the equivalent of supabase migration repair --status applied. Looking for that gap turned up a larger one, which is recorded rather than papered over: the ledger holds 56 applied migrations while supabase/migrations/ holds 28 hand-written files whose names do not match it, 34 applied migrations have no file in the repository at all, and about 350 KB of applied SQL exists only inside the database it would be needed to rebuild. So supabase db push would not reproduce production and db reset would produce a different schema. npm run check:migrations fails when a file is not accounted for — which is exactly how this went unnoticed — and runs offline, so CI needs no credential.
  • The social card had drifted from the headline it was a picture of. The card was drawn by hand, so it carried its own copy of the headline, and that copy advertised "One API over every frontier model" while the og:description rendered directly beside it on every page said something else. A shared link showed two different sentences about the same product and nothing in CI could notice, because the headline lived inside a PNG. The card is now a capture of the real hero, so there is one headline and the card is a photograph of it.
  • Route preview reported models this deployment cannot reach. /api/gateway/route-preview previewed against the whole registry while the live path narrows to providers whose managed key is configured, and the available field the code comment promised "so the difference is visible rather than surprising" had never existed. Probed against production, only two providers have a managed key, so a customer previewing nano was shown a Google model that would in fact have been served by OpenAI. The selection runs a second time against the live constraint now, and the response says which.

Added

  • The Gateway keeps the data it used to throw away, and it is off by default. gateway_requests has 23 columns and not one of them says anything about what a request *was* — it is a complete account of what a request cost. Meanwhile selectModel computes a seven-signal complexity breakdown on every request, uses it to choose a tier, and the route narrowed the result before either write site could see it. A new routing_events table records shape and outcome, never content: a keyed hash of the last user message, its character count, the seven signal contributions as computed, the decision and the result. There is no column that could hold prompt text, which is the point — the guarantee is enforced by the shape of the table rather than by a convention someone has to remember. The hash is HMAC-SHA256 under a server-side secret and not a bare digest, because a plain SHA-256 of "summarise this" is recoverable with a word list, which is plaintext wearing a hex coat. With GATEWAY_ROUTING_EVENTS unset the message is not read, built or written, and the migration creates an empty table and leaves it empty.
  • Routing data, so a customer asking "what do you keep about my prompts?" has somewhere to read the answer. The field table is generated from ROUTING_EVENT_COLUMNS, the same constant the writer uses, so the page cannot claim we store something we do not or quietly omit something we do; a column nobody has described renders a visible warning rather than vanishing from the list. The page deliberately does not say that a model exists, that anything is trained, or that routing is learned — it is not, the capture is off in production, and the table is empty.
  • Price-aware tier ordering, behind a flag, default off. representativeModel took the first eligible entry of a hand-ordered list, and there was no price in that function: on a 3:1 blend the first entry was 15.2× the cheapest model in the standard tier, 8.7× in small and 5.2× in flagship. GATEWAY_PRICE_AWARE_ROUTING reorders the tier's candidates cheapest-first — the candidate set, the availability predicate and the BYOK provider lock are untouched, so the two modes can only ever disagree about which of the same eligible models is picked. Sorting on price alone looked right and was not: it routed to de-listed previous-generation keys the registry keeps for callers who name them, and cheapest is not a reason to serve somebody last year's model. Current-generation first, then price. On production's provider set today that changes exactly one decision, 20% cheaper; with all nine providers keyed, all five tiers improve by 50–88%. npm run check:price-aware asserts that the flag off reproduces list order, that the price-aware pick stays inside the eligible set, and that it is never more expensive.
  • /compare answers the three things we are actually mistaken for. The page graded three gateways of the same shape, which answers one of the three questions a reader arrives with — a provider's own API, a gateway like those, or a company that hosts an agent on a VM. Each now gets a section. It argues the receipt, BYOK, the local proxy and the human gate, and says in as many words that it does not argue breadth; the agent-VM column states the retirement plainly rather than implying we compete there.

Changed

  • Every platform is named on the Lob Bot download band, built or not. The section showed only the platforms a release actually carries, which answers "can I download this" and leaves "is my machine ever getting one" to be inferred from an absence — and an absence reads as abandoned rather than as next. With a Windows-only release, macOS and Linux users saw no mention of themselves at all. All three are named now; the ones with a file are a button and the ones without say "Coming soon". The roster comes from PLATFORMS, the same map the asset matcher uses, so a platform added there and forgotten on the page would otherwise simply never be mentioned. Lob Bot v0.2.0 was tagged in the lob-bot repository on the same day and its release workflow builds a Windows installer; this site serves whatever that release carries, above the 0.2.0 floor set in 0.25.0.
  • One sentence, in the four places that speak first. The canonical line — one OpenAI-compatible key, every model, a receipt on every call, and an agent that waits for you before it changes anything — had been typed separately into the root metadata, the home page's own metadata, the hero and the footer, and the four had already drifted. The hero had been opening with a catalogue figure, which is trivia to lead with when the same number sits on the Gateway card four inches below.

0.25.0 2026-09-16

Added

  • A Content-Security-Policy that was measured rather than guessed. Done carelessly a policy silently breaks fonts, analytics or the Console while every build still passes, so this started with an inventory: the built site was served and driven with a real browser across every top-level route, and every request recorded — document, script, stylesheet, font, image, media, fetch — came from the site's own origin. It is enforcing rather than report-only, and the Supabase origin in connect-src is read from NEXT_PUBLIC_SUPABASE_URL, the same variable inlined into the client bundle, so the policy cannot name a project the code does not dial. Three origins a grep of the tree finds are deliberately absent: a CDN reached only from a component nothing imports, Stripe's JS (checkout is a server-issued URL the browser navigates to, and a top-level navigation is not a subresource), and the APIs dialled from route handlers, where CSP does not apply.
  • .well-known/security.txt and .well-known/ai-plugin.json — two files that claim only what is true.
  • The routing registry and parity fixtures, exported as JSON. npm run dump:registry emits the model registry carrying the commit SHA it was generated at, so drift is visible; npm run dump:fixtures emits golden scorer breakdowns and a routing cross-product. The learned router lives in another repository and must not retype any of it — a drifted copy is worse than no copy, because it would train against prices that quietly stopped being true. Neither generator changes anything that serves a request.
  • The CLI is on npm again, at 0.1.1. lobstack was published on 11 September and unpublished nine minutes later, and for four days the registry answered 404 while the site handed out an install command for it. 0.1.1 rather than 0.1.0 because npm's tombstone for an unpublished version is permanent — the bump was the only version that could be published, not a preference. Every surface describing the CLI reads the registry field in src/lib/packages.ts, so /docs/cli, /docs/gateway/sdk and /about corrected themselves when it flipped.

Fixed

  • The Lob Bot download route had stopped asking. /api/download/lob-bot/status carried revalidate = 60 and no dynamic export, and with no request-bound API in the handler Next treats that as prerenderable — so it ran during next build, when GITHUB_RELEASE_TOKEN did not exist, concluded there was nothing to download, and served that from a static file with a one-year cache. Adding the token to the deployment changed nothing. revalidate schedules regeneration of something already static; it does not prevent prerendering. Verified end to end against the real GitHub API: the download streams the installer rather than a truncated stub.
  • Orphaned last lines, across every heading and lede on the site. The home hero's sub-paragraph ended with a single word alone on a fourth line. That is the default greedy line-breaker rather than a bad sentence, so rewriting the sentence fixes one instance and leaves the next writer the same odds — it is text-wrap: pretty on prose and text-wrap: balance on headings and ledes, in the shared primitives, so pages that do not exist yet inherit it. Measured by walking real line boxes across every route in the sitemap at 1280×900 and 390×844: blocks whose last line was under 35% of the line above went from 99 to 10. Preformatted text is outside both selector lists, because text-wrap is a shorthand that also sets text-wrap-mode and would have unset the white-space: pre a curl command depends on.
  • Every factual claim on all 25 docs pages, read against the code that implements it. The product had changed enormously in a week and the docs had been patched page by page rather than reviewed as a whole. Checked against production rather than against the migrations directory, the spend-metering migration was found applied and five pages said it was not.
  • /status was presenting honest content as a void. Four bands, each a centred two-word label over a single centred sentence, three of them saying the same thing in three wordings — you could not tell by looking whether the page had rendered. It is a panel of rows now, one row per thing the page measures, and an absence takes the shape of the answer: same place, same size, same label beside it. Giving an absence the shape of the answer is how a status page says "we do not know this" as a statement instead of as an empty container.

Changed

  • The site is prerendered. The root layout carried export const dynamic = "force-dynamic" on the assumption that prerendering needed auth context. Nothing needed it — the providers are client components and render fine on the server — and the real constraint is narrower: a handful of Console panels call useSearchParams() without their own Suspense boundary. The opt-out moved to the two subtrees that have it, 58 routes became static files, and generateStaticParams on the three dynamic segments began doing what it was written to do. The nine still rendered on demand are the Console surfaces, /dashboard and the screenshot harness — all signed-in or internal, all noindex. Structured data moved to src/lib/seo.ts and every node is built from the module implementing the thing it describes, which is how the old 150-line literal came to advertise sandboxing and compliance alignment that /docs/security explicitly denies.
  • A third of the marketing copy, cut. The report was "detailed but very generic feeling", and the cause was two changes that were each right: making every claim rigorously honest grew a qualifying sentence beside it, and centring the site on one set of primitives gave every page the same shape — eyebrow, H1, lede, card grid, repeat. Uniform plus dense reads as generic. Measured at 1280×900 across every marketing route before anything was touched, then after: total height down 12%, words down 19%, cards down 29%.

0.24.0 2026-09-11

Added

  • Console Overview, rebuilt on the request ledger, in two modes. The common state of this Console is an account that has never made a call, so the first mode is a real screen rather than an empty state: three numbered steps, the current one open. Step one mints a key inline and shows the secret once, because sending somebody elsewhere to come back with a string they can no longer see loses the one value the screen depends on. Step two is that key already substituted into a real command, with curl, Python and Node tabs over the same request. Step three polls the priced ledger and renders the first request itemised — asked for, served, tokens, cost — the moment it lands. The second mode is four bands: Spend, Health, Recent requests and Attention. Attention renders only when it has items; there is no green "all systems normal" tile, because a reassurance tile is a thing readers learn to skip, and the day it is wrong it is the only thing on the page.
  • Console Usage, rebuilt on the request ledger, with unpriced made visible. The page read /api/agent/analytics, which prices an unknown model at Claude Sonnet list rates so that a cost never silently disappears — right for an estimate, wrong as the basis for a page headlined by a dollar figure, because every row comes back carrying a number and a call the meter could not price is then indistinguishable from one that genuinely cost that much. It reads /api/v1/usage now, the org-scoped trace, which is the only source in the product carrying unpriced_requests. cost_usd: null is never rendered as $0.00: nothing priced in the window shows an em dash and says the total is unknown rather than zero; partly priced shows a floor with a note naming how many of how many requests carry no price.
  • A Console Models surface, generated from the registry. What this account can call, what it costs them, and which model auto actually picks at each complexity tier — three answers already in the repository and none of them on an account-aware surface. Rates come from lobstackRateIn and lobstackRateOut, the same arithmetic gateway/allowance.ts runs for the receipt, so no price is typed in the new files; what auto prefers is MODEL_TIERS walked the way representativeModel walks it, so a reordered tier list moves the page; plan reach resolves through getPlan() and allowsTier() and is never inferred. A Copy curl button per model produces a real request against the real base URL.
  • Console Logs, pointed at the Gateway request trace. /dashboard/logs rendered agent_logs — lines a process on a VM wrote about itself — and the table was dropped with the runtime. The page was not throwing, which was worse: it rendered an empty list forever, with no way for a reader to tell "nothing happened" from "nothing will ever happen here again". It reads one row of gateway_requests per call that reaches us now, org-scoped and outliving every machine, filterable by key, model and status, each row expanding to the whole trace — the x-lobstack-request-id a customer quotes, endpoint, provider, mode, client, transport, the prompt and completion split, total and time-to-first-token latency, and the error class with the sentence saying whose problem it is. It reads a new sibling route, GET /api/v1/requests, rather than growing /api/v1/usage, whose list and total cannot disagree precisely because the rows returned are the rows summed.
  • A terminal UI for the CLI, still with zero dependencies. npx lobstack opens a full-screen UI that shows what each call cost as it happens. A TUI normally means ink or blessed; a process holding a live key should not pull a package tree to draw a box, so this is hand-rolled on node:readline's keypress decoder and nine escape sequences. Rows go to the receipt before the transcript, because you can scroll back for history and you cannot scroll back for a price you never saw. Money is never truncated — $0.004400 clipped to $0.004 is not a shorter number, it is a wrong one — so the receipt is three pieces with shorter fallbacks and the layout picks the widest set that fits. Piped, redirected, on TERM=dumb or before init, it prints exactly what it printed before, and every exit path ends stdout with reset, show-cursor and leave-alt-screen. Key bindings and the degradation table are in the CLI docs.
  • /docs/mcp. @lobstack/mcp was the only one of the three packages the site had never mentioned anywhere, and publishing it would have made its npm page the sole documentation for it. The page covers the four tools and which two work without a key, the config block for Claude Desktop, Claude Code, Cursor and Zed, and the two receipt rules that matter most — null is unpriced and never rendered as $0.00, and a saving is only a saving when the caller named a model. Tool names and descriptions are read off a real tools/list handshake against the built server, not from the README.
  • Agent Skills and Connectors as browsable hierarchies. Both were one long page. /skills rendered every skill with its complete SKILL.md expanded underneath it, so the only way to find out what the archive contained was to scroll past all of it, and there was no URL for "the ones about cost"; /connectors was honest and short but flat, so no connector had an address a search engine could rank or a model could cite. Skills gained a category layer because the data carries a category on every row; connectors did not, because they do not.
  • Token Intelligence, written down as a specification. token-conservation.ts exports TOKEN_INTELLIGENCE_VERSION and COMPLEXITY_SIGNALS — seven signals with their names, their tests, their literal patterns, their bands and their points, each carrying its own evaluate — and scoreComplexityBreakdown() returns the per-signal contribution plus the version and the pre-cap total. It is a classical heuristic and nothing claims otherwise: no model call in the scoring path, no learned weight, no embedding. What it has that no competitor's router has is that every decision it makes can be reproduced by hand from published data, and /gateway/routing#try is rebuilt around that argument.

Fixed

  • Row-level security on this database had never worked. Run as a real signed-in user for the first time, the policy on org_members subqueried org_members — evaluating it requires evaluating it, so Postgres aborted with 42P17 infinite recursion detected in policy, and so did every table whose policy reached through that membership read: orgs, API keys, the audit log, invites, the request trace and the usage ledger. This is not a regression from the rewrite that found it; the original policy had the identical self-referential shape and had never worked since the day it was written. It was invisible because every route in the application reads with the service-role key, which bypasses RLS entirely, so nothing in the product had ever evaluated one of these policies — decoration over a door nobody had tried. user_org_ids() is the SECURITY DEFINER function the schema already used for this exact problem on agents, and verified with a real member's claims, that user sees one org where the service role sees 43.
  • Three write RPCs were callable by anon. PostgREST publishes every function in public at /rest/v1/rpc/<name>, and three of them are SECURITY DEFINER — recording spend, crediting a paid top-up, and creating or merging a user row — so row-level security would not have stopped anyone holding the publishable key that ships in the browser bundle. Revoking EXECUTE from anon and authenticated did nothing, correctly: Postgres grants it to PUBLIC by default, both roles are members of PUBLIC, and revoking a privilege a role never held directly is a no-op. The revoke names PUBLIC now, service_role is granted back by name, search_path is pinned on all eight definer functions, and the two rollup views are security_invoker so the RLS underneath them applies.
  • The priced ledger stopped writing on 8 September and nothing said so. token_usage's last row was 2026-09-08 04:00:17 while gateway_requests kept writing — 58 rows since, 15 of them HTTP 200, carrying $0.9277 of real money the ledger the Console reads had no record of. Two correct-looking commits ninety minutes apart: a migration gave token_usage.request_id a foreign key to gateway_requests(id) while the route still called recordUsage before recordTrace, the child before the parent, so every gateway insert failed 23503; and the fix that stopped /api/agent/messages writing a duplicate row removed the redundant writer that had been masking it. The two ledgers are independent try blocks, which is why nothing surfaced.
  • The fix for the tools 400 was in the half of the error nobody read. The previous fix omitted reasoning_effort when tools were present. The remedy was in the clause after the comma: with the field absent the model applies its own default, so the request still arrives carrying an effort and the provider still refuses it. Omission is not none.
  • A data audit was gating every deploy, and the data it audited was wrong. check:metering reads production and exits 1 on any finding, and it had been wired into verify, which prebuild runs. It found something, correctly, and the site stopped shipping — including the deploy that would have fixed the number. It is npm run audit:metering now, on demand and on a schedule, and the header says plainly why it must not go back.

Changed

  • An Agent Skill is not a connector, and the counts were ours to get wrong. src/lib/skills.ts held entries that were every one of them a credentialed third-party integration with a requiredConfig, and the page called them skills. The distinction is structural now rather than editorial: an Agent Skill is a folder with a SKILL.md at its root — markdown, no credentials, portable to any agent that reads a skills directory, and the copy is the install — while a Connector is auth config plus tool definitions plus an endpoint, bound to the account that holds the credential and worthless as text. One teaches; the other grants access. The published connector figure also counted rows rather than connectors: fifteen ids were declared twice by a block appended in April and a sixteenth was one search engine registered under two names. Every lookup goes through getConnectorById, a find, so the earlier record always won and the duplicates were live only for things that iterate — which is to say, for the count we published and for nothing else.
  • The agent-VM connector catalogue was retired. src/lib/connectors.ts described its rows with a systemPrompt written for a runtime that no longer exists, and that catalogue was the most-repeated sentence on the site. Counts now come from src/lib/lobbot-connectors.ts, which mirrors the catalogue of a product that runs, and the honest claim is the bigger one: the built-in connectors, plus any MCP server you point it at, which has no ceiling. Rows that belonged to the retired runtime are labelled as such rather than quietly dropped — they are reachable only through the generic http-mcp and stdio-mcp transports, if somebody publishes a server for them.
  • The machine came out of the middle of the Console. Settings carried a whole Server tab headed "Manage the VM your runtime lives on" and the sidebar footer showed a server tier as permanent chrome on accounts that may have no server. Settings is Profile, Organization and Model now, plus Agent only when a machine exists; Server is gone for everybody, its two unique capabilities moved rather than dropped; Machine sits at the bottom of OPERATE, after API Keys and Webhooks, because every account has keys and most will never have a VM. Two numbers on the org stat band were lies of a familiar family: a percentage of a message limit shown to a spend plan, because the insights route answered a request limit unconditionally, and a spend figure that was a SUM over nulls coalesced to zero, so an account whose rows the meter could not price rendered as free. It reads unpriced now.
  • The CLI publishes from the repository that publishes it. A release workflow had been added here; wrong repository — the lobstack package publishes from the public CLI repo, the two copies of the source had already diverged, and provenance settles it anyway, because the attestation is checked against package.json's repository field. What stayed is the shape: put NPM_TOKEN in repository secrets once and a tag publishes, so the token is never in a shell, a dotfile or a message. The job asserts the tag matches cli/package.json before it publishes, and publishes with provenance. The tag prefix is cli-v rather than v, because this repository is the website too and the two do not version together.
  • "There is no installer to download yet" had not been true since 8 September. The download button on /lob-bot reads the release through /api/download/lob-bot and renders a button per platform that has an asset; the only thing holding it back was a missing deployment secret, so the page would have carried a working Download button and, six sections lower, an FAQ answer denying one exists. The FAQ names the three gaps that are actually true and stay true either way: nothing published is signed, the engine is a startup flag, and auto-update has no key or host.

Removed

  • The agent-VM runtime. Lobstack's original product was one dedicated cloud VM per agent running a Python bridge that called back into some forty-five platform routes. Checkout stopped building a machine when provisionVm began defaulting to false, and the Gateway, the Console, the CLI and /start have never needed one. Deleted: the api/agent/** routes the bridge called back into, the fleet-operations admin routes and their console, nine crons and their vercel.json entries, the Machine surface's terminal panel, the bridge itself, and the infrastructure, provisioning, queue, chat, operator, overseer, self-optimization and template libraries under src/lib. Deliberately kept: agent_instances and every read of it — the table is named for a machine and is not one. It carries plan_tier, api_keys binds to it, and gateway/auth.ts, gateway/quota.ts and billing.ts all read it on authenticated calls. It is the billing row, and no column was dropped.
  • Orphaned Console components, and their cascade. Twenty-two files of unreachable React that no user could have reached, each proven unreachable by a repo-wide search for the name as an import specifier, a JSX tag, a dynamic import and a bare string.
  • Six directory and template tables, and five functions whose tables were already gone. All verified to have zero references in application source first. skill_directory is worth naming: it was a second copy of src/lib/agent-skills.ts, which is what /skills, the sitemap and the count checker actually read — two hand-kept copies of one list, one of which never shipped.

0.23.0 2026-09-10

Changed

  • Plans include dollars of model spend, not messages. Every previous plan sold messagesPerMonth. A message is not a unit of cost — it is anything from a forty-token ping to a two-hundred-thousand-token context with a tool loop behind it — and nothing anywhere capped tokens, so every plan was underwater at its own advertised limit on any flagship model. Nobody discovered it, because the Gateway was refusing almost every OpenAI request and almost no inference ever ran. A plan now includes a number of dollars of model spend measured at our own published per-token rates, so cost of goods is bounded by construction rather than by hoping customers write short prompts. LOBSTACK_RATE_MULTIPLIER is the whole gross margin on managed traffic and is deliberately modest, because the receipt shows the customer what their call cost and anyone who can compare that to a provider's public price list will. BYOK meters requests instead, because a customer on their own key costs us nothing in tokens: it sells the routing, the receipt, the Console and the local proxy, and none of the inference. See Metering & cost.
  • Three meters, because three things are being sold. spend for a pricing.ts plan, requests for BYOK, and legacy for the stripe.ts tiers that sold messages per month — three live subscriptions are mid-period on those and are deliberately not being migrated, because a customer who bought messages does not get told mid-period that they have run out of dollars they never agreed to be measured in. Top-ups follow the same rule: POST /api/checkout/credits takes { usd } on a priced plan and { messages } on a legacy one, and the Console only ever offers the unit the plan is actually on. Enforcement is applied to API-key callers and not to agent credentials — turning it on for agents already running would return 402 on the next deploy to machines that have been over their allowance for weeks, which is a billing-policy decision and not one to make silently inside a refactor.
  • Half of a verified routed saving is credited back to the allowance. Verified is the whole of the rule: the request ran on our provider key, both models are priced, the row is not an error row, and the baseline is strictly above the actual cost. Routing does not always find something cheaper, and where it does not there is no saving and no credit.
  • The baseline has to say what it is. A request that names a model has an obvious counterfactual; a request that says auto — the documented default — has none, which is why savings_usd was structurally null on the one traffic shape we tell people to use. The baseline for auto is the most expensive model the caller's plan may reach, and every surface carries baseline_reason so a plan-ceiling comparison is never presented as one the caller asked for. That is also the most flattering number available to us, which is exactly why it has to be labelled. The rule caught its own bug on the way in: the first version took the priciest key in the whole registry, retired ones included, and overstated a free account's saving by half. Current keys only.
  • The whole site re-pointed at the product it actually sells. /lob-bot rebuilt around what Lob Bot does rather than a drawing of it, the homepage stopped depicting it as a Gateway consumer, and the fleet-brain claim was cut back to what is true. One footer, one accent, and one way to update a bridge.

Added

  • /start, and the CLI. /onboarding was not an on-ramp: it asked six questions about VM regions and messenger integrations, inferred a plan from the answers, and ended at Stripe checkout having minted no key at all — and /gateway's primary button, reading "Get a key", pointed at it. /start is three steps: mint a key, copy one command, watch the receipt arrive. The third step is the product. Every gateway can hand you a key and a curl; almost none will tell you on the response what the call cost and what the model you asked for would have charged for the same tokens, so rather than describe that the page polls for the user's own first request and prints it. GET /api/v1/first-call backs it — one row, newest first, and stop — rather than /api/v1/usage, which pages up to a thousand traces to build a summary and is the wrong shape for a two-second poll. When there is no saving the page says why instead of showing a blank. The curl comes from src/lib/site.ts, because a page that hands people a command to paste is the last place that should re-type a host.
  • Comparison pages, with a build check that fails when a claim goes stale. Comparison intent is most of this category's organic search and Lobstack appeared in none of it. The competitive review these were meant to typeset was two days old and two of its load-bearing claims were already false, so the facts live in src/lib/compare.ts — one first-party source and a short quote per claim, or an explicit negative established by searching the vendor's own docs — and scripts/check-compare.ts fails the build when a claim ages out.
  • A per-agent bridge credential, phase 1 of 3. AGENT_API_SECRET was one value for the whole fleet, used in both directions: the control plane presented it to every bridge's root-level endpoints, and every bridge presented the same value back. A tenant could read it by asking their own agent to cat its config, and it also made x-agent-id unverifiable, because requireAuthOrAgent checked the shared secret and then returned the id the caller had put in the header. Current exposure was zero — both live agents belonged to the same owner — so this is a launch blocker rather than an incident, and it is deliberately not rushed: identity is not hot-reloadable, so rotating a bridge onto its own secret needs a release and a supervised push. Phase 1 changes no behaviour. agent_instances gains api_secret and api_secret_activated_at, both null, and authenticateAgent() accepts either secret and binds the agent id when the per-agent one is used.
  • Settings is about you and your organization, rather than about a machine.

Fixed

  • The Gateway returned 400 to every OpenAI request for three months. reasoning_effort was set unconditionally on every model matching /^(gpt-5|o1|o3|o4)/, which is most of the OpenAI catalogue, to a value OpenAI's own error message does not list. The ledger carries roughly 1,395 consecutive failures from June to September with not one success, and the handful of requests that ever worked were on models the regex happened not to match. Three months of "the managed provider credentials need checking" was one line: a bad key surfaces as a 502 on this path and every trace row said 400 and validation, so the evidence to distinguish the two was sitting in a table nobody read. It was the second time — the Gateway had already invented temperature on Anthropic and had the provider refuse it, and the comment fixing that is four files away describing this exact failure. The value is a named constant now, and scripts/api-layer-check.ts asserts it is in the set the provider enumerates.
  • Parallel tool calls could not work on any Claude model. Anthropic requires strictly alternating roles and OpenAI's shape does not, so a turn with two parallel tool calls — one assistant message and two role: "tool" messages, each of which maps onto a user turn — emitted two consecutive user turns and was refused. It takes a second simultaneous call to appear, which is why a chat window never found it and an agent loop finds it on its first real task. Consecutive same-role messages fold into one entry now, which is also the shape Anthropic wants for the parallel case.
  • The price now rides on the frame that carries the tokens. A streamed answer's headers are written before the provider has reported a single token, so x-lobstack-cost-usd cannot exist on that path, and for three months the trailing usage chunk went out with token counts only under a comment claiming a client could read cost from it. Lob Bot believed it, fell back to its own bundled rate card of six models, and priced every request the router sent elsewhere at exactly $0.00 in its Spend view while the Console billed it correctly — two numbers disagreeing, which is worse than either being wrong on its own. usage keeps the exact OpenAI shape so an SDK that has never heard of us parses it unchanged; the money hangs off x_lobstack beside it, with cost_usd null rather than zero when the served model is unpriced and priced saying which case you are in.
  • Sign-up was a 404, and sign-in hung for thirty seconds. Every "Get Started" pointed at /onboarding, an eight-step questionnaire that happens to show a sign-in panel when it finds no user, so a visitor who wanted an account met an interview first and anyone who typed the URL a person types got nothing. A magic link opened from a mail app could never work either: ?code= is PKCE and the verifier lives in the browser that began the sign-in, so tapping the link inside a mail client's own browser fails however valid the link is — the callback tries ?token_hash= first now, which verifies in any browser on any device. And the failure was invisible, because the old code caught the exchange error and called setTimeout with an empty body: nothing shown, nothing logged, nothing retried, until a thirty-second timer blamed an expired link that was almost never the reason. Two more found on the way — redirectTo was built from window.location.origin, so a sign-in begun on the apex came back across a 307 that drops the host-only cookie the verifier lives in, and AuthProvider rendered children bare when the Supabase environment variables were missing, so useAuth() threw and every auth page died as an unhandled client exception.
  • Claims that stopped being true when checkout stopped building a machine. Every plan on /pricing sold vCPU, RAM and SSD and the FAQ said "All plans include a dedicated VM"; the Console told new subscribers to "deploy a runtime to bring the Gateway online", which the Gateway never waited for; /about opened with "Lobstack provisions a dedicated Linux VM for every agent". Docs and legal are rescoped in the same pass — from "every agent" to "each agent that has a machine deployed" — keeping every security commitment and keeping Hetzner as a disclosed subprocessor, because legacy and opt-in VMs are real.
  • BYOK key storage claim. The checkout page said a provider key was "Stored on your server only. Never saved to Lobstack." It is written to agent_instances.ai_api_key, which is what the privacy policy discloses (AES-256 at rest). The page now says that.

Removed

  • A VM is no longer built at checkout. provisionAgent() takes provisionVm, defaulting to false. A subscription buys Gateway access, the Console and a monthly allowance; a dedicated machine is deployed deliberately from Console → Machine, which is now the only way one comes into existence. The two paths that genuinely mean it opt in: /api/agent/deploy and the admin payments backfill, which replays checkouts bought under the old contract. New agent status no_machine — active and listable, not stopped (which means the server was destroyed) and not live. Existing agents are untouched.
  • The hourly server-side Operator loop. Removed from vercel.json; /api/cron/operator returns 410. Its only route to an agent was fetchBridge(server_ip, "/operator/run"), and checkout no longer builds a server_ip to reach. It had also never worked: step 1 of the one production goal was claimed, abandoned and re-kicked roughly 2,200 times from 5 June without once reporting back, because a step flipping between pending and in_progress looks exactly like a step being worked on. src/lib/operator/{loop,planner,kpis}.ts stay, unscheduled — Operator returns as a mode inside Lob Bot, where the loop runs next to the tools it drives and a step that changes something stops at the approval gate. /api/agent/operator (goals, plan steps, KPIs) is unaffected.
  • Overseer as a product. Removed from /enterprise, /about and every other customer-facing surface. It was never customer-facing in fact — every approval route is gated on verifyAdmin — so this removes the claim, not the capability. The daily cron, the admin panel and src/lib/overseer/* are unchanged; it is a good ops tool and a bad feature.

0.22.0 2026-09-08

Added

  • Every Gateway call comes back with a receipt. Until 7 September token_usage stored token counts and nothing else, and every dollar figure in the Console was recomputed at read time from the live registry — so editing a price silently rewrote all historical cost, managed traffic was indistinguishable from BYOK traffic the customer had already paid for, and routing was never persisted, which left "the router saves you money" with no data behind it at all. A ledger row now carries the price applied at request time: cost_usd, the per-million rates in force, the rate multiplier, the provider, the mode, the model asked for, the model served, whether it was routed, and what the baseline would have charged. The row reproduces its own arithmetic, one row per inference round including rounds that failed with zero tokens, so an error rate stays computable from the ledger alone. On a buffered response the arithmetic comes back in x-lobstack-* headers, where an unpriced model produces an empty value rather than a zero, and provider_cost_usd — what the provider charged us — is written to the ledger and appears in no header, no stream frame and no API response.
  • An API a client that is not a virtual machine can use. The only bearer credential the platform had was agent_instances.gateway_token, which belongs to a VM, so letting a desktop client in meant fabricating an agent row for it — and because token_usage.agent_id was NOT NULL with ON DELETE CASCADE, deleting that row would have erased the billing history with it. api_keys is org-owned, scoped, expiring and revocable; the full key is returned once and never stored, what is kept is a SHA-256 plus a non-secret selector used as the lookup index, so verification is one indexed read and a constant-time compare. A key may bind to an agent or stand alone as an org-level managed-inference credential, and the binding is ON DELETE SET NULL, because destroying a machine must not revoke a credential.
  • Real routes for the Console, and two surfaces it did not have. It had been one 479-line client component whose navigation was useState — no deep links, no back button, and no way to send somebody a URL that lands on the thing you are looking at, which is a real problem for a surface whose job is showing people what broke. ConsoleContext owns agent-scoped data, polling and switching; org-scoped data is deliberately not poured through it, because keys and request traces belong to an organization and outlive any single machine.
  • An enterprise organization layer. Consent-based invites — /invite previews the inviter, the org and the role through an unauthenticated endpoint that format-validates the token and never echoes it back, with distinct expired, revoked, used and mismatch states and an explicit join. Last-owner guards on demotion and departure, owner-only grant and revoke, a real already-a-member check, and an audit trail for org and membership changes. The identity bug it started from: the membership insert and the owner plan-limit count keyed on the internal database id while tenancy keys on the auth id, so a newly created team org was invisible to its own creator.
  • Bridge v25 — parallel tool calls in all three LLM loops, with guarded-tool confirmations staying sequential, approved calls running concurrently, an interrupt watcher cancelling in-flight tasks, results returned in tool_call_id order and one failing tool never losing its neighbours; RAG recall over synced memories and earlier-session summaries injected per turn; auto-continuation, where a model that ends genuinely unfinished work says so in a tag the wrapper answers, bounded and interrupt-aware; delegate_subtasks, up to four bounded sub-agents with nesting refused and per-task failure isolation; plan mode, which withholds tools entirely and asks for a plan to approve before execution; and workspace-rooted file tools behind realpath escape checks.
  • /docs/api-keys — the key format and why the prefix is safe to print, scopes, agent binding, streaming, the x-lobstack-* headers, the failure taxonomy with whose problem each class is and whether it is worth retrying, quota, revocation and the usage endpoint.

Fixed

  • Every successful Gateway request was metered twice. The bridge called the Gateway for inference, which records a priced row, and then posted the conversation to /api/agent/messages with the same usage attached, which recorded it again — two rows about 250ms apart, one with the served model and no session, one with the requested string and a session. Audited against the live ledger rather than read off the code: 48.3% of all metered tokens were double-counted, and the direction is overcharge. /api/agent/messages records only when the agent is not on the Gateway path now, because in direct mode the bridge calls the provider itself and its row is the only record there is. Two related findings in the same audit: total recorded cost across the whole table was $0.00, because three of the four writers were raw inserts that never set cost, mode, source or provider; and org_id was null on 100% of rows, so every invoice bucketed into NULL.
  • The Gateway sent temperature on every request whether the caller asked for one or not. Anthropic deprecated the sampling parameters on its newer models and does not ignore them — it returns a hard 400, and that error was the most common row in this account's history. A temperature is forwarded only when the caller set one and only to a model that still takes one; when we drop it we say so on the response with x-lobstack-dropped-params. Defaulting it was never ours to decide anyway, since it silently set the character of every answer.
  • The Console was reporting numbers that are not true. /api/agent/status ordered health checks and logs newest-first and then reversed both arrays, and every consumer reads index 0 as "most recent" — so with a one-per-minute cron and a twenty-sample window, every resource figure in the Console was about twenty minutes old while the heading said "Now". Recent Activity, off the same reversed array, was showing the oldest events in the window. The Usage heading states the sample's real age now, because "Now" is a claim worth being able to check.

Changed

  • Lobstack as an AI company. The marketing scope was rebuilt on a white ground with near-black ink, hairlines, black pill buttons and alternating full-bleed bands, and the type is sans only. The homepage leads with the company rather than a feature, indexing the ecosystem as Gateway, Console and Lob Bot, and there are product pages for each — /gateway renders its model catalogue and prices from the gateway registry rather than from copy.
  • The Console became Mission Control. Chat, Agent Config, Skills, Sandbox, Memory, Wallet and Affiliate tabs were removed along with their dead wiring; Overview, Usage, Logs, Terminal, Webhooks and Settings stayed, with Overview refocused on Gateway health, usage and logs. Console tokens flipped white-first with a graphite dark mode, and the app no longer forces dark: light is the default and dark honours a stored choice.
  • The docs were rebuilt around the three products. The index had led with "a live agent in 90 seconds" and "dedicated infrastructure — every agent gets its own cloud VM", and the Gateway, which is now the business, appeared nowhere in the twenty-card grid. Eight near-identical Skills pages ended at a tab that no longer exists, four documented panels that are orphaned in the codebase, and five security pages presented Kubernetes, Istio, gVisor and Vault as live production when they exist only as infrastructure-as-code — the sixth page, the honest one, marked the same controls "Ready — IaC defined". 27 of 38 pages removed, 24 written against the code rather than against the last version of the docs. The shell is a fixed sidebar and a scrolling middle, a 672px measure, and a contents rail that reads headings out of the DOM rather than from a manifest each page has to maintain.
  • The Console page stopped advertising six verbs. Monitor, Analyze, Inspect, Command, Configure, Administer described an intention rather than a surface, over a screenshot of a console that no longer exists. Both now match what shipped: six questions the Console can actually answer, and a plate rendered from the real thing.

0.21.1 2026-08-03

Fixed

  • Usage was priced from a stale local table that mispriced every current-generation model to the default rate; pricing and provider identity come from the gateway model registry now. Three more in the same data layer: the error rate had been dividing log lines by request counts while token_usage.error was fetched and unused, latency was an average of bucket averages rather than real p50 and p95, and windows stopped at Supabase's 1,000-row cap with nothing saying so — they paginate past it now, and a truncated flag marks a total that is a floor.

Changed

  • Console Logs — level filter chips with live counts, sticky date separators, oldest-to-newest order, per-row copy, download of the filtered set, and a follow mode that auto-scrolls while you are at the bottom and offers a "Latest" pill when you are not.
  • Console Settings — Destroy requires typing DESTROY in a confirm modal that spells out what is permanently lost, and the rebuild actions state that memory and sessions are preserved and disable themselves while a rebuild is in flight.
  • Onboarding gained a fixed progress strip, a Back button that rewinds exactly one step and restores the prior selections, a double-submit guard on every answer handler, and a review step that recaps focus, integrations, model, region, name and plan before deploy.

0.21.0 2026-07-27

Added

  • July 2026 model catalog refresh — 15 current-generation engines: Claude Opus 5, Claude Sonnet 5, Claude Haiku 4.5, GPT-5.6 (Sol / Terra / Luna), Gemini 3.1 Pro, Gemini 3.5 Flash, Grok 4.5, Grok 4.1 Fast, DeepSeek V4 Pro / Flash, Qwen 3.7 Max / Plus, and Mistral Medium 3.5 — bringing the catalog to 30+ models.

Changed

  • DeepSeek retired its legacy chat and reasoner API endpoints on 2026-07-24 — old DeepSeek V3 and R1 keys now route automatically to DeepSeek V4 Flash and V4 Pro, so existing agents keep working with no action required.
  • Previous-generation models remain selectable for existing agent configurations; pickers now feature the current generation first.

0.20.0 2026-06-04

Added

  • Lobstack Pay (LSP-1) — agentic settlement protocol: policy-governed smart-account wallets, the x402 payment-required handshake, USDC on Base, and USD-pegged Lobstack Credits.
  • On-chain settlement — the LobstackSettlement contract settles USDC and emits verifiable receipts; gasless ERC-4337 smart accounts (paymaster-sponsored) plus a custodial EOA path.
  • Operator — agents that build and run a business: objectives to an LLM-generated plan, an autonomous execution loop, live KPIs, and per-goal spend budgets.
  • Overseer — the fleet brain: observes privacy-safe metrics, learns (rule engine plus LLM analyst on any model), proposes actions you approve in the admin panel, applies them live, and measures the outcome.
  • Org/tenant scoping for the Overseer — per-org rollups, org-tagged insights, and an admin org filter.
  • 10 native enterprise integrations — QuickBooks, Xero, Bill.com, Ramp, Okta, ServiceNow, Confluence, Box, Segment, and Snyk.
  • Wallet and Operator dashboard tabs; an Overseer admin panel with approve / apply / dismiss.

Improved

  • Agent bridge v20 — Lobstack Pay tools, native enterprise integration handlers, and Operator tools with a fire-and-forget execution endpoint.
  • The LLM analyst and Operator planner run on the Lobstack Gateway, so they can use any model on managed Lobstack AI.

0.19.0 June 2026

Added

  • Lobstack AI Gateway docs + marketing (Phase 4). New /docs/gateway page (managed vs BYOK, Token Intelligence tiers, the OpenAI-compatible API, credits), plus Auto/managed notes across the models, pricing, and Features pages.
  • Existing-agent backfill — admin endpoint POST /api/admin/gateway-backfill mints a gateway_token, sets byok, and pushes gateway config to already-provisioned VMs so they move onto the gateway (idempotent).
  • Credit-flow hardening — credit_purchases idempotency ledger (keyed by Stripe session id) prevents double-crediting on webhook retries; dashboard pack picker.
  • Managed AI, and a message-credit top-up (Gateway Phase 3). Onboarding offered "Use Lobstack AI" (no API key — usage included in your plan, billed through the gateway) against "Bring your own key", plus an "Auto" option that let Token Intelligence pick the model per message. The top-up sold messages: /api/checkout/credits, a one-time Stripe payment consumed automatically once the monthly quota was exhausted, against a new agent_instances.message_credits column. Checkout, webhook and provisioning thread llm_mode; settings switch managed, byok or auto through /api/agent/update. The unit did not survive — plans include dollars of model spend as of 0.23.0, and the same route sells dollars to every plan that is not one of the three legacy subscriptions still mid-period on messages.
  • Lobstack Gateway (Phase 1) — a unified, OpenAI-compatible LLM API (POST /api/gateway/v1/chat/completions, GET /api/gateway/v1/models) that fronts every provider behind one endpoint. Per-request Token Intelligence selects the cheapest capable model (reusing the complexity scorer, bounded by plan tier), usage is metered into token_usage, and keys resolve as managed (Lobstack's keys) or BYOK (the agent's key). New src/lib/gateway/*, a unified model registry with per-token pricing, and additive agent_instances.llm_mode + gateway_token.
  • Self-optimization loop (v0) — agents safely improve their own system prompts behind a frozen held-out eval gate. Prompts are versioned data; promotions require beating baseline by a margin, 100% deterministic hard-check pass rate, and a variance guard. Atomic, reversible promotion via selfopt_promote(). New schema (prompt_versions, eval_cases, agent_runs, optimization_proposals), src/lib/selfopt/*, and nightly /api/cron/optimize (07:00 UTC).
  • Docs Integrations Directory — a data-driven page rendering the live SKILL_CATALOG in full, grouped by category, where seven integrations had previously been documented by hand.
  • Features page sections for Integrations, Channels, Workflow automation, and the model catalogue.

Changed

  • Lobstack Gateway is now the primary inference path (Phase 2). Bridge v18 routes all inference through the gateway in managed/byok mode (tools still execute locally via the multi-round loop), falling back to direct calls only if the gateway is unreachable or llm_mode: "direct". Provisioning mints a per-agent gateway_token, defaults agents to byok, and writes llm_mode/gateway_url/gateway_token into the VM config (hot-reloadable). Token Intelligence never crosses providers in BYOK mode (single-provider keys).
  • Repositioned around the proprietary Lobstack Agent Runtime as the primary execution engine. Removed OpenClaw from all public docs and marketing (About "Engine" section, /docs/openclaw, nav, community, model gateway, README badge); MCP is now documented as native to the runtime.
  • /agents renders every template in AGENT_TEMPLATE_LIBRARY — the single source of truth — rather than a hardcoded subset; category filters derive from TEMPLATE_CATEGORIES.
  • Consolidated compute onto Hetzner Cloud — removed DigitalOcean/Vultr from marketing, docs, and legal (privacy/terms). Backend provisioning fallback code is unchanged.
  • Homepage hero subheader rewritten around deploying ready-made agents out of the box.

Removed

  • Orphaned src/components/OpenClaw.tsx landing section and the /docs/openclaw page.

0.18.0 2026-06-02

Added

  • Lobstack AI Gateway — a unified, OpenAI-compatible endpoint in front of every provider, now the primary path agents use to reach a model.
  • Use Lobstack AI (managed) — deploy an agent with no API key; model usage is included in your plan.
  • Auto model selection — Token Intelligence routes each message to the lowest capable tier, bounded by your plan tier.
  • Message-credit top-ups — buy extra messages from the dashboard; they are used automatically once the monthly allowance runs out.

Changed

  • Bring-your-own-key agents now also route through the gateway for Token Intelligence and unified usage analytics (a single-provider key is never used for another vendor).
  • Switch between Lobstack AI and your own key, or toggle Auto, from Settings with zero downtime.

0.17.0 2026-06-02

Added

  • Integrations Directory — the full integration catalog browsable in the docs, grouped by category and sourced from the live skill catalog.
  • Agent Templates page surfaces all 128 production-ready templates across 17 categories, each pre-loaded with a role, tools, and recommended skills.
  • Self-optimization loop (v0) — agents improve their own system prompts behind a frozen held-out eval gate, with atomic, reversible promotions.

Changed

  • The Lobstack Agent Runtime is documented as the proprietary, primary execution engine on every agent VM.
  • Consolidated all compute onto Hetzner Cloud; provider references across docs, marketing, and legal pages updated accordingly.
  • Homepage and Features repositioned around deploying ready-made agents out of the box.
  • MCP servers are documented as natively supported by the Lobstack runtime.

0.16.0 2026-03-05

Added

  • Token Conservation Engine — smart model routing based on complexity scoring (0-100) across 5 tiers (nano → flagship), with context window optimization and token budget management
  • Chat-to-Automation pipeline — /automate, /schedule, /trigger, /remind slash commands with natural language time parsing to create workflows directly from conversation
  • Agentic Session Management — sessions support categories (general, task, research, support, automation, creative, debug), statuses (active/completed/paused/archived), pinning, and grouped sidebar
  • 10 new slash commands: /automate, /schedule, /trigger, /remind, /status, /pin, /category, /done, /export
  • Cron trigger execution engine — every-minute cron with full cron expression parsing and double-fire prevention (55s cooldown)
  • Billing safety-net cron — hourly job catches agents whose billing period wasn't reset by Stripe webhooks
  • Webhook retry with exponential backoff — 3 attempts at 0s, 5s, 30s; smart retry skips 4xx (except 429)
  • Enhanced analytics — per-model token breakdown, hourly aggregation for peak detection, composite efficiency score
  • Token budget API — GET returns budget status/burn rate, POST returns model routing recommendations with savings estimates
  • /export command downloads conversation as formatted markdown

Fixed

  • Dashboard template dropdown — replaced overflowing horizontal category buttons with proper <select> in AgentConfigPanel
  • N+1 query in health cron — batch fetch all agent logs instead of per-agent loop
  • Admin listUsers() N+1 — replaced loading all auth users with targeted email-based DB query
  • Dashboard over-polling — tiered polling (15s fast, 60s slow) reduces API calls ~40%

Improved

  • Chat session sidebar grouped by Pinned → Active → Completed → Archived with category icons and context menu
  • SELECT * elimination in admin routes — fetch only required columns
  • Session API rewritten with full category, status, icon, pinned, message_count support
  • Slash command registry expanded to 22 built-in commands

0.15.0 2026-03-03

Added

  • 8 new AI model providers: DeepSeek (V3, R1), Qwen (Max, Plus), Mistral (Large, Small), Meta Llama 3.3 70B via Groq, Ollama self-hosted
  • Edit workflow functionality — modify existing workflows without deleting and recreating
  • Redesigned Settings model selector with provider-grouped layout and model badges
  • Expanded bento box on landing page from 3 to 8 models with cycling carousel
  • SVG brand icons for Google, DeepSeek, Mistral, Meta, Groq, Qwen, and Ollama
  • Ollama self-hosted model support — runs locally on agent VM with no API key
  • Firecrawl Scrape tool added to workflow builder

Fixed

  • Critical workflow execution JSON parse error — _truncate_result creating malformed JSON
  • Workflow variable interpolation double-serialization
  • Firecrawl Scrape field name mismatch ("formats" vs "format")
  • Agent Messages metric race condition — now uses ground-truth DB count
  • Messages counter backwards jumps — Math.max(dbCount, cachedCount)
  • Performance Intelligence chart flickering — stale-while-revalidate pattern
  • Workflow execution no longer injects status messages into Chat
  • Incorrect social links in docs pages
  • SettingsPanel API key provider detection for new providers

Improved

  • Settings panel model selection UX with provider groups and badges
  • Workflow builder Edit mode with "Save Changes" vs "Create"
  • API key section dynamically adapts to provider
  • Documentation updated for 24 models and 10 providers

0.14.0 2026-03-03

Added

  • Agent Templates expanded from 20 to 36 across all 9 categories
  • syncToBridge retry helper with exponential backoff for critical bridge sync points
  • Skills panel error banner with retry button when catalog fetch fails
  • Agent Templates bento card on landing page hero section

Fixed

  • Critical AGENT_SECRET → AGENT_API_SECRET env var typo in webhooks — was silently breaking all event-triggered workflow executions
  • TOCTOU race condition in pending execution pickup — replaced SELECT-then-UPDATE with atomic UPDATE+SELECT claim pattern
  • Execution status validation — invalid statuses now rejected with 400 instead of silently defaulting to "completed"
  • Execution POST auth — X-Agent-Id header now preferred over untrusted body agent_id
  • Skills POST/PUT missing DB upsert error handling — failures now return 500 instead of silently continuing
  • Skills PUT not regenerating SKILLS.md — config saves now update the system prompt file and push to bridge
  • Triggers PATCH missing bridge sync — trigger updates now forward to the VM like POST and DELETE already did
  • Workflows PATCH missing triggers in bridge sync — workflow updates now include trigger data
  • Webhooks route handlers (GET/POST/DELETE/PATCH) missing try-catch — all now have safe JSON parsing and error responses
  • Webhook delivery deliverWebhook silent error swallowing — failures now logged with context
  • Event trigger pipeline reliability — queue-first pattern ensures pending execution exists before attempting direct bridge call
  • SkillsPanel catalog fetch not checking response.ok — now detects HTTP errors and shows user-facing error state
  • SkillsPanel handleSaveConfig parsing response body twice and not handling failure — now parses once with fallback

Improved

  • Workflow execution pipeline hardened end-to-end: event trigger → queue → bridge pickup → result reporting
  • Bridge communication reliability with retry and backoff for transient failures
  • Skills integration lifecycle: toggle, configure, sync to bridge, and regenerate system prompt all verified

0.13.0 2026-03-03

Added

  • 12 new Agent Templates: Legal & Compliance, HR & Recruiting, E-Commerce Manager, DevOps & SRE, Education & Tutoring, Financial Advisor, Project Manager, Cybersecurity Analyst, Creative Director, Real Estate Agent, Healthcare Assistant, Podcast Producer
  • 3 new template categories: Operations, Finance, Education (9 total categories)
  • Slash command highlighting in Chat — /commands now render as styled tags with hash icon
  • UUID validation for agent_id in pending executions endpoint
  • Disabled workflow detection — pending executions for disabled workflows are auto-cancelled

Fixed

  • Critical timestamp conversion bug in execution API — now handles ISO strings, unix seconds, and milliseconds correctly
  • Missing error handling in workflow trigger deletion (was fire-and-forget)
  • Missing try-catch on request body parsing in executions POST endpoint
  • Invalid CSS class wrap-break-word → break-words in SandboxPanel file viewer
  • Redundant cursor logic in WorkflowCanvas drag handling
  • Unused state variable in SandboxPanel template selection
  • Race condition in pending execution pickup for disabled workflows

Improved

  • Agent Template Library expanded from 8 to 20 templates covering enterprise, operations, finance, education, healthcare, and creative use cases
  • Execution status validation against allowed status whitelist
  • Workflow execution engine hardened with proper error handling and validation
  • Agent lookup error handling now distinguishes 404 from 500

0.12.0 2026-03-02

Added

  • Agent Template Library with 8 pre-built agent configurations (Customer Support, Research Assistant, Content Creator, Developer Assistant, Sales & Outreach, Personal Assistant, Data Analyst, Social Media Manager)
  • Template browser UI in Agent Config panel with category filtering and preview
  • Architecture documentation page at /docs/architecture
  • Changelog documentation page at /docs/changelog
  • Error boundary component for dashboard crash resilience
  • CHANGELOG.md for tracking platform changes

Fixed

  • All ESLint errors and warnings across the codebase (prefer-const, unused variables, setState-in-effect anti-patterns)
  • Auth callback React anti-pattern — setState now scheduled via queueMicrotask
  • Unused eslint-disable directives cleaned up in admin MasterTerminal
  • Unused variable removal across API routes (payments, memory, sessions)
  • Unused imports cleaned up across docs pages

Improved

  • Sitemap now reflects actual docs routes with correct paths
  • Code quality: zero TypeScript errors, reduced ESLint warnings significantly

0.11.0 2026-03-01

Fixed

  • agent_configs table not in PostgREST schema cache — added v12 migration with NOTIFY pgrst, 'reload schema'
  • schema.sql missing NOTIFY — added reload signal at end of main schema
  • aiohttp breaking bridge entirely — added stdlib HTTP fallback layer (both server + client)
  • Deploy crashes on schema cache miss — wrapped agent_configs seeding in try/catch
  • Config API crashes on schema cache miss — added graceful fallback to in-memory defaults
  • Infrastructure pip install fragility — split aiohttp install from core deps, added build essentials

0.10.0 2026-02-28

Added

  • Deep OpenClaw integration with MCP servers, ClawHub skills, and security hardening
  • OpenClaw version pinned to 2026.2.26 for reproducible deployments
  • 150+ tool integrations spanning AI providers, crypto, finance, DevOps, CRM, and publishing
  • Slash command system with enhanced '+' modal and rich output rendering
  • Queue-based workflow execution engine with heartbeat-driven bridge pickup
  • Visual workflow builder with Run Now feedback (loading state + success indicator)
  • Master Terminal for admin panel operations
  • Admin Runbook rewritten as comprehensive operations manual
  • Video script for Lobstack product demo

Fixed

  • Critical aiohttp scoping bug breaking ALL tool integrations
  • Workflow Create crash and Run Now not working
  • Stuck pending executions — keep pending until bridge confirms, add stale cleanup
  • Bridge: auto-fetch workflows from platform if not in memory
  • Tool loop on round exhaustion — added graceful summary
  • Workflow execute 404/502 — relaxed agent lookup and added retry logic
  • Shared getAgentForUser utility — eliminated lookup divergence causing 404

0.9.0 2026-02-27

Added

  • Redesigned Skills panel with modern categorized filtering system
  • GlassFlow-style bento grid with product UI mockups on landing page
  • Interactive bento grid with live visuals per feature card
  • 20+ new skill integrations with real brand logos
  • Dashboard UX overhaul with glass effects, collapsible sidebar, and Performance Intelligence chart
  • HEARTBEAT.md and WORKFLOWS.md agent configurations
  • User sync endpoint and UI button to reconcile Stripe customers with Supabase
  • POST /api/admin/agents/assign-user to link orphaned agents
  • POST /api/admin/demo-account for creating demo agent accounts

Fixed

  • Smooth sidebar animation and corner radius connecting to header
  • Consistent curved border radius on all dashboard pages
  • Compact tech-style segmented toggle for Skills panel

0.8.0 2026-02-27

Added

  • Comprehensive SEO & AISEO optimization for search engine and LLM discoverability
  • Modern floating pill navbar for landing page
  • Comprehensive docs site with 30+ pages covering all platform features
  • Supabase auth email templates with Lobstack branding
  • Affiliate and onboarding pages aligned with landing page design system

Fixed

  • Subscription loss after Privy-to-Supabase auth migration — handles both duplicate-already-created and not-yet-created scenarios
  • Pre-existing duplicate users from auth migration
  • Auth resilience to auth_id column not in PostgREST schema cache
  • Checkout 401 — use in-memory session instead of cookie-based getSession()
  • Bearer token fallback added to auth flow for all API calls
  • Existing subscribers seeing payment page instead of dashboard
  • Magic link auth, PKCE race condition, and homepage redirect

0.7.0 2026-02-26

Added

  • Complete Framer-grade light-first redesign
  • Supabase Auth migration from Privy (Google OAuth + email magic links)
  • GitHub OAuth sign-in
  • 3D Spline hero with mouse-tracking tilt and dashboard preview
  • Redesigned testimonials with dual-row marquee
  • New Lobstack shield lobster logo across all pages

Changed

  • Migrated auth from Privy to Supabase for better control and pricing
  • Dashboard, onboarding, affiliate pages aligned to light design tokens
  • Force light mode — removed dark class and stale localStorage
One source, not twoThis page has no content of its own. Edit CHANGELOG.md at the root of the repository, or src/lib/app-releases.ts for an app release (the list /about reads too), and the next build picks it up.
Lobstack

An AI team that asks before it acts, and an API with a receipt on every call.

© LobstackXLinkedInGitHub