Release v0.27 – v0.29
v0.27 – v0.29 Release: Installable Extensions, a Signed Registry, and a New Dashboard
October 17, 2026 · The Smarter Project
v0.24 to v0.26 got Smarter ready to run in public. v0.27 to v0.29, released on October 15 and 16, change how Smarter grows. A new tool for your LLMs used to mean a change to Smarter itself and a new release. Now it is an Extension: a Python package that a platform administrator installs at run time, from a signed registry, without a redeploy. The web console’s dashboard is redesigned around everything the last dozen releases added.
| Change | What it means for you |
|---|---|
| Extensions | Python packages with their own tools, settings, documentation and lifecycle, installed while the platform runs. |
| Signed Extension registry | Browse, install and update Extensions from a registry whose index and archives are verified with an Ed25519 signature. |
| Extensions in the web console | Superusers install, configure, enable, update, roll back and uninstall Extensions on two new console pages. Every user sees the Extensions their account may use. |
| Three official Extensions | The weather, calculator and date calculator tools are now Extensions, in their own repositories. |
| Dashboard redesign | A Getting Started card that works, every resource kind in My Resources, and new cards for Extensions, the SDKs, integrations and the Smarter MCP server. |
| Init jobs you can trust | The init job fails when an official Extension doesn’t install, emails its whole log, and a daily task cleans up orphaned DNS records. |
Extensions: tools you install, not tools you release
Smarter could give an LLM new tools in two ways. Plugins are manifests that configure one of Smarter’s built-in tool patterns, such as an API call or a SQL query. And three built-in Python functions, for the weather, a calculator and date arithmetic, were hard-coded into Smarter. Adding a fourth meant changing the platform and shipping a release.
Extensions are the third way, and they work like WordPress plugins. An Extension is a Python package with its own tools, settings, documentation, assets and lifecycle. A platform superuser installs it at run time, from the web console or the registry, and every app, worker and beat pod picks it up without a redeploy.
An Extension describes itself in a standard pyproject.toml. Here is the official weather Extension’s:
[tool.smarter]
slug = "weather"
package = "weather"
display-name = "Weather"
requires-smarter = ">=0.27"
tools = ["weather.tools:GetWeather"]
timeout = 30
[[tool.smarter.settings]]
name = "google_maps_api_key"
type = "secret"
required = true
description = "A Google Maps Geocoding API key, which finds the latitude and longitude of a location."
[[tool.smarter.settings]]
name = "weather_api_url"
type = "url"
default = "https://api.open-meteo.com/v1/forecast"
description = "The Open-Meteo forecast api."
A tool is a class with a name and a Pydantic arguments model. The model’s JSON Schema is the tool’s parameters, and its docstring is the tool’s description, so what the LLM is offered can never disagree with what the tool validates:
class GetWeather(SmarterExtensionTool):
"""Get the current weather, and the forecast for the next 24 hours, for a location."""
name = "get_weather"
arguments_model = WeatherArguments
def call(self, arguments: WeatherArguments, context: ExtensionContext) -> JsonValue:
settings = context.settings
place = geocode(arguments.location, settings.google_maps_api_key.get_secret_value())
...
An LLMClient lists the Extensions it uses by slug:
spec:
extensions:
- weather
plugins:
- image_search
- Typed settings, and secrets that stay secret. Settings are declared in
pyproject.tomland configured by the administrator. A secret setting is stored as a Smarter Secret, encrypted at rest, and reaches the tool as aSecretStr. - A full lifecycle. Install, update, roll back to any earlier version, configure, enable, disable and uninstall. Hooks can run before and after each step: a pre hook that fails cancels the step, and a post hook that fails leaves the Extension installed but disabled, with the error shown. New Extensions are installed disabled, and one with unset required settings can’t be enabled.
- Resources that come and go with it. An Extension can ship SAM manifests and waffle switches, which are created on install and removed on uninstall, exactly the ones it created.
- Updates without restarts. Each version loads beside the previous one, under its own namespace, rather than reloading modules in place, which Python does not do reliably.
- Failures stay inside the tool. Each call runs with the Extension’s timeout. Invalid arguments, exceptions, timeouts and results that aren’t JSON go back to the LLM as an error, so they don’t fail the prompt, and a broken Extension is skipped and reported.
- Per-account availability. An Extension is available to every account, or to the accounts you list.
- Tools named for their Extension. The LLM is offered each tool as
ext_<slug>_<tool>, such asext_weather_get_weather.
Security
Extensions can only import what Smarter already ships. Their dependencies are checked against the platform’s installed libraries, never installed, and an incompatible Extension explains every unmet Python, Smarter or library requirement. An uploaded archive is validated before anything is imported: size, file count and zip bomb limits, and no path traversal or links. An Extension’s documentation is rendered with raw HTML and file inclusion turned off. Only superusers can install, configure or remove an Extension.
📖 Extensibility · Building an Extension
The signed Extension registry
The Smarter Extension registry is an index of published Extensions. Smarter reads it, verifies it, and installs from it:
- Verified on every read. The index is signed with Ed25519, and Smarter checks the signature with
SMARTER_EXTENSION_REGISTRY_PUBLIC_KEYevery time it reads the index. An index that doesn’t verify is never cached or used. - Verified archives. Every downloaded archive is checked against the sha256 in the signed index.
- Trust badges. Each publisher is official, verified or community. An archive that you upload yourself is badged unverified, and is never offered a registry update, so a registry package with the same slug can’t replace it.
- Update checks. A daily task records each Extension’s newest compatible version, and the console shows what can be updated.
The three official Extensions, weather, calculator and date calculator, are published there. initialize_platform installs them, and configures their secret settings from the platform’s Secrets of the same name, such as google_maps_api_key.
Managing Extensions in the web console
Superusers manage Extensions on two new React pages in the web console, under Extensions in the sidebar. A badge counts the Extensions that have an update available.
- Installed: a table of every installed Extension, with an enable switch per row, an upload button and Check for updates.
- Browse the registry: search, filter by trust badge, and read an Extension’s documentation before you install it, then install a version from a card.
- An Extension’s own page has an enable toggle, an update banner, and tabs for its overview, tools, settings, availability, versions (with roll back) and the resources and switches it created. The settings form is generated from the Extension’s
pyproject.toml. A secret setting can be kept, typed in, taken from one of the platform’s Secrets, or cleared, and its value is never sent back to the browser.
Everyone else can see which Extensions they may use. The LLM Tools page (formerly Plugins) has a read-only Extensions tab beside the Tool Plugins tabs, with each Extension’s slug, version, publisher, trust badge and whether it’s enabled, so a prompt engineer knows which slugs spec.extensions may list. The page moved from /plugin/ to /llm-tools/, and the old URLs redirect.
A dashboard that matches the product
The dashboard had fallen behind. Its widgets were plain lists of links, and none of the recent features (Extensions, the Smarter MCP server, the OpenAPI document, Guardrails, Vectorstores, LLMHosts, Custom Domains) appeared on it.
- Getting Started works. Two of its steps counted the built-in LLMClients and plugins that every user can see, so every new account started half done, and the card disappeared as soon as a user stored a Secret and deployed an LLMClient. The steps now count only what you own. The card shows until every step is done, then stays for 90 days, and a failed request shows its error.
- My Resources counts MCPClients, Guardrails, Secrets, Vectorstores, Custom Domains, LLMHosts and Extensions, each linked to its list.
- Quick Actions adds Guardrails, Apply Manifest, and an API Reference link to your platform’s own OpenAPI page, plus Extensions and Infrastructure for superusers.
- New cards: Extensions, the SDKs (with the Node.js and Go SDKs and their install commands), integrations (WordPress, Drupal, Shopify, Google Tag Manager, Docusaurus, MkDocs, Sphinx and VitePress), the CLI, the VS Code extension, the free course designs for instructors, the Smarter MCP server with the
claude mcp addcommand for your platform, self-hosting, and contributing. - The chat header counts every tool. Smarter Chat’s header, such as openai gpt-4o-mini with 2 additional tools, counted only plugins. The chat configuration now sends a
total_toolscount that includes Extensions and MCPClients. Guardrails aren’t counted, because an LLM can’t call one.
Behavior changes you will notice
spec.functionsis nowspec.extensions. The LLMClient manifest lists Extensions by slug. The built-in functionsget_current_weather,calculatoranddate_calculatorare gone, and their replacements are the official Extensions, whose tools areext_weather_get_weather,ext_calculator_calculatorandext_date_calculator_date_calculator.- API names follow. The LLMClient REST route
/llm-clients/{id}/functionsis now/extensions, and the chat configuration’sfunctionslist is nowextensions. The OpenAPI document, the LLMClient schema and the chat contract are regenerated. - An LLMClient whose Extensions aren’t installed is skipped, with a warning, when the built-in LLMClients are deployed, so a registry that can’t be reached doesn’t fail the whole init job.
- Cloning an LLMClient copies everything it uses.
clone()never copied an LLMClient’s plugins, and didn’t copy its MCPClients or guardrails at all. It now copies every link, but only those that the clone’s owner is allowed to use.
Fixes and operations
- The init job fails when an official Extension doesn’t install, because the built-in LLMClients that need it are then skipped. It used to report success.
- The whole init job log, by email. The job’s email carried only the last 500 lines of its log, so the cause of an early failure had often scrolled away. It now attaches the whole log, with credentials redacted. A log over 5 MB is uploaded to the platform’s storage under an unguessable name, and linked instead.
- Orphaned DNS records are cleaned up. A daily task deletes the A records of LLMClient hosts that nothing uses any more, at most 50 a run.
manage.py delete_orphan_dns_records --dry-runlists them without deleting anything. It runs only in the AWS environments, and does nothing if it can’t tell which hosts are live. - Provider verification survives deploys. Each deploy reset every built-in Provider to verified and active, which re-enabled Providers that had failed verification or that an admin had suspended. Billing, authentication, rate-limit and outage errors no longer deactivate every model of a Provider either: they are now inconclusive, and change nothing. Reasoning models get enough tokens to pass verification, and Gemini’s embedding, video and Live models are no longer created as chat models.
- Logs hold less. Secret ciphertext and Account contact details are no longer logged, and the example Secret manifests no longer publish their test passwords.
- One write per plugin apply. Applying a plugin wrote it three times and sent
plugin_updatedthree times. It now writes once. - The built-in
metaaiLLMClient used a model that Meta no longer offers. It now uses Meta’s current default model. - DNS verification checked the API domain’s delegation in the wrong zone, and reported A records that point elsewhere, such as at a CDN, as verified. They are now reported as warnings, and left unchanged.
- Styles:
conversationHeader.colornow also colors the chat header’s buttons, which were invisible on six built-in LLMClients, andbuttons.colorcolors only the send and attach buttons.
Upgrading
- Convert
spec.functionstospec.extensionsin your LLMClient manifests. The old function links are dropped by the migration, not converted, so an LLMClient that used the weather, calculator or date calculator function has no tools until you list the matching Extension and apply its manifest again. Update system prompts that name the old tools. - The registry key. The registry is turned off while
SMARTER_EXTENSION_REGISTRY_PUBLIC_KEYis empty. The Helm chart now sets it, andSMARTER_EXTENSION_REGISTRY_URL, to the public registry. If you deploy another way, copy both from.env.example. - Set
GOOGLE_MAPS_API_KEY.initialize_platforminstalls and enables the official Extensions, and fills in their secret settings from the platform Secrets of the same name.initialize_providerscreates thegoogle_maps_api_keySecret fromGOOGLE_MAPS_API_KEY. Without it, the weather Extension can’t be enabled, because its key is a required setting, and the init job fails. - The weather Extension needs version 0.2.1 or later, which fixed a dependency requirement that the platform couldn’t meet.
manage.py deploy_example_llmclientis removed.deploy_builtin_llmclientsalready deploys the example LLMClient from its manifest. Remove it from your own scripts.- SDKs: update the Python, Node.js and Go SDKs for the
functionstoextensionschange and the newtotal_toolsfield.
What’s next
The next post covers v0.30 to v0.32, which translate the web console into Spanish, French and Brazilian Portuguese, and let users upload a profile image.
The full list of changes is in the v0.27, v0.28 and v0.29 changelogs. To try the release, start with the documentation, or browse the code on GitHub.
