smarter-api v0.2 – v0.6 Release: The Smarter Python SDK, Typed From End to End
smarter-api is the official Python SDK of Smarter. It’s meant to be to Smarter what the openai package is to the OpenAI api, so one pip install gives your Python code typed access to your own Smarter platform, whether it runs on your laptop or on Kubernetes. This is its first announcement, and it covers everything from v0.2, which replaced the SDK’s two-year-old predecessor with a new one, to v0.6, released today.
pip install --upgrade smarter-api
The old SDK covered a single endpoint and a resource kind that the platform no longer has. The new one covers the whole api, returns Pydantic models instead of JSON, and raises typed exceptions instead of returning error dictionaries. It installs as smarter-api and imports as smarter.
| What you get | In one sentence |
|---|---|
| Every resource kind | Apply, validate, get, describe, delete, deploy and undeploy any of the 25 kinds through the same manifest api as the smarter cli. |
| Prompts and chat | Prompt an LLMClient, hold a chat session that the platform remembers, and stream a prompt’s progress as it runs. |
| Each resource’s own actions | Evaluate Guardrails, call MCP servers’ tools, add documents to and search vectorstores, and plan and deploy self-hosted LLMs. |
| Typed models | A Pydantic model for every response, and a generated model of every manifest kind, so your editor and type checker know every field. |
| Typed errors | One SmarterError hierarchy, with a subclass for each http status, such as NotFoundError. |
| Zero setup if you use the cli | It reads the cli’s ~/.smarter/config.yaml, or SMARTER_API_KEY and SMARTER_BASE_URL. |
| The platform’s own kinds | SAMKinds and its apply order now come from smarter-types, the same package that the platform uses. |
Using it
from smarter import Smarter
client = Smarter() # SMARTER_API_KEY, or the smarter cli's ~/.smarter/config.yaml
me = client.whoami()
print(f"Hello, {me.user.username}!")
llmclient = client.llm_clients.find("customer_support")
print(client.llm_clients.prompt(llmclient.id, "Where is my order #1234?").text)
chat = client.llm_clients.chat(llmclient.id)
print(chat.send("What is 2 to the 10th power?").text)
print(chat.send("And divided by 4?").text) # the session remembers the question before
- Every write goes through the manifest api.
client.manifests.apply()sends a manifest exactly assmarter apply -fdoes, so the SDK, the cli and the web console change resources the same way, with the same validation. - Retries that know the platform. Timeouts, connection errors, rate limits and gateway errors are retried with backoff, twice by default, and honor
Retry-After. A 503 that the platform itself sends, for a resource that isn’t ready yet, isn’t retried, because a retry wouldn’t change it. - Your api key never reaches a log. Logging is off unless you set
SMARTER_LOG, and keys are always masked. - It keeps working when the platform grows. The response models accept fields they don’t know yet, and values that the platform may add to, such as kinds, are strings rather than closed enumerations, so a newer platform doesn’t break an older SDK.
Getting Started With smarter-api has a complete walkthrough, including a script that applies a folder of manifests in dependency order, the way a CI/CD job would.
What changed from v0.2 to v0.6
v0.6 and the platform’s own manifest kinds
SAMKindscomes from smarter-types. The SDK used to have no way to know which kinds exist, or the order to apply them in, without copying the platform’s definitions. Now it depends on smarter-types, the package the platform uses, andfrom smarter import SAMKindsis that class.SAMKinds.apply_rank()sorts manifests so that each resource comes after the resources it names, such as a Secret before its Connection, a Connection before its plugin.- Manifests with unquoted dates are accepted. YAML reads an unquoted
2024-06-15as a date, which isn’t a JSON value, soManifestrejected a manifest that the platform accepts, such as one with a release-date annotation. A date is now kept as the text it was written as.
v0.5 follows the platform
- Functions became extensions (v0.5.1). The platform replaced an LLMClient’s built-in functions with installable Extensions, and renamed them everywhere. The SDK follows, with no deprecated aliases, because an alias could only call a route that the platform no longer serves.
llm_clients.functions()is nowllm_clients.extensions(),LLMClient.functionsisLLMClient.extensions, and the models named after functions are named after extensions. If your code used them, rename them. config(verbose=True)(v0.5.2). Since Smarter v0.36.6, an LLMClient’s configuration is short unless you ask for all of it.llm_clients.config()returns the short one by default, andverbose=Trueadds the plugin and extension lists and the tool-call history.- An LLMClient’s MCPClients, Guardrails and tools. The
LLMClientmodel hasmcpclients,guardrailsandtools, everything that the LLMClient adds to a prompt, each an empty list on an older platform.
v0.3 and v0.4 cover the rest of the api
- User profiles and plugin uses.
client.accounts.user_profileslists each user’s memberships of accounts, andclient.history.plugin_use(id)retrieves one use of a plugin. - Typed Orchestrators and Vectorsearches, whose own fields used to arrive as untyped extras.
Built to be depended on
A client library sits under its users’ own code, so v0.5.3 rebuilt how smarter-api is tested, released and documented, on the same pattern as cache-results.
- Tested on Python 3.10 to 3.14 on every push and pull request, at 99% branch coverage, against recorded responses from a running platform. A contract test fails when the platform’s api has a field that the SDK doesn’t declare, and the SDK keeps a pinned copy of the platform’s OpenAPI document and the JSON Schema of every manifest kind.
- Typed. The package ships
py.typed, and its manifest models are generated from the schemas that the platform publishes. - Released by a workflow, not a laptop. Every push to
mainruns the whole test matrix, and semantic-release decides from the commit messages whether to release. The release is rehearsed on TestPyPI and installed back, then published to PyPI with trusted publishing, so no PyPI token exists anywhere, and installed back again. - Documented on its own site. docs.smarter-python.smarter.sh has a quickstart, a user guide (configuration, manifests, chat, resources, models and errors), an api reference generated from the code, including a page for every manifest kind, and 25 architecture decision records.
- Licensed like Smarter, under the AGPL-3.0-or-later, and published by The Smarter Project.
Try it, and tell people about it
- Install it and prompt one of your LLMClients in a few lines, after
pip install smarter-api. If you don’t have a platform yet, the Quick Start Guide runs one on your laptop. - Star the repository at github.com/smarter-sh/smarter-python.
- Open an issue for a bug, or for a part of the api that you’d like a better shape for. The contributing guide explains how to make a change.
- Prefer JavaScript or Go? The Node.js and Go SDKs follow this one’s design, resources and errors.
What’s next
- An async client. smarter-api is synchronous today, and async applications call it in a thread with
asyncio.to_thread. Its transport and resources are built so that anAsyncSmartercan be added without changing the public api, as ADR-018 explains. - Keeping in step with the platform. Each Smarter release that changes its api is followed by a smarter-api release that syncs the contracts and models.
The changelog is on GitHub, with the v0.6.0 release. The package is on PyPI, the docs are at docs.smarter-python.smarter.sh, and the source is at github.com/smarter-sh/smarter-python.
