API Contract

The Smarter api contract: the JSON Schemas of the SAM manifests, and the OpenAPI document of the Smarter api.

Both are generated from the platform’s Pydantic models by manage.py export_api_contract, and committed beside this package: sam/<Kind>.schema.json and openapi.json. Tests fail when a committed file is out of date. They are the source from which the smarter cli and the SDKs generate their clients, so a change to a SAM model is a change to the api.

See The Api Contract.

Constants of the Smarter api contract: the SAM JSON Schemas, and the OpenAPI document of the Smarter api.

smarter.apps.api.v1.contract.const.API_VERSION = 'v1'

the version of the api, not of the platform.

The platform’s version changes with every release, which would make the committed document stale.

Type:

The document’s info.version

smarter.apps.api.v1.contract.const.DEFAULT_PLATFORM_URL = 'https://platform.smarter.sh'

The default of the document’s platform server variable.

Each Smarter installation has its own.

smarter.apps.api.v1.contract.const.JSON_SCHEMA_DIALECT = 'https://json-schema.org/draft/2020-12/schema'

The dialect of the document’s schemas, and of the SAM JSON Schemas.

smarter.apps.api.v1.contract.const.LOCAL_PLATFORM_URL = 'http://localhost:9357'

The platform of a local development environment.

smarter.apps.api.v1.contract.const.OPENAPI_PATH = '/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/api/v1/contract/openapi.json'

The OpenAPI document of the Smarter api, generated from smarter.apps.api.v1.contract.openapi.

smarter.apps.api.v1.contract.const.OPENAPI_VERSION = '3.1.0'

The version of the OpenAPI Specification that the document follows.

3.1 schemas are JSON Schema 2020-12.

smarter.apps.api.v1.contract.const.SAM_EXAMPLE_HOST = 'localhost'

The host of the in-process request that renders an example manifest.

Every environment allows it.

smarter.apps.api.v1.contract.const.SAM_EXAMPLE_SUFFIX = '.example.json'

The suffix of a SAM example manifest’s file name, after its kind.

smarter.apps.api.v1.contract.const.SAM_SCHEMA_DIR = '/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/api/v1/contract/sam'

The folder of the SAM JSON Schemas, one <Kind>.schema.json per kind.

smarter.apps.api.v1.contract.const.SAM_SCHEMA_SUFFIX = '.schema.json'

The suffix of a SAM JSON Schema’s file name, after its kind.

The JSON Schemas of the SAM manifests, one per kind, generated from their Pydantic models, and an example manifest of each kind.

manage.py export_api_contract writes them to sam/<Kind>.schema.json and sam/<Kind>.example.json, beside this module, and a test fails if a committed file is out of date.

  • A schema is exactly the data of the cli’s json-schema/<Kind>/ response, so a client may read either. The SDKs generate their manifest models from them, and smarter.apps.api.v1.contract.openapi includes them in the OpenAPI document.

  • An example is the data of the cli’s example-manifest/<Kind>/ response, without its read-only status, whose timestamps change on every request. The SDKs test their generated models against them, and a test checks that each example is valid under its kind’s schema.

smarter.apps.api.v1.contract.sam.sam_example(kind)[source]

A SAM kind’s example manifest, without its read-only status.

It is rendered in-process by the cli’s public example-manifest view, so that it is exactly what the api returns, because the brokers build their examples for a request.

Parameters:

kind (str) – The kind, e.g. Guardrail.

Returns:

The manifest.

Return type:

dict[str, Any]

Raises:
  • KeyError – If kind is not a SAM kind.

  • ValueError – If the view does not return an example.

smarter.apps.api.v1.contract.sam.sam_example_json(kind)[source]

A SAM kind’s example manifest, as the text of sam/<Kind>.example.json.

Parameters:

kind (str) – The kind, e.g. Guardrail.

Returns:

The manifest, as indented JSON, with a final newline.

Return type:

str

smarter.apps.api.v1.contract.sam.sam_example_path(kind, directory='/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/api/v1/contract/sam')[source]

The file of a SAM kind’s example manifest.

Parameters:
  • kind (str) – The kind, e.g. Guardrail.

  • directory (str) – The folder of the examples.

Returns:

e.g. .../sam/Guardrail.example.json.

Return type:

str

smarter.apps.api.v1.contract.sam.sam_models()[source]

The Pydantic model of each SAM kind: the model that its broker validates manifests with.

The brokers are imported here, rather than at the module’s top, because they import most of the platform’s apps.

Returns:

The models, by kind, e.g. {"Guardrail": SAMGuardrail, ...}, sorted by kind.

Return type:

dict[str, type[BaseModel]]

smarter.apps.api.v1.contract.sam.sam_schema(kind)[source]

A SAM kind’s JSON Schema (draft 2020-12): the schema that the cli’s json-schema command returns.

Parameters:

kind (str) – The kind, e.g. Guardrail.

Returns:

The schema.

Return type:

dict[str, Any]

Raises:

KeyError – If kind is not a SAM kind.

smarter.apps.api.v1.contract.sam.sam_schema_json(kind)[source]

A SAM kind’s JSON Schema, as the text of sam/<Kind>.schema.json.

Parameters:

kind (str) – The kind, e.g. Guardrail.

Returns:

The schema, as indented JSON, with a final newline.

Return type:

str

smarter.apps.api.v1.contract.sam.sam_schema_path(kind, directory='/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/api/v1/contract/sam')[source]

The file of a SAM kind’s JSON Schema.

Parameters:
  • kind (str) – The kind, e.g. Guardrail.

  • directory (str) – The folder of the schemas.

Returns:

e.g. .../sam/Guardrail.schema.json.

Return type:

str

smarter.apps.api.v1.contract.sam.write_sam_schemas(directory='/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/api/v1/contract/sam')[source]

Write every SAM kind’s JSON Schema and example manifest, and remove the files of kinds that no longer exist.

Parameters:

directory (str) – The folder to write. Defaults to sam/, beside this module.

Returns:

The paths that were written, sorted by kind, each kind’s schema before its example.

Return type:

list[str]

Pydantic models of the Smarter cli api contract, and of the OpenAPI document that publishes it.

The cli api (/api/v1/cli/) is the api of the smarter cli and of the SDKs: it applies, gets, describes and deletes the resources that SAM manifests declare. Its requests and responses are described by:

smarter.apps.api.v1.contract.openapi assembles them into an OpenAPI document, which is modeled here too (OpenApi...), so that it is built from models rather than from nested dicts. A schema inside the document is JSON Schema, which is arbitrary JSON, so it is a JsonValue.

The response models allow extra fields: adding a field is backward compatible. Removing or renaming one that is declared here is not.

smarter.apps.api.v1.contract.models.CLI_API_MODELS: tuple[type[BaseModel], ...] = (<class 'smarter.apps.api.v1.contract.models.CliApiApplied'>, <class 'smarter.apps.api.v1.contract.models.CliApiValidation'>, <class 'smarter.apps.api.v1.contract.models.CliApiGet'>, <class 'smarter.apps.api.v1.contract.models.CliApiResource'>, <class 'smarter.apps.api.v1.contract.models.CliApiStatus'>, <class 'smarter.apps.api.v1.contract.models.CliApiVersion'>, <class 'smarter.apps.api.v1.contract.models.CliApiWhoami'>, <class 'smarter.apps.api.v1.contract.models.CliApiPromptBody'>, <class 'smarter.apps.api.v1.contract.models.CliApiPrompt'>, <class 'smarter.apps.api.v1.contract.models.RestApiErrorResponse'>)

The models of the cli api’s response data whose JSON Schema the OpenAPI document includes.

Their dependencies are included with them.

(
    <class 'smarter.apps.api.v1.contract.models.CliApiApplied'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiValidation'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiGet'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiResource'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiStatus'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiVersion'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiWhoami'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiPromptBody'>,
    <class 'smarter.apps.api.v1.contract.models.CliApiPrompt'>,
    <class 'smarter.apps.api.v1.contract.models.RestApiErrorResponse'>,
)
class smarter.apps.api.v1.contract.models.CliApiApplied(**data)[source]

Bases: CliApiModel

The data of an apply response: the resource that the manifest created or updated.

apiVersion: str
kind: str
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class smarter.apps.api.v1.contract.models.CliApiGet(**data)[source]

Bases: CliApiModel

The data of a get response: the resources of a kind that match the request’s criteria.

apiVersion: str
data: CliApiGetItems
kind: str
kwargs: dict[str, JsonValue]
metadata: CliApiGetMetadata
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
class smarter.apps.api.v1.contract.models.CliApiGetItems(**data)[source]

Bases: CliApiModel

The table of a get response: its columns, and one row per resource.

items: list[dict[str, JsonValue]]
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

titles: list[CliApiGetTitle]
class smarter.apps.api.v1.contract.models.CliApiGetMetadata(**data)[source]

Bases: CliApiModel

The metadata of a get response’s data.

count: int
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.CliApiGetTitle(**data)[source]

Bases: CliApiModel

A column of a get response’s table: an item’s field, and its serializer field’s type.

model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
type: str
class smarter.apps.api.v1.contract.models.CliApiModel(**data)[source]

Bases: BaseModel

Base class of the models of the cli api’s response data, which allow extra fields.

model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.CliApiPrompt(**data)[source]

Bases: CliApiModel

The data of a prompt response: the request that the cli api sent to the LLMClient, and its response.

model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

request: CliApiPromptRequest
response: CliApiPromptChatResponse
class smarter.apps.api.v1.contract.models.CliApiPromptBody(**data)[source]

Bases: CliApiModel

The request body of a prompt.

messages: list[PromptChatApiMessage] | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

prompt: str
session_key: str | None
class smarter.apps.api.v1.contract.models.CliApiPromptChatResponse(**data)[source]

Bases: CliApiModel

The LLMClient’s journaled response to a prompt.

api: str
data: CliApiPromptLambdaResponse
metadata: PromptChatApiJournalMetadata
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.CliApiPromptLambdaResponse(**data)[source]

Bases: CliApiModel

The LLMClient’s response to a prompt: the version 1 prompt response, with its body decoded from a JSON string.

body: PromptChatApiCompletionV1
headers: dict[str, str]
isBase64Encoded: bool
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

statusCode: int
class smarter.apps.api.v1.contract.models.CliApiPromptRequest(**data)[source]

Bases: CliApiModel

The request that a prompt sent to the LLMClient.

messages: list[PromptChatApiMessage]
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

session_key: str
class smarter.apps.api.v1.contract.models.CliApiResource(**data)[source]

Bases: CliApiModel

A kind of resource that the cli api manages: an item of the resources response’s data.

APIKind: str
Deployable: bool
Display: str
DisplayPlural: str
Plural: str
Singular: str
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.CliApiStatus(**data)[source]

Bases: CliApiModel

The data of a status response: the platform’s infrastructure and compute.

compute: CliApiStatusCompute
infrastructures: CliApiStatusInfrastructures
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.CliApiStatusCompute(**data)[source]

Bases: CliApiModel

The platform’s compute, from Python’s platform module.

machine: str
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

platform: str
processor: str
release: str
system: str
version: str
class smarter.apps.api.v1.contract.models.CliApiStatusInfrastructures(**data)[source]

Bases: CliApiModel

The infrastructure of a status response.

kubernetes: dict[str, JsonValue]
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

redis: CliApiStatusRedis
class smarter.apps.api.v1.contract.models.CliApiStatusRedis(**data)[source]

Bases: CliApiModel

The Redis server of a status response, from Redis’s INFO command.

gcc_version: str | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

os: str | None
redis_build_id: str | None
redis_version: str | None
class smarter.apps.api.v1.contract.models.CliApiValidation(**data)[source]

Bases: CliApiModel

The data of a validate response.

errors: list[CliApiValidationError]
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

valid: bool
class smarter.apps.api.v1.contract.models.CliApiValidationError(**data)[source]

Bases: CliApiModel

An error of a manifest that validate reports.

loc: list[str | int]
message: str
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

type: str
class smarter.apps.api.v1.contract.models.CliApiVersion(**data)[source]

Bases: CliApiModel

The data of a version response.

api: CliApiVersionApi
cli: CliApiVersionCli
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.CliApiVersionApi(**data)[source]

Bases: CliApiModel

The platform’s version, and the versions of its main Python packages.

model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

python: dict[str, str | None]
version: str
class smarter.apps.api.v1.contract.models.CliApiVersionCli(**data)[source]

Bases: CliApiModel

The smarter cli’s latest version.

model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

version: str
class smarter.apps.api.v1.contract.models.CliApiWhoami(**data)[source]

Bases: CliApiModel

The data of a whoami response: the api key’s user and account, and the platform’s environment.

account: CliApiWhoamiAccount
environment: str
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

user: CliApiWhoamiUser
class smarter.apps.api.v1.contract.models.CliApiWhoamiAccount(**data)[source]

Bases: CliApiModel

The api key’s account.

accountNumber: str
address1: str | None
address2: str | None
city: str | None
companyName: str | None
country: str | None
createdAt: str | None
currency: str | None
description: str | None
hashedId: str | None
id: int
isActive: bool | None
isDefaultAccount: bool | None
language: str | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
phoneNumber: str | None
postalCode: str | None
state: str | None
timezone: str | None
updatedAt: str | None
class smarter.apps.api.v1.contract.models.CliApiWhoamiUser(**data)[source]

Bases: CliApiModel

The api key’s user.

email: str | None
firstName: str | None
id: int
isStaff: bool
isSuperuser: bool
lastName: str | None
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

username: str
class smarter.apps.api.v1.contract.models.OpenApiComponents(**data)[source]

Bases: OpenApiModel

The document’s reusable schemas and security schemes.

model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

schemas: dict[str, JsonValue]
securitySchemes: dict[str, OpenApiSecurityScheme]
class smarter.apps.api.v1.contract.models.OpenApiContact(**data)[source]

Bases: OpenApiModel

The document’s contact information.

model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
url: str
class smarter.apps.api.v1.contract.models.OpenApiDocument(**data)[source]

Bases: OpenApiModel

An OpenAPI 3.1 document.

components: OpenApiComponents
info: OpenApiInfo
jsonSchemaDialect: str
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

openapi: str
paths: dict[str, OpenApiPathItem]
security: list[dict[str, list[str]]]
servers: list[OpenApiServer]
tags: list[OpenApiTag]
class smarter.apps.api.v1.contract.models.OpenApiInfo(**data)[source]

Bases: OpenApiModel

The document’s metadata.

contact: OpenApiContact | None
description: str | None
license: OpenApiLicense | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

summary: str | None
title: str
version: str
class smarter.apps.api.v1.contract.models.OpenApiLicense(**data)[source]

Bases: OpenApiModel

The api’s license.

model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
url: str
class smarter.apps.api.v1.contract.models.OpenApiMediaType(**data)[source]

Bases: OpenApiModel

The schema of a request’s or response’s body, in one media type.

model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

schema_: JsonValue
x_smarter_events: dict[str, JsonValue] | None
class smarter.apps.api.v1.contract.models.OpenApiModel(**data)[source]

Bases: BaseModel

Base class of the models of an OpenAPI 3.1 document.

They forbid extra fields, so a misspelled field fails rather than being published. Fields whose OpenAPI name is a Python keyword, or a BaseModel attribute, have an alias: e.g. in_ is in, and schema_ is schema. A field that is None is left out of the dump, because no OpenAPI field may be null. exclude_none would also drop the nulls inside the schemas, e.g. a field’s "default": null, so the models drop their own Nones instead.

model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.OpenApiOperation(**data)[source]

Bases: OpenApiModel

An http method of a path.

description: str | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

operationId: str
parameters: list[OpenApiParameter]
requestBody: OpenApiRequestBody | None
responses: dict[str, OpenApiResponse]
security: list[dict[str, list[str]]] | None
summary: str
tags: list[str]
class smarter.apps.api.v1.contract.models.OpenApiParameter(**data)[source]

Bases: OpenApiModel

A path, query or header parameter of an operation.

description: str | None
in_: Literal['path', 'query', 'header']
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
required: bool
schema_: JsonValue
class smarter.apps.api.v1.contract.models.OpenApiPathItem(**data)[source]

Bases: OpenApiModel

A path, and its operations.

delete: OpenApiOperation | None
get: OpenApiOperation | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

post: OpenApiOperation | None
class smarter.apps.api.v1.contract.models.OpenApiRequestBody(**data)[source]

Bases: OpenApiModel

An operation’s request body.

content: dict[str, OpenApiMediaType]
description: str | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

required: bool
class smarter.apps.api.v1.contract.models.OpenApiResponse(**data)[source]

Bases: OpenApiModel

One of an operation’s responses.

content: dict[str, OpenApiMediaType] | None
description: str
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

type smarter.apps.api.v1.contract.models.OpenApiSchema = _AllowAnyJson]

A JSON Schema (2020-12), e.g. {"$ref": "#/components/schemas/SAMGuardrail"}.

class smarter.apps.api.v1.contract.models.OpenApiSecurityScheme(**data)[source]

Bases: OpenApiModel

An api key scheme: the only one that the cli api accepts from programs.

description: str | None
in_: Literal['header']
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
type: Literal['apiKey']
class smarter.apps.api.v1.contract.models.OpenApiServer(**data)[source]

Bases: OpenApiModel

A server that hosts the api.

description: str | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

url: str
variables: dict[str, OpenApiServerVariable] | None
class smarter.apps.api.v1.contract.models.OpenApiServerVariable(**data)[source]

Bases: OpenApiModel

A variable of a server’s url.

default: str
description: str | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.api.v1.contract.models.OpenApiTag(**data)[source]

Bases: OpenApiModel

A tag, which groups operations.

description: str | None
model_config = {'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
class smarter.apps.api.v1.contract.models.RestApiErrorResponse(**data)[source]

Bases: BaseModel

The body of an error response of the REST api’s views: Django REST framework’s {"detail": ...}.

e.g. a 404 for a row that does not exist, or a 403 for a user who may not use the view.

detail: str
model_config = {'extra': 'allow'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

The OpenAPI 3.1 document of the Smarter api, generated from Pydantic models.

The document covers the apis that the smarter cli and the SDKs call, family by family:

  • the cli api (/api/v1/cli/), to apply, get, describe, validate and delete the resources that SAM manifests declare,

  • the chat api (/api/v1/llm-clients/{id}/config/ and .../prompt/), to chat with an LLMClient, as JSON or as a stream of Server-Sent Events,

  • the REST reads of the resource families: the LLMClients’, Guardrails’, Secrets’, MCPClients’, vectorstores’, LLMHosts’, plugins’, Providers’ and Proxies’, whose responses are built from each app’s contract models, e.g. smarter.apps.llmclient.contract.models. Only the reads are published: clients write through the cli api’s manifests, which the brokers validate.

It is built from:

so a change to any of them changes the document. manage.py export_api_contract writes it to openapi.json, beside this module, and a test fails if the committed file is out of date, or if a route of a family in DOCUMENTED_URLCONFS is neither in the document nor in UNDOCUMENTED_ROUTES.

The live Swagger and Redoc pages (/docs/swagger/) are generated by drf-yasg from the views, and describe every api of the platform in OpenAPI 2. This document describes fewer apis, but types their requests and responses, so that clients can be generated from it.

smarter.apps.api.v1.contract.openapi.CHAT_MODELS: tuple[type[BaseModel], ...] = (<class 'smarter.apps.prompt.contract.models.PromptChatApiConfigRequest'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigResponse'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptRequest'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptResponse'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiErrorResponse'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressEvent'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressResult'>)

The Smarter Chat api contract’s models that the chat api’s operations use.

(
    <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigRequest'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigResponse'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptRequest'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptResponse'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiErrorResponse'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressEvent'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressResult'>,
)
smarter.apps.api.v1.contract.openapi.DOCUMENTED_URLCONFS: dict[str, str] = {'/accounts/': 'smarter.apps.account.api.v1.urls', '/cli/': 'smarter.apps.api.v1.cli.urls', '/connections/': 'smarter.apps.connection.api.v1.urls', '/guardrails/': 'smarter.apps.guardrail.api.v1.urls', '/journal/': 'smarter.lib.journal.api.v1.urls', '/llm-clients/': 'smarter.apps.llmclient.api.v1.urls', '/llmhosts/': 'smarter.apps.llmhost.api.v1.urls', '/mcpclients/': 'smarter.apps.mcpclient.api.v1.urls', '/orchestrators/': 'smarter.apps.orchestrator.api.v1.urls', '/plugins/': 'smarter.apps.plugin.api.v1.urls', '/prompts/': 'smarter.apps.prompt.api.v1.urls', '/providers/': 'smarter.apps.provider.api.v1.urls', '/proxy/': 'smarter.apps.proxy.api.v1.urls', '/secrets/': 'smarter.apps.secret.api.v1.urls', '/vectorsearches/': 'smarter.apps.vectorsearch.api.v1.urls', '/vectorstores/': 'smarter.apps.vectorstore.api.v1.urls'}

each one’s path, relative to /api/v1, and its urlconf.

Every route of these urlconfs must be in the document, or in UNDOCUMENTED_ROUTES.

{
    '/accounts/': 'smarter.apps.account.api.v1.urls',
    '/cli/': 'smarter.apps.api.v1.cli.urls',
    '/connections/': 'smarter.apps.connection.api.v1.urls',
    '/guardrails/': 'smarter.apps.guardrail.api.v1.urls',
    '/journal/': 'smarter.lib.journal.api.v1.urls',
    '/llm-clients/': 'smarter.apps.llmclient.api.v1.urls',
    '/llmhosts/': 'smarter.apps.llmhost.api.v1.urls',
    '/mcpclients/': 'smarter.apps.mcpclient.api.v1.urls',
    '/orchestrators/': 'smarter.apps.orchestrator.api.v1.urls',
    '/plugins/': 'smarter.apps.plugin.api.v1.urls',
    '/prompts/': 'smarter.apps.prompt.api.v1.urls',
    '/providers/': 'smarter.apps.provider.api.v1.urls',
    '/proxy/': 'smarter.apps.proxy.api.v1.urls',
    '/secrets/': 'smarter.apps.secret.api.v1.urls',
    '/vectorsearches/': 'smarter.apps.vectorsearch.api.v1.urls',
    '/vectorstores/': 'smarter.apps.vectorstore.api.v1.urls',
}
Type:

The families of routes that the document covers

smarter.apps.api.v1.contract.openapi.PATH_PARAMETER_ALIASES: dict[str, str] = {'guardrail_id': 'id', 'hashed_id': 'id', 'llmclient_id': 'id', 'llmhost_id': 'id', 'mcpclient_id': 'id', 'orchestrator_id': 'id', 'pk': 'id', 'secret_id': 'id', 'vectorsearch_id': 'id', 'vectorstore_id': 'id'}

The document’s names of the routes’ path parameters, where they differ.

A resource’s routes take either its numeric id or its hashed id, which the document describes as one {id}.

{
    'guardrail_id': 'id',
    'hashed_id': 'id',
    'llmclient_id': 'id',
    'llmhost_id': 'id',
    'mcpclient_id': 'id',
    'orchestrator_id': 'id',
    'pk': 'id',
    'secret_id': 'id',
    'vectorsearch_id': 'id',
    'vectorstore_id': 'id',
}
smarter.apps.api.v1.contract.openapi.UNDOCUMENTED_ROUTES: dict[str, str] = {'/accounts/batch-create-users/': 'Creates users from a CSV file in the web console. Clients apply User manifests with the cli api.', '/llm-clients/{id}/functions/{function_id}/plugins': 'It returns every plugin of the LLMClient, whatever the function, because it is routed to LLMClientPluginListView. Not published until it is fixed or removed.', '/llm-clients/{id}/prompt/config/': 'A legacy alias of /llm-clients/{id}/config/, for pages that installed an older Smarter Chat.', '/orchestrators/{id}/orchestrator/': 'Running an Orchestrator is not implemented yet: the route has no POST handler, and answers 405.', '/plugins/add-example-plugins/{user_id}/': "A web console action, which clients replace with the cli api's manifests.", '/plugins/upload/': "A web console action, which clients replace with the cli api's manifests.", '/plugins/{plugin_id}/clone/{new_name}': "A web console action, which clients replace with the cli api's manifests.", '/prompts/passthrough/{provider_name}/': "A passthrough to an LLM provider's api, whose requests and responses are the provider's, not Smarter's.", '/prompts/smarter/{provider_name}/': "The chat api of an LLM provider through Smarter, whose requests and responses are the provider's, not Smarter's.", '/proxy/{name}/': "A Proxy's passthrough, whose requests and responses are its provider's api, not Smarter's.", '/proxy/{name}/{path}': "A Proxy's passthrough, whose requests and responses are its provider's api, not Smarter's.", '/vectorsearches/{id}/vectorsearch/': 'Running a Vectorsearch is not implemented yet: the route has no POST handler, and answers 405.'}

The paths of the routes of DOCUMENTED_URLCONFS that the document leaves out, and why.

{
    '/accounts/batch-create-users/': 'Creates users from a CSV file in the web console. Clients apply User manifests with the cli api.',
    '/llm-clients/{id}/functions/{function_id}/plugins': 'It returns every plugin of the LLMClient, whatever the function, because it is routed to LLMClientPluginListView. Not published until it is fixed or removed.',
    '/llm-clients/{id}/prompt/config/': 'A legacy alias of /llm-clients/{id}/config/, for pages that installed an older Smarter Chat.',
    '/orchestrators/{id}/orchestrator/': 'Running an Orchestrator is not implemented yet: the route has no POST handler, and answers 405.',
    '/plugins/add-example-plugins/{user_id}/': "A web console action, which clients replace with the cli api's manifests.",
    '/plugins/upload/': "A web console action, which clients replace with the cli api's manifests.",
    '/plugins/{plugin_id}/clone/{new_name}': "A web console action, which clients replace with the cli api's manifests.",
    '/prompts/passthrough/{provider_name}/': "A passthrough to an LLM provider's api, whose requests and responses are the provider's, not Smarter's.",
    '/prompts/smarter/{provider_name}/': "The chat api of an LLM provider through Smarter, whose requests and responses are the provider's, not Smarter's.",
    '/proxy/{name}/': "A Proxy's passthrough, whose requests and responses are its provider's api, not Smarter's.",
    '/proxy/{name}/{path}': "A Proxy's passthrough, whose requests and responses are its provider's api, not Smarter's.",
    '/vectorsearches/{id}/vectorsearch/': 'Running a Vectorsearch is not implemented yet: the route has no POST handler, and answers 405.',
}
smarter.apps.api.v1.contract.openapi.UNDOCUMENTED_URLCONFS: dict[str, str] = {'/tests/': "Views that only the platform's own unit tests call."}

The families of routes under /api/v1 that the document leaves out, and why.

Every family that smarter.apps.api.v1.urls mounts must be in DOCUMENTED_URLCONFS or here.

{'/tests/': "Views that only the platform's own unit tests call."}
smarter.apps.api.v1.contract.openapi.chat_paths()[source]

The chat api’s paths, relative to the server’s /api/v1.

The prompt’s 200 response is JSON, or, for a client that accepts text/event-stream, a stream of Server-Sent Events: progress events, then one result event, whose response is the JSON that a non-streaming client receives. OpenAPI 3.1 can’t type the events of a stream, so the stream’s media type names their schemas in an x-smarter-events extension.

Returns:

The paths, e.g. {"/llm-clients/{id}/prompt/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.cli_paths()[source]

The cli api’s paths, relative to the server’s /api/v1, by the url names of their routes.

Returns:

The paths, e.g. {"/cli/apply/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.cli_schemas()[source]

Every schema of the document: the models’ schemas, a manifest of any kind, and the responses of the commands.

Returns:

The schemas, by name, and the SAM kinds.

Return type:

tuple[dict[str, TypeAliasType], list[str]]

smarter.apps.api.v1.contract.openapi.guardrail_paths()[source]

The Guardrails’ REST reads, and the dry run of a Guardrail, relative to the server’s /api/v1.

Returns:

The paths, e.g. {"/guardrails/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.id_or_hashed_id(resource)[source]

The {id} path parameter of a resource whose routes take its numeric id or its hashed id.

Parameters:

resource (str) – The resource’s kind, e.g. Guardrail.

Returns:

The parameter.

Return type:

OpenApiParameter

smarter.apps.api.v1.contract.openapi.llmclient_paths()[source]

The REST reads of the LLMClients, relative to the server’s /api/v1.

An LLMClient is read by its numeric id or its hashed id. Its related rows, by its numeric id only: their routes take no hashed id.

Returns:

The paths, e.g. {"/llm-clients/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.llmhost_paths()[source]

The LLMHosts’ REST reads, discovery and deployment, relative to the server’s /api/v1.

Returns:

The paths, e.g. {"/llmhosts/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.mcpclient_paths()[source]

The MCPClients’ REST reads, their reconnection, and the call of a tool, relative to the server’s /api/v1.

Returns:

The paths, e.g. {"/mcpclients/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.merge_paths(*families)[source]

The paths of several families, with the operations of a path that two families share in one path item.

Parameters:

families (dict[str, OpenApiPathItem]) – Each family’s paths.

Returns:

The paths.

Return type:

dict[str, OpenApiPathItem]

Raises:

ValueError – If two families define the same method of a path.

smarter.apps.api.v1.contract.openapi.openapi_document()[source]

The Smarter api’s OpenAPI document.

Returns:

The document.

Return type:

OpenApiDocument

smarter.apps.api.v1.contract.openapi.openapi_json()[source]

The Smarter api’s OpenAPI document, as the text of openapi.json.

Returns:

The document, as indented JSON, with a final newline.

Return type:

str

smarter.apps.api.v1.contract.openapi.plugin_paths()[source]

The plugins’ REST reads, relative to the server’s /api/v1.

Returns:

The paths, e.g. {"/plugins/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.provider_paths()[source]

The Providers’ REST reads, relative to the server’s /api/v1.

A Provider is read by its name.

Returns:

The paths, e.g. {"/providers/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.proxy_paths()[source]

The Proxies’ list, relative to the server’s /api/v1.

Their passthroughs are the providers’ apis.

Returns:

The paths, e.g. {"/proxy/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.query(name, description, schema, required=False)[source]

A query parameter.

Parameters:
  • name (str) – The parameter’s name.

  • description (str) – Its description.

  • schema (TypeAliasType) – Its JSON Schema.

  • required (bool) – Whether it is required.

Returns:

The parameter.

Return type:

OpenApiParameter

smarter.apps.api.v1.contract.openapi.rest_operation(operation_id, summary, description, tag, response, *, parameters, status='200', request_body=None)[source]

An operation of the REST api, whose success is one of the document’s schemas, and whose errors are DRF’s.

Parameters:
  • operation_id (str) – The operation’s id, e.g. vectorstore_search.

  • summary (str) – A one-line summary.

  • description (str) – A description, which says who may call it, and what it changes.

  • tag (str) – The operation’s tag.

  • response (str) – The successful response’s schema, in components.schemas.

  • parameters (list[OpenApiParameter]) – The operation’s parameters.

  • status (str) – The successful response’s http status, e.g. 202 for queued work.

  • request_body (OpenApiRequestBody | None) – The operation’s request body.

Returns:

The operation.

Return type:

OpenApiOperation

smarter.apps.api.v1.contract.openapi.rest_read(operation_id, summary, description, tag, item, *, many, parameters, note="Requires an api key of a superuser: the REST api's views refuse other users with a 403. Other users read their resources with the cli api's get and describe.")[source]

A read of the REST api: a GET whose response is a row, or a list of rows, of one of the document’s schemas.

Parameters:
  • operation_id (str) – The operation’s id, e.g. llmclient_list.

  • summary (str) – A one-line summary.

  • description (str) – A description, to which note is added.

  • tag (str) – The operation’s tag.

  • item (str) – The schema of a row, in components.schemas.

  • many (bool) – Whether the response is a list of rows.

  • parameters (list[OpenApiParameter]) – The operation’s parameters.

  • note (str) – Who may read, e.g. SUPERUSER_ONLY or READ_PERMISSION.

Returns:

The operation.

Return type:

OpenApiOperation

smarter.apps.api.v1.contract.openapi.secret_paths()[source]

The Secrets’ REST reads, relative to the server’s /api/v1.

A Secret’s value is never returned.

Returns:

The paths, e.g. {"/secrets/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.vectorstore_paths()[source]

The vectorstores’ REST reads and maintenance, relative to the server’s /api/v1.

Reading and searching need read permission. Everything else needs ownership.

Returns:

The paths, e.g. {"/vectorstores/": ...}.

Return type:

dict[str, OpenApiPathItem]

smarter.apps.api.v1.contract.openapi.write_openapi(path='/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/api/v1/contract/openapi.json')[source]

Write the Smarter api’s OpenAPI document.

Parameters:

path (str) – The file to write. Defaults to openapi.json, beside this module.

Returns:

The path that was written.

Return type:

str

Pydantic models of the account data that the REST api’s responses include.

A resource that a user owns, e.g. an LLMClient or a plugin, is returned with its owner, as AccountApiUserProfile: the owner’s username and email, and their account’s number. It is the output of smarter.apps.account.serializers.UserProfileSerializer, which the REST api returned before it was modeled, and which clients already read.

The accounts’ REST api (/api/v1/accounts/), which only superusers may call, returns accounts (AccountApiAccountDetail), users (AccountApiUserDetail), user profiles (AccountApiProfile) and account contacts (AccountApiContact): the outputs of smarter.apps.account.serializers.AccountSerializer, UserSerializer and AccountContactSerializer, which clients already read.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.account.contract.models.ACCOUNT_API_MODELS = (<class 'smarter.apps.account.contract.models.AccountApiAccountDetail'>, <class 'smarter.apps.account.contract.models.AccountApiUserDetail'>, <class 'smarter.apps.account.contract.models.AccountApiProfile'>, <class 'smarter.apps.account.contract.models.AccountApiContact'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

(
    <class 'smarter.apps.account.contract.models.AccountApiAccountDetail'>,
    <class 'smarter.apps.account.contract.models.AccountApiUserDetail'>,
    <class 'smarter.apps.account.contract.models.AccountApiProfile'>,
    <class 'smarter.apps.account.contract.models.AccountApiContact'>,
)
class smarter.apps.account.contract.models.AccountApiAccount(**data)[source]

Bases: AccountApiModel

An account, as the owner of a resource: a smarter.apps.account.models.Account’s number.

account_number: str
classmethod from_model(account)[source]

The contract’s model of an account.

Parameters:

account (Account) – The row.

Returns:

The model.

Return type:

AccountApiAccount

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.account.contract.models.AccountApiAccountDetail(**data)[source]

Bases: AccountApiModel

An account: a smarter.apps.account.models.Account.

account_number: str | None
address1: str | None
address2: str | None
annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
city: str | None
company_name: str
country: str | None
created_at: datetime | None
currency: str | None
description: str | None
classmethod from_model(account)[source]

The contract’s model of an account.

Parameters:

account (Account) – The row.

Returns:

The model.

Return type:

AccountApiAccountDetail

hashed_id: str
id: int
is_active: bool
is_default_account: bool
language: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
phone_number: str | None
postal_code: str | None
state: str | None
tags: list[str]
timezone: str | None
updated_at: datetime | None
version: str | None
class smarter.apps.account.contract.models.AccountApiContact(**data)[source]

Bases: AccountApiModel

A contact of an account, who receives its notices: a smarter.apps.account.models.AccountContact.

account: AccountApiAccount
created_at: datetime | None
email: str
first_name: str
classmethod from_model(contact)[source]

The contract’s model of an account contact.

Parameters:

contact (AccountContact) – The row, whose account should be fetched with it.

Returns:

The model.

Return type:

AccountApiContact

id: int
is_primary: bool
is_test: bool
last_name: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

phone: str | None
updated_at: datetime | None
welcomed: bool
class smarter.apps.account.contract.models.AccountApiModel(**data)[source]

Bases: BaseModel

Base class of the account contract’s models.

The api’s JSON is camelCase, e.g. accountNumber. The models’ fields are snake_case, and their camelCase aliases are what they validate and dump.

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.account.contract.models.AccountApiProfile(**data)[source]

Bases: AccountApiModel

A user’s membership of an account: a smarter.apps.account.models.UserProfile.

account: AccountApiAccount
annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
created_at: datetime | None
description: str | None
classmethod from_model(user_profile)[source]

The contract’s model of a user profile.

Parameters:

user_profile (UserProfile) – The row, whose user and account should be fetched with it.

Returns:

The model.

Return type:

AccountApiProfile

hashed_id: str
id: int
is_test: bool
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
profile_image_url: str | None
tags: list[str]
updated_at: datetime | None
user: AccountApiUserDetail
version: str | None
class smarter.apps.account.contract.models.AccountApiUser(**data)[source]

Bases: AccountApiModel

A user, as the owner of a resource: a django.contrib.auth.models.User’s username and email.

email: str | None
classmethod from_model(user)[source]

The contract’s model of a user.

Parameters:

user (User) – The row.

Returns:

The model.

Return type:

AccountApiUser

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

username: str
class smarter.apps.account.contract.models.AccountApiUserDetail(**data)[source]

Bases: AccountApiModel

A user: a django.contrib.auth.models.User, without its password and permissions.

email: str
first_name: str
classmethod from_model(user)[source]

The contract’s model of a user.

Parameters:

user (User) – The row.

Returns:

The model.

Return type:

AccountApiUserDetail

id: int
is_staff: bool
is_superuser: bool
last_name: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

username: str
class smarter.apps.account.contract.models.AccountApiUserProfile(**data)[source]

Bases: AccountApiModel

The owner of a resource: a smarter.apps.account.models.UserProfile’s user and account.

account: AccountApiAccount
classmethod from_model(user_profile)[source]

The contract’s model of a resource’s owner.

Parameters:

user_profile (UserProfile) – The row, whose user and account should be fetched with it.

Returns:

The model.

Return type:

AccountApiUserProfile

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

user: AccountApiUser
smarter.apps.account.contract.models.MetaDataApiAnnotations = list[dict[str, JsonValue]] | dict[str, JsonValue] | None

a list of key-value pairs, e.g. [{"smarter.sh/purpose": "example"}], or,.

in legacy rows, an object.

Type:

MetaDataModel.annotations

Pydantic models of the plugin data that the REST api’s responses include.

PluginApiPluginMeta is a plugin’s metadata, as the REST api returns it, e.g. in an LLMClient’s plugins. It is the output of smarter.apps.plugin.serializers.PluginMetaSerializer, which the REST api returned before it was modeled, and which clients already read: the owner is nested, rather than its id.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.plugin.contract.models.PluginApiPluginClass

the choices of PluginMeta.plugin_class.

A test fails if the two differ.

Type:

A plugin’s class

alias of Literal[‘api’, ‘skill’, ‘sql’, ‘static’, ‘websearch’, ‘imagesearch’]

class smarter.apps.plugin.contract.models.PluginApiPluginMeta(**data)[source]

Bases: AccountApiModel

A plugin’s metadata: a smarter.apps.plugin.models.PluginMeta.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
can_delete: bool
created_at: datetime | None
description: str | None
classmethod from_model(plugin_meta, user=None)[source]

The contract’s model of a plugin’s metadata.

Parameters:
  • plugin_meta (PluginMeta) – The row, whose user_profile and tags should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

PluginApiPluginMeta

id: int
kind: str
manifest_url: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
plugin_class: Literal['api', 'skill', 'sql', 'static', 'websearch', 'imagesearch']
ready: bool
tags: list[str]
updated_at: datetime | None
user_profile: AccountApiUserProfile
version: str | None

Pydantic models of the LLMClients’ REST api responses (/api/v1/llm-clients/).

The REST api’s views build their responses from these models, and the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes their JSON Schemas. Each model is built from its row by from_model().

They describe the JSON that smarter.apps.llmclient.serializers produced before the api was modeled, which clients already read: camelCase keys, an LLMClient’s owner nested rather than its id, and an LLMClient’s related rows inline. Two values changed: canDelete is computed for the requesting user, where the serializers, called without a request, always said false, and an api key’s apiKey is its token’s public key_id, where it was the token’s digest.

The models forbid extra fields: the api returns exactly what they declare. Adding a field is backward compatible. Removing or renaming one is not.

smarter.apps.llmclient.contract.models.LLMCLIENT_API_MODELS = (<class 'smarter.apps.llmclient.contract.models.LLMClientApiLLMClient'>, <class 'smarter.apps.llmclient.contract.models.LLMClientApiPlugin'>, <class 'smarter.apps.llmclient.contract.models.LLMClientApiFunction'>, <class 'smarter.apps.llmclient.contract.models.LLMClientApiKey'>, <class 'smarter.apps.llmclient.contract.models.LLMClientApiCustomDomain'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

Their dependencies are included with them.

(
    <class 'smarter.apps.llmclient.contract.models.LLMClientApiLLMClient'>,
    <class 'smarter.apps.llmclient.contract.models.LLMClientApiPlugin'>,
    <class 'smarter.apps.llmclient.contract.models.LLMClientApiFunction'>,
    <class 'smarter.apps.llmclient.contract.models.LLMClientApiKey'>,
    <class 'smarter.apps.llmclient.contract.models.LLMClientApiCustomDomain'>,
)
class smarter.apps.llmclient.contract.models.LLMClientApiCustomDomain(**data)[source]

Bases: LLMClientApiOrmModel

A custom domain of an LLMClient: a smarter.apps.llmclient.models.LLMClientCustomDomain.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
aws_hosted_zone_id: str
description: str | None
domain_name: str
classmethod from_model(custom_domain)[source]

The contract’s model of a custom domain.

Parameters:

custom_domain (LLMClientCustomDomain) – The row.

Returns:

The model.

Return type:

LLMClientApiCustomDomain

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
user_profile: int
verification_message: str
verification_status: Literal['Not Verified', 'Verifying', 'Verified', 'Failed']
verified_at: datetime | None
version: str | None
smarter.apps.llmclient.contract.models.LLMClientApiDnsVerificationStatus

The choices of LLMClient.dns_verification_status.

A test fails if the two differ.

alias of Literal[‘Verifying’, ‘Not Verified’, ‘Verified’, ‘Failed’]

class smarter.apps.llmclient.contract.models.LLMClientApiFunction(**data)[source]

Bases: LLMClientApiOrmModel

A built-in function of an LLMClient: a smarter.apps.llmclient.models.LLMClientFunctions.

classmethod from_model(function)[source]

The contract’s model of a built-in function of an LLMClient.

Parameters:

function (LLMClientFunctions) – The row.

Returns:

The model.

Return type:

LLMClientApiFunction

llmclient: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: Literal['get_current_weather', 'date_calculator', 'calculator'] | None
smarter.apps.llmclient.contract.models.LLMClientApiFunctionName

the choices of LLMClientFunctions.name.

A test fails if the two differ.

Type:

A built-in function’s name

alias of Literal[‘get_current_weather’, ‘date_calculator’, ‘calculator’]

class smarter.apps.llmclient.contract.models.LLMClientApiKey(**data)[source]

Bases: LLMClientApiOrmModel

An api key of an LLMClient: a smarter.apps.llmclient.models.LLMClientAPIKey.

api_key: UUID
classmethod from_model(api_key)[source]

The contract’s model of an api key of an LLMClient.

Parameters:

api_key (LLMClientAPIKey) – The row, whose api_key should be fetched with it.

Returns:

The model.

Return type:

LLMClientApiKey

llmclient: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.llmclient.contract.models.LLMClientApiLLMClient(**data)[source]

Bases: LLMClientApiOrmModel

An LLMClient: a smarter.apps.llmclient.models.LLMClient, with its related rows and its urls.

Its functions, plugins, custom_domains and api_keys are inline, and its urls and hosts are computed, as the LLMClient’s properties compute them for the platform that serves the request.

allowed_origins: list[str]
annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
api_keys: list[LLMClientApiKey]
app_assistant: str | None
app_example_prompts: list[str] | None
app_file_attachment: bool | None
app_info_url: str | None
app_name: str | None
app_placeholder: str | None
app_welcome_message: str | None
base_api_domain: str | None
base_default_host: str | None
can_delete: bool
custom_domain: int | None
custom_domains: list[LLMClientApiCustomDomain]
custom_host: str | None
custom_url: str | None
default_host: str | None
default_max_tokens: int | None
default_model: str | None
default_system_role: str | None
default_temperature: float | None
default_url: str | None
deployed: bool | None
description: str | None
dns_verification_status: Literal['Verifying', 'Not Verified', 'Verified', 'Failed'] | None
classmethod from_model(llmclient, user=None)[source]

The contract’s model of an LLMClient.

Parameters:
  • llmclient (LLMClient) – The row, whose user_profile should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

LLMClientApiLLMClient

functions: list[LLMClientApiFunction]
hashed_id: str
hostname: str | None
is_authentication_required: bool
manifest_url: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
plugins: list[LLMClientApiPluginRef]
provider: str | None
ready: bool
rfc1034_compliant_name: str | None
sandbox_host: str | None
sandbox_url: str | None
styles: dict[str, JsonValue] | None
subdomain: int | None
tags: list[str]
tls_certificate_issuance_status: Literal['No Certificate', 'Requested', 'Issued', 'Failed'] | None
url: str | None
url_chat_config: str | None
url_chatapp: str | None
url_llmclient: str | None
user_profile: AccountApiUserProfile
version: str | None
class smarter.apps.llmclient.contract.models.LLMClientApiOrmModel(**data)[source]

Bases: AccountApiModel

Base class of the models of LLMClient rows: their primary key and timestamps.

created_at: datetime | None
id: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

updated_at: datetime | None
class smarter.apps.llmclient.contract.models.LLMClientApiPlugin(**data)[source]

Bases: LLMClientApiOrmModel

A plugin of an LLMClient: a smarter.apps.llmclient.models.LLMClientPlugin, with the plugin’s metadata.

classmethod from_model(plugin, user=None)[source]

The contract’s model of a plugin of an LLMClient.

Parameters:
  • plugin (LLMClientPlugin) – The row, whose plugin_meta should be fetched with it.

  • user (object) – The requesting user, for the plugin’s canDelete.

Returns:

The model.

Return type:

LLMClientApiPlugin

llmclient: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

plugin_meta: PluginApiPluginMeta
class smarter.apps.llmclient.contract.models.LLMClientApiPluginRef(**data)[source]

Bases: AccountApiModel

A plugin of an LLMClient, in the LLMClient’s own response: the LLMClientPlugin’s id, and the plugin’s name.

classmethod from_model(plugin)[source]

The contract’s reference to a plugin of an LLMClient.

Parameters:

plugin (LLMClientPlugin) – The row, whose plugin_meta should be fetched with it.

Returns:

The model.

Return type:

LLMClientApiPluginRef

id: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
smarter.apps.llmclient.contract.models.LLMClientApiTlsCertificateIssuanceStatus

The choices of LLMClient.tls_certificate_issuance_status.

A test fails if the two differ.

alias of Literal[‘No Certificate’, ‘Requested’, ‘Issued’, ‘Failed’]

smarter.apps.llmclient.contract.models.LLMClientApiVerificationStatus

The choices of LLMClientCustomDomain.verification_status.

A test fails if the two differ.

alias of Literal[‘Not Verified’, ‘Verifying’, ‘Verified’, ‘Failed’]

Pydantic models of the Guardrails’ REST api requests and responses (/api/v1/guardrails/).

The REST api’s views build their responses from these models, and the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes their JSON Schemas.

GuardrailApiGuardrail is a Guardrail, as smarter.apps.guardrail.serializers.GuardrailSerializer returned it before the api was modeled, and GuardrailApiEvent an event, as GuardrailEventSerializer returned it. Clients already read them, so their shapes are kept: a Guardrail’s keys are camelCase, and an event’s snake_case. One value changed: a Guardrail’s canDelete is computed for the requesting user. The serializer was called without a request, so it was always false.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.guardrail.contract.models.GUARDRAIL_API_MODELS = (<class 'smarter.apps.guardrail.contract.models.GuardrailApiGuardrail'>, <class 'smarter.apps.guardrail.contract.models.GuardrailApiEvents'>, <class 'smarter.apps.guardrail.contract.models.GuardrailApiEvaluateRequest'>, <class 'smarter.apps.guardrail.contract.models.GuardrailApiEvaluation'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

Their dependencies are included with them.

(
    <class 'smarter.apps.guardrail.contract.models.GuardrailApiGuardrail'>,
    <class 'smarter.apps.guardrail.contract.models.GuardrailApiEvents'>,
    <class 'smarter.apps.guardrail.contract.models.GuardrailApiEvaluateRequest'>,
    <class 'smarter.apps.guardrail.contract.models.GuardrailApiEvaluation'>,
)
smarter.apps.guardrail.contract.models.GuardrailApiAction

The choices of Guardrail.action.

A test fails if the two differ.

alias of Literal[‘log’, ‘flag’, ‘redact’, ‘transform’, ‘block’, ‘escalate’]

smarter.apps.guardrail.contract.models.GuardrailApiCategory

The choices of Guardrail.category.

A test fails if the two differ.

alias of Literal[‘pii’, ‘secrets’, ‘prompt_injection’, ‘jailbreak’, ‘toxicity’, ‘self_harm’, ‘hallucination’, ‘off_topic’, ‘compliance’, ‘formatting’, ‘custom’]

class smarter.apps.guardrail.contract.models.GuardrailApiEvaluateRequest(**data)[source]

Bases: GuardrailApiSnakeModel

The request body of a dry run of a Guardrail on a text.

model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

stage: Literal['input', 'output']
text: str
class smarter.apps.guardrail.contract.models.GuardrailApiEvaluation(**data)[source]

Bases: AccountApiModel

The result of a dry run of a Guardrail on a text.

It records no events.

disposition: PipelineDisposition
duration_ms: float | None
error: str | None
findings: list[GuardrailApiFinding]
guardrail: str
message: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

stage: Literal['input', 'output']
text: str
triggered: bool
class smarter.apps.guardrail.contract.models.GuardrailApiEvent(**data)[source]

Bases: GuardrailApiSnakeModel

A Guardrail’s event: a smarter.apps.guardrail.models.GuardrailEvent, a record of what it did to a prompt.

Its keys are snake_case: the serializer that the api used was not camelCase.

action: Literal['log', 'flag', 'redact', 'transform', 'block', 'escalate']
category: Literal['pii', 'secrets', 'prompt_injection', 'jailbreak', 'toxicity', 'self_harm', 'hallucination', 'off_topic', 'compliance', 'formatting', 'custom']
confidence: float | None
created_at: datetime | None
disposition: Literal['logged', 'flagged', 'redacted', 'transformed', 'blocked', 'escalated', 'monitored', 'error']
error: str | None
excerpt: str | None
classmethod from_model(event)[source]

The contract’s model of a Guardrail’s event.

Parameters:

event (GuardrailEvent) – The row, whose llmclient should be fetched with it.

Returns:

The model.

Return type:

GuardrailApiEvent

guardrail: int | None
guardrail_name: str
id: int
llmclient: str | None
mode: Literal['enforce', 'monitor']
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

rationale: str | None
reviewed: bool
session_key: str | None
severity: int
stage: Literal['input', 'output', 'both']
strategy: Literal['regex', 'keyword', 'detector', 'semantic', 'moderation', 'llm_judge']
updated_at: datetime | None
smarter.apps.guardrail.contract.models.GuardrailApiEventDisposition

what a guardrail did.

A test fails if the two differ.

Type:

The choices of GuardrailEvent.disposition

alias of Literal[‘logged’, ‘flagged’, ‘redacted’, ‘transformed’, ‘blocked’, ‘escalated’, ‘monitored’, ‘error’]

class smarter.apps.guardrail.contract.models.GuardrailApiEvents(**data)[source]

Bases: GuardrailApiSnakeModel

The response of a Guardrail’s events: its name, and its latest events, newest first.

events: list[GuardrailApiEvent]
guardrail: str
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.guardrail.contract.models.GuardrailApiFinding(**data)[source]

Bases: GuardrailApiSnakeModel

What a Guardrail found in a text.

confidence: float | None
matches: list[GuardrailMatch]
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

rationale: str | None
class smarter.apps.guardrail.contract.models.GuardrailApiGuardrail(**data)[source]

Bases: AccountApiModel

A Guardrail: a smarter.apps.guardrail.models.Guardrail.

action: Literal['log', 'flag', 'redact', 'transform', 'block', 'escalate']
annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
can_delete: bool
category: Literal['pii', 'secrets', 'prompt_injection', 'jailbreak', 'toxicity', 'self_harm', 'hallucination', 'off_topic', 'compliance', 'formatting', 'custom']
config: dict[str, JsonValue] | None
created_at: datetime | None
description: str | None
fail_closed: bool
classmethod from_model(guardrail, user=None)[source]

The contract’s model of a Guardrail.

Parameters:
  • guardrail (Guardrail) – The row, whose user_profile should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

GuardrailApiGuardrail

hashed_id: str
id: int
is_active: bool
manifest_url: str
message: str | None
mode: Literal['enforce', 'monitor']
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
pattern: str | None
priority: int
ready: bool
replacement: str | None
rfc1034_compliant_name: str | None
severity: int
stage: Literal['input', 'output', 'both']
strategy: Literal['regex', 'keyword', 'detector', 'semantic', 'moderation', 'llm_judge']
tags: list[str]
threshold: float | None
updated_at: datetime | None
user_profile: AccountApiUserProfile
version: str | None
smarter.apps.guardrail.contract.models.GuardrailApiMode

The choices of Guardrail.mode.

A test fails if the two differ.

alias of Literal[‘enforce’, ‘monitor’]

class smarter.apps.guardrail.contract.models.GuardrailApiSnakeModel(**data)[source]

Bases: BaseModel

Base class of the guardrail contract’s models whose keys are snake_case, as their api returned them.

model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

smarter.apps.guardrail.contract.models.GuardrailApiStage

The choices of Guardrail.stage.

A test fails if the two differ.

alias of Literal[‘input’, ‘output’, ‘both’]

smarter.apps.guardrail.contract.models.GuardrailApiStrategy

The choices of Guardrail.strategy.

A test fails if the two differ.

alias of Literal[‘regex’, ‘keyword’, ‘detector’, ‘semantic’, ‘moderation’, ‘llm_judge’]

Pydantic models of the Secrets’ REST api responses (/api/v1/secrets/).

A Secret’s response is its metadata. Its value is never returned.

SecretApiSecret is a Secret, as smarter.apps.secret.serializers.SecretSerializer returned it before the api was modeled, which clients already read. One value changed: its canDelete is computed for the requesting user. The serializer was called without a request, so it was always false.

smarter.apps.secret.contract.models.SECRET_API_MODELS = (<class 'smarter.apps.secret.contract.models.SecretApiSecret'>,)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

(<class 'smarter.apps.secret.contract.models.SecretApiSecret'>, )
class smarter.apps.secret.contract.models.SecretApiSecret(**data)[source]

Bases: AccountApiModel

A Secret’s metadata: a smarter.apps.secret.models.Secret, without its value.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
can_delete: bool
created_at: datetime | None
description: str | None
expires_at: datetime | None
classmethod from_model(secret, user=None)[source]

The contract’s model of a Secret.

Parameters:
  • secret (Secret) – The row, whose user_profile should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

SecretApiSecret

id: int
last_accessed: datetime | None
manifest_url: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
ready: bool
tags: list[str]
updated_at: datetime | None
user_profile: AccountApiUserProfile
version: str | None
class smarter.apps.secret.contract.models.SecretApiSecretRef(**data)[source]

Bases: AccountApiModel

A Secret, as another resource refers to it, e.g. a Provider’s api key: its name, never its value.

can_delete: bool
classmethod from_model(secret, user=None)[source]

The contract’s reference to a Secret.

Parameters:
  • secret (Secret) – The row.

  • user (object) – The requesting user, for can_delete.

Returns:

The model.

Return type:

SecretApiSecretRef

id: int
manifest_url: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
ready: bool

Pydantic models of the MCPClients’ REST api responses (/api/v1/mcpclients/).

The REST api’s views build their responses from these models, and the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes their JSON Schemas.

MCPClientApiMCPClient is an MCPClient, as smarter.apps.mcpclient.serializers.MCPClientSerializer returned it before the api was modeled, which clients already read. One value changed: its canDelete is computed for the requesting user. The other models replace the dicts that the views built by hand, with the same keys. lastConnected is now an ISO 8601 date-time ending in Z, where it ended in +00:00: the same instant.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.mcpclient.contract.models.MCPCLIENT_API_MODELS = (<class 'smarter.apps.mcpclient.contract.models.MCPClientApiMCPClient'>, <class 'smarter.apps.mcpclient.contract.models.MCPClientApiStatus'>, <class 'smarter.apps.mcpclient.contract.models.MCPClientApiStatusError'>, <class 'smarter.apps.mcpclient.contract.models.MCPClientApiTools'>, <class 'smarter.apps.mcpclient.contract.models.MCPClientApiToolResult'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

Their dependencies are included with them.

(
    <class 'smarter.apps.mcpclient.contract.models.MCPClientApiMCPClient'>,
    <class 'smarter.apps.mcpclient.contract.models.MCPClientApiStatus'>,
    <class 'smarter.apps.mcpclient.contract.models.MCPClientApiStatusError'>,
    <class 'smarter.apps.mcpclient.contract.models.MCPClientApiTools'>,
    <class 'smarter.apps.mcpclient.contract.models.MCPClientApiToolResult'>,
)
smarter.apps.mcpclient.contract.models.MCPClientApiAuthType

The choices of MCPClient.auth_type.

A test fails if the two differ.

alias of Literal[‘none’, ‘api_key’, ‘oauth2’, ‘bearer_token’]

smarter.apps.mcpclient.contract.models.MCPClientApiConnectionStatus

the result of the last connection.

A test fails if the two differ.

Type:

The choices of MCPClient.status

alias of Literal[‘unconfigured’, ‘connected’, ‘disconnected’, ‘error’]

class smarter.apps.mcpclient.contract.models.MCPClientApiMCPClient(**data)[source]

Bases: AccountApiModel

An MCPClient: a smarter.apps.mcpclient.models.MCPClient.

Its credentials are their Secret’s name.

allowed_resources: list[str] | None
allowed_tools: list[str] | None
annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
api_key_header: str
auth_type: Literal['none', 'api_key', 'oauth2', 'bearer_token']
cache_ttl: int
can_delete: bool
command: str | None
created_at: datetime | None
credentials: str | None
description: str | None
endpoint_url: str | None
classmethod from_model(mcpclient, user=None)[source]

The contract’s model of an MCPClient.

Parameters:
  • mcpclient (MCPClient) – The row, whose user_profile and credentials should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

MCPClientApiMCPClient

hashed_id: str
headers: dict[str, JsonValue] | None
id: int
include_instructions: bool
is_active: bool
last_connected_at: datetime | None
last_error: str | None
manifest_url: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
priority: int
protocol_version: str | None
ready: bool
rfc1034_compliant_name: str | None
server_name: str | None
server_version: str | None
status: Literal['unconfigured', 'connected', 'disconnected', 'error']
tags: list[str]
timeout: int
tools: list[str] | None
transport: Literal['stdio', 'sse', 'http'] | None
updated_at: datetime | None
user_profile: AccountApiUserProfile
version: str | None
class smarter.apps.mcpclient.contract.models.MCPClientApiStatus(**data)[source]

Bases: AccountApiModel

An MCPClient’s connection to its MCP server: the result of the last connection, and what the server reported.

classmethod from_model(mcpclient)[source]

The connection status of an MCPClient.

Parameters:

mcpclient (MCPClient) – The row.

Returns:

The model.

Return type:

MCPClientApiStatus

last_connected: datetime | None
last_error: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
protocol_version: str | None
server_name: str | None
server_version: str | None
status: Literal['unconfigured', 'connected', 'disconnected', 'error']
tools: list[str]
class smarter.apps.mcpclient.contract.models.MCPClientApiStatusError(**data)[source]

Bases: MCPClientApiStatus

A failed connection to an MCP server: the error, beside the MCPClient’s connection status.

detail: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.mcpclient.contract.models.MCPClientApiTool(**data)[source]

Bases: AccountApiModel

A tool that an MCP server offers, and that the MCPClient allows.

description: str
destructive: bool | None
classmethod from_tool(tool)[source]

The contract’s model of a tool from an MCP server’s catalog.

Parameters:

tool (MCPToolInfo) – The tool.

Returns:

The model.

Return type:

MCPClientApiTool

input_schema: dict[str, JsonValue]
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
read_only: bool | None
title: str | None
class smarter.apps.mcpclient.contract.models.MCPClientApiToolResult(**data)[source]

Bases: AccountApiModel

The result of a call of an MCPClient’s tool, as text for an LLM.

content: str
classmethod from_result(mcpclient, tool, result)[source]

The contract’s model of a tool call’s result.

Parameters:
Returns:

The model.

Return type:

MCPClientApiToolResult

is_error: bool
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
tool: str
class smarter.apps.mcpclient.contract.models.MCPClientApiTools(**data)[source]

Bases: AccountApiModel

An MCPClient’s connection status, its server’s instructions, and the tools that it offers the LLM.

classmethod from_catalog(mcpclient, catalog, tools)[source]

The tools of an MCPClient, from its server’s catalog.

Parameters:
Returns:

The model.

Return type:

MCPClientApiTools

instructions: str | None
last_connected: datetime | None
last_error: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
protocol_version: str | None
server_name: str | None
server_version: str | None
status: Literal['unconfigured', 'connected', 'disconnected', 'error']
tools: list[MCPClientApiTool]
smarter.apps.mcpclient.contract.models.MCPClientApiTransport

The choices of MCPClient.transport.

A test fails if the two differ.

alias of Literal[‘stdio’, ‘sse’, ‘http’]

Pydantic models of the vectorstores’ REST api requests and responses (/api/v1/vectorstores/).

The REST api’s views build their responses from these models, and the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes their JSON Schemas.

VectorstoreApiVectorstore, VectorstoreApiDocument and VectorstoreApiSnapshot are the rows, as smarter.apps.vectorstore.serializers returned them before the api was modeled, which clients already read. One value changed: a vectorstore’s canDelete is computed for the requesting user. The serializer was called without a request, so it was always false. The other models replace the dicts that the views built by hand, with the same keys.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.vectorstore.contract.models.VECTORSTORE_API_MODELS = (<class 'smarter.apps.vectorstore.contract.models.VectorstoreApiVectorstore'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiStatus'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiDocuments'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiAddText'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentsAdded'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentDeleted'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSearch'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSearchResults'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshot'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshots'>, <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiRestored'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

Their dependencies are included with them.

(
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiVectorstore'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiStatus'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiDocuments'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiAddText'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentsAdded'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentDeleted'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSearch'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSearchResults'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshot'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshots'>,
    <class 'smarter.apps.vectorstore.contract.models.VectorstoreApiRestored'>,
)
class smarter.apps.vectorstore.contract.models.VectorstoreApiAddText(**data)[source]

Bases: AccountApiModel

The JSON request body that adds a text, or the document at a url, to a vectorstore.

Files are multipart/form-data.

metadata: dict[str, JsonValue] | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
text: str | None
url: str | None
smarter.apps.vectorstore.contract.models.VectorstoreApiBackend

The choices of VectorstoreMeta.backend.

A test fails if the two differ.

alias of Literal[‘qdrant’, ‘pinecone’]

class smarter.apps.vectorstore.contract.models.VectorstoreApiDocument(**data)[source]

Bases: AccountApiModel

A document of a vectorstore: a smarter.apps.vectorstore.models.VectorstoreDocument, without its content.

chunk_count: int
content_type: str
created_at: datetime | None
classmethod from_model(document)[source]

The contract’s model of a vectorstore’s document.

Parameters:

document (VectorstoreDocument) – The row.

Returns:

The model.

Return type:

VectorstoreApiDocument

hashed_id: str
id: int
loaded_at: datetime | None
metadata: dict[str, JsonValue]
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
sha256: str
size_bytes: int
source: Literal['upload', 'url', 'text', 'file']
status: Literal['pending', 'loading', 'loaded', 'failed', 'deleting']
status_message: str
updated_at: datetime | None
class smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentDeleted(**data)[source]

Bases: AccountApiModel

A document that is being removed, with its chunks.

document: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

status: Literal['pending', 'loading', 'loaded', 'failed', 'deleting']
smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentSource

The choices of VectorstoreDocument.source.

A test fails if the two differ.

alias of Literal[‘upload’, ‘url’, ‘text’, ‘file’]

smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentStatus

The choices of VectorstoreDocument.status.

A test fails if the two differ.

alias of Literal[‘pending’, ‘loading’, ‘loaded’, ‘failed’, ‘deleting’]

class smarter.apps.vectorstore.contract.models.VectorstoreApiDocuments(**data)[source]

Bases: AccountApiModel

A vectorstore’s documents, newest first.

documents: list[VectorstoreApiDocument]
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.vectorstore.contract.models.VectorstoreApiDocumentsAdded(**data)[source]

Bases: AccountApiModel

The documents that a request added, the ones that the vectorstore already had, and whether they’re queued.

documents: list[VectorstoreApiDocument]
duplicates: list[VectorstoreApiDocument]
message: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

queued: bool
smarter.apps.vectorstore.contract.models.VectorstoreApiHosting

The choices of VectorstoreMeta.hosting.

A test fails if the two differ.

alias of Literal[‘self_hosted’, ‘managed’]

smarter.apps.vectorstore.contract.models.VectorstoreApiMetric

The choices of VectorstoreMeta.metric.

A test fails if the two differ.

alias of Literal[‘cosine’, ‘euclidean’, ‘dotproduct’]

class smarter.apps.vectorstore.contract.models.VectorstoreApiRestored(**data)[source]

Bases: AccountApiModel

A vectorstore whose data was replaced with one of its snapshots.

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

restored: str
vector_count: int
vectorstore: str
class smarter.apps.vectorstore.contract.models.VectorstoreApiSearch(**data)[source]

Bases: AccountApiModel

The request body of a search of a vectorstore.

fetch_k: int | None
filter: dict[str, JsonValue] | None
k: int
lambda_mult: float | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

query: str
score_threshold: float | None
search_type: Literal['similarity', 'similarity_score_threshold', 'mmr']
class smarter.apps.vectorstore.contract.models.VectorstoreApiSearchResult(**data)[source]

Bases: AccountApiModel

A chunk that a search found.

classmethod from_result(result)[source]

The contract’s model of a search result.

Parameters:

result (SearchResult) – The result.

Returns:

The model.

Return type:

VectorstoreApiSearchResult

id: str | None
metadata: dict[str, JsonValue]
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

score: float | None
text: str
class smarter.apps.vectorstore.contract.models.VectorstoreApiSearchResults(**data)[source]

Bases: AccountApiModel

The results of a search of a vectorstore, most similar first.

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

results: list[VectorstoreApiSearchResult]
vectorstore: str
smarter.apps.vectorstore.contract.models.VectorstoreApiSearchType

smarter.apps.vectorstore.backends.base.SEARCH_TYPES.

A test fails if the two differ.

Type:

The search types

alias of Literal[‘similarity’, ‘similarity_score_threshold’, ‘mmr’]

class smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshot(**data)[source]

Bases: AccountApiModel

A snapshot of a vectorstore: a smarter.apps.vectorstore.models.VectorstoreSnapshot, a Qdrant snapshot or Pinecone backup.

created_at: datetime | None
classmethod from_model(snapshot)[source]

The contract’s model of a vectorstore’s snapshot.

Parameters:

snapshot (VectorstoreSnapshot) – The row.

Returns:

The model.

Return type:

VectorstoreApiSnapshot

hashed_id: str
id: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
scheduled: bool
size_bytes: int | None
status: Literal['creating', 'ready', 'failed']
status_message: str
updated_at: datetime | None
vector_count: int | None
smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshotStatus

The choices of VectorstoreSnapshot.status.

A test fails if the two differ.

alias of Literal[‘creating’, ‘ready’, ‘failed’]

class smarter.apps.vectorstore.contract.models.VectorstoreApiSnapshots(**data)[source]

Bases: AccountApiModel

A vectorstore’s snapshots.

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

snapshots: list[VectorstoreApiSnapshot]
class smarter.apps.vectorstore.contract.models.VectorstoreApiStatus(**data)[source]

Bases: AccountApiModel

A vectorstore’s status and statistics, checked now.

message: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

stats: dict[str, JsonValue]
status: Literal['pending', 'provisioning', 'ready', 'stopped', 'failed', 'deleting']
vector_count: int
vectorstore: str
smarter.apps.vectorstore.contract.models.VectorstoreApiStatusValue

The choices of VectorstoreMeta.status.

A test fails if the two differ.

alias of Literal[‘pending’, ‘provisioning’, ‘ready’, ‘stopped’, ‘failed’, ‘deleting’]

class smarter.apps.vectorstore.contract.models.VectorstoreApiVectorstore(**data)[source]

Bases: AccountApiModel

A vectorstore: a smarter.apps.vectorstore.models.VectorstoreMeta.

Its related rows are their names.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
api_key_secret: str | None
backend: Literal['qdrant', 'pinecone']
can_delete: bool
connection: str | None
created_at: datetime | None
deletion_protection: bool
deployed_at: datetime | None
description: str | None
dimension: int
document_count: int
embeddings_model: str
embeddings_provider: str | None
endpoint_url: str
classmethod from_model(vectorstore, user=None)[source]

The contract’s model of a vectorstore.

Parameters:
  • vectorstore (VectorstoreMeta) – The row, whose user_profile should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

VectorstoreApiVectorstore

hashed_id: str
hosting: Literal['self_hosted', 'managed']
id: int
index_name: str
is_active: bool
last_checked_at: datetime | None
last_maintenance_at: datetime | None
last_snapshot_at: datetime | None
manifest_url: str
metric: Literal['cosine', 'euclidean', 'dotproduct']
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
snapshot_count: int
spec: dict[str, JsonValue]
stats: dict[str, JsonValue]
status: Literal['pending', 'provisioning', 'ready', 'stopped', 'failed', 'deleting']
status_message: str
tags: list[str]
updated_at: datetime | None
user_profile: AccountApiUserProfile
vector_count: int
version: str | None

Pydantic models of the LLMHosts’ REST api responses (/api/v1/llmhosts/).

The REST api’s views build their responses from these models, and the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes their JSON Schemas.

LLMHostApiLLMHost is an LLMHost, as smarter.apps.llmhost.serializers.LLMHostSerializer returned it before the api was modeled, which clients already read. One value changed: its canDelete is computed for the requesting user. The other models replace the dicts that the views and the LLMHost service built by hand, with the same keys. Their date-times now end in Z, where they ended in +00:00: the same instant. A catalog’s model keeps its snake_case keys.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.llmhost.contract.models.LLMHOST_API_MODELS = (<class 'smarter.apps.llmhost.contract.models.LLMHostApiLLMHost'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiStatus'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiLogs'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiPlan'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiUndeployed'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiReport'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiDiscovery'>, <class 'smarter.apps.llmhost.contract.models.LLMHostApiDraftManifest'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

Their dependencies are included with them.

(
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiLLMHost'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiStatus'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiLogs'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiPlan'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiUndeployed'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiReport'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiDiscovery'>,
    <class 'smarter.apps.llmhost.contract.models.LLMHostApiDraftManifest'>,
)
class smarter.apps.llmhost.contract.models.LLMHostApiCatalogModel(**data)[source]

Bases: BaseModel

A model, as a catalog, e.g. Hugging Face, describes it.

Its keys are snake_case, e.g. parameter_count, as the api returned them before it was modeled.

architecture: str | None
catalog: str
context_window: int | None
description: str | None
downloads: int | None
files: list[str]
classmethod from_model_info(model)[source]

The contract’s model of a catalog’s model.

Parameters:

model (ModelInfo) – The model.

Returns:

The model.

Return type:

LLMHostApiCatalogModel

gated: bool
license: str | None
likes: int | None
manifest: dict[str, JsonValue] | None
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

parameter_count: int | None
quantization: str
repository: str
source: str
tags: list[str]
task: str
class smarter.apps.llmhost.contract.models.LLMHostApiDiscovery(**data)[source]

Bases: AccountApiModel

The models of a catalog that match a search, most popular first.

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

models: list[LLMHostApiCatalogModel]
class smarter.apps.llmhost.contract.models.LLMHostApiDraftManifest(**data)[source]

Bases: AccountApiModel

A draft LLMHost manifest for a model, to review and apply.

manifest: dict[str, JsonValue]
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

smarter.apps.llmhost.contract.models.LLMHostApiFormat

The choices of LLMHost.api_format.

A test fails if the two differ.

alias of Literal[‘openai_compatible’, ‘huggingface’, ‘ollama_native’, ‘custom’]

smarter.apps.llmhost.contract.models.LLMHostApiInferenceEngine

The choices of LLMHost.inference_engine.

A test fails if the two differ.

alias of Literal[‘vllm’, ‘tgi’, ‘sglang’, ‘llama_cpp’, ‘ollama’, ‘tei’, ‘custom’]

class smarter.apps.llmhost.contract.models.LLMHostApiLLMHost(**data)[source]

Bases: AccountApiModel

A self-hosted LLM: a smarter.apps.llmhost.models.LLMHost.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
api_format: Literal['openai_compatible', 'huggingface', 'ollama_native', 'custom']
api_key_secret: int | None
can_delete: bool
compute: int | None
context_window: int | None
cost_per_hour: str | None
created_at: datetime | None
deployed_at: datetime | None
description: str | None
embedding_dimensions: int | None
endpoint_url: str
classmethod from_model(llmhost, user=None)[source]

The contract’s model of an LLMHost.

Parameters:
  • llmhost (LLMHost) – The row, whose user_profile should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

LLMHostApiLLMHost

gpu_count: int
gpu_type: str
hashed_id: str
health_check_url: str
id: int
inference_engine: Literal['vllm', 'tgi', 'sglang', 'llama_cpp', 'ollama', 'tei', 'custom']
is_active: bool
last_health_check_at: datetime | None
last_health_ok: bool | None
license: str
manifest_url: str
model_architecture: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_repository: str
model_revision: str
model_source: Literal['huggingface', 'ollama', 's3', 'url', 'pvc']
model_task: Literal['text-generation', 'embedding']
name: str
parameter_count: int | None
public_url: str
quantization: Literal['none', 'fp32', 'fp16', 'bf16', 'fp8', 'mxfp4', 'int8', 'int4', 'gguf', 'awq', 'gptq']
ready_replicas: int
replicas: int
served_model_name: str
spec: dict[str, JsonValue]
status: Literal['provisioning', 'pending', 'downloading', 'deploying', 'active', 'degraded', 'inactive', 'error']
status_message: str
supports_function_calling: bool
supports_reasoning: bool
supports_streaming: bool
supports_vision: bool
tags: list[str]
updated_at: datetime | None
user_profile: AccountApiUserProfile
version: str | None
vram_required_gb: int | None
class smarter.apps.llmhost.contract.models.LLMHostApiLogs(**data)[source]

Bases: AccountApiModel

The inference server’s recent logs.

llmhost: str
logs: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

smarter.apps.llmhost.contract.models.LLMHostApiModelSource

The choices of LLMHost.model_source.

A test fails if the two differ.

alias of Literal[‘huggingface’, ‘ollama’, ‘s3’, ‘url’, ‘pvc’]

smarter.apps.llmhost.contract.models.LLMHostApiModelTask

The choices of LLMHost.model_task.

A test fails if the two differ.

alias of Literal[‘text-generation’, ‘embedding’]

class smarter.apps.llmhost.contract.models.LLMHostApiObservation(**data)[source]

Bases: AccountApiModel

What is known about an LLMHost, as of a status check.

checked_at: datetime | None
endpoint: str | None
classmethod from_observation(observation)[source]

The contract’s model of a status check.

Parameters:

observation (LLMHostObservation) – The observation.

Returns:

The model.

Return type:

LLMHostApiObservation

healthy: bool | None
message: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

pods: list[LLMHostApiPod]
public_url: str | None
ready_replicas: int
replicas: int
status: str
class smarter.apps.llmhost.contract.models.LLMHostApiPlan(**data)[source]

Bases: AccountApiModel

The Kubernetes resources that a deployment would apply, with secrets redacted.

llmhost: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

resources: list[dict[str, JsonValue]]
class smarter.apps.llmhost.contract.models.LLMHostApiPod(**data)[source]

Bases: AccountApiModel

A pod of an LLMHost: its name, phase, readiness, restarts, and why it is not ready, if it isn’t.

downloading: bool
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str | None
phase: str | None
ready: bool
reason: str | None
restarts: int
smarter.apps.llmhost.contract.models.LLMHostApiQuantization

The choices of LLMHost.quantization.

A test fails if the two differ.

alias of Literal[‘none’, ‘fp32’, ‘fp16’, ‘bf16’, ‘fp8’, ‘mxfp4’, ‘int8’, ‘int4’, ‘gguf’, ‘awq’, ‘gptq’]

class smarter.apps.llmhost.contract.models.LLMHostApiReport(**data)[source]

Bases: AccountApiModel

A summary of LLMHosts: their count by status and engine, the GPUs they use, and their cost.

by_engine: dict[str, int]
by_status: dict[str, int]
llmhosts: list[LLMHostApiReportHost]
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

totals: LLMHostApiReportTotals
class smarter.apps.llmhost.contract.models.LLMHostApiReportHost(**data)[source]

Bases: AccountApiModel

An LLMHost in a report: its status, model, GPUs and cost.

compute: str | None
cost_per_hour: str | None
deployed_at: datetime | None
endpoint: str | None
engine: str
estimated_cost: str | None
gpu_type: str | None
gpus: int
model: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
owner: str
public_url: str | None
ready_replicas: int
replicas: int
status: str
task: str
uptime_hours: float | None
class smarter.apps.llmhost.contract.models.LLMHostApiReportTotals(**data)[source]

Bases: AccountApiModel

The totals of a report of LLMHosts.

active: int
cost_per_hour: str
deployed: int
errors: int
estimated_cost: str
gpus: int
llmhosts: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class smarter.apps.llmhost.contract.models.LLMHostApiStatus(**data)[source]

Bases: LLMHostApiObservation

An LLMHost’s status, checked now, or after a deployment: the observation, with the LLMHost’s name.

llmhost: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

smarter.apps.llmhost.contract.models.LLMHostApiStatusValue

The choices of LLMHost.status.

A test fails if the two differ.

alias of Literal[‘provisioning’, ‘pending’, ‘downloading’, ‘deploying’, ‘active’, ‘degraded’, ‘inactive’, ‘error’]

class smarter.apps.llmhost.contract.models.LLMHostApiUndeployed(**data)[source]

Bases: AccountApiModel

An LLMHost whose Kubernetes resources were destroyed.

llmhost: str
message: str
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

status: Literal['provisioning', 'pending', 'downloading', 'deploying', 'active', 'degraded', 'inactive', 'error']
smarter.apps.llmhost.contract.models.money(value, decimal_places=4)[source]

A decimal amount as the api returns it: a string with the field’s decimal places, e.g. "0.1768".

Parameters:
  • value (Decimal | None) – The amount, or None.

  • decimal_places (int) – The number of decimal places.

Returns:

The amount, or None.

Return type:

str | None

Pydantic models of the Providers’ REST api responses (/api/v1/providers/).

The REST api’s views build their responses from these models, and the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes their JSON Schemas.

ProviderApiProvider and ProviderApiModel are the rows, as smarter.apps.provider.serializers returned them before the api was modeled, which clients already read: a Provider’s api key is its Secret’s name and status, never the key.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.provider.contract.models.PROVIDER_API_MODELS = (<class 'smarter.apps.provider.contract.models.ProviderApiProvider'>, <class 'smarter.apps.provider.contract.models.ProviderApiModel'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

(
    <class 'smarter.apps.provider.contract.models.ProviderApiProvider'>,
    <class 'smarter.apps.provider.contract.models.ProviderApiModel'>,
)
class smarter.apps.provider.contract.models.ProviderApiModel(**data)[source]

Bases: AccountApiModel

A model of an LLM provider: a smarter.apps.provider.models.ProviderModel, with its provider.

created_at: datetime | None
description: str | None
classmethod from_model(provider_model, user=None)[source]

The contract’s model of a provider’s model.

Parameters:
  • provider_model (ProviderModel) – The row, whose provider should be fetched with it.

  • user (object) – The requesting user, for the provider’s can_delete.

Returns:

The model.

Return type:

ProviderApiModel

id: int
is_active: bool
is_default: bool
is_deprecated: bool
is_flagged: bool
is_suspended: bool
max_completion_tokens: int
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
provider: ProviderApiProvider
supports_audio_generation: bool
supports_audio_input: bool
supports_code_interpreter: bool
supports_embedding: bool
supports_fine_tuning: bool
supports_image_generation: bool
supports_image_input: bool
supports_streaming: bool
supports_summarization: bool
supports_text_generation: bool
supports_text_input: bool
supports_tools: bool
supports_translation: bool
temperature: float
top_p: float
updated_at: datetime | None
class smarter.apps.provider.contract.models.ProviderApiProvider(**data)[source]

Bases: AccountApiModel

An LLM provider: a smarter.apps.provider.models.Provider.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
api_key: SecretApiSecretRef | None
base_url: str | None
can_delete: bool
connectivity_test_path: str | None
contact_email: str | None
contact_email_verified: datetime | None
created_at: datetime | None
default_model: str | None
description: str | None
docs_url: str | None
classmethod from_model(provider, user=None)[source]

The contract’s model of a Provider.

Parameters:
  • provider (Provider) – The row, whose user_profile, api_key and tos_accepted_by should be fetched with it.

  • user (object) – The requesting user, for can_delete. None may delete nothing.

Returns:

The model.

Return type:

ProviderApiProvider

id: int
is_active: bool
is_default: bool
is_deprecated: bool
is_flagged: bool
is_official_provider: bool
is_suspended: bool
is_verified: bool
manifest_url: str | None
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
ownership_requested: str | None
privacy_policy_url: str | None
ready: bool
rfc1034_compliant_name: str | None
status: Literal['unverified', 'verifying', 'failed', 'verified', 'suspended', 'deprecated']
support_email: str | None
support_email_verified: datetime | None
tags: list[str]
terms_of_service_url: str | None
tos_accepted: bool
tos_accepted_at: datetime | None
tos_accepted_by: AccountApiUser | None
updated_at: datetime | None
user_profile: AccountApiUserProfile
version: str | None
website_url: str | None
smarter.apps.provider.contract.models.ProviderApiStatus

The choices of Provider.status.

A test fails if the two differ.

alias of Literal[‘unverified’, ‘verifying’, ‘failed’, ‘verified’, ‘suspended’, ‘deprecated’]

Pydantic models of the Proxies’ REST api responses (/api/v1/proxy/).

The list of the Proxies that the caller may use is built from ProxyApiProxies, with the keys that the view built by hand before the api was modeled. A Proxy’s passthrough (/api/v1/proxy/<name>/<path>) forwards the request to the provider’s api, and returns its response, as it is, so its requests and responses are the provider’s, not Smarter’s, and are not modeled.

smarter.apps.proxy.contract.models.PROXY_API_MODELS = (<class 'smarter.apps.proxy.contract.models.ProxyApiProxies'>,)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

(<class 'smarter.apps.proxy.contract.models.ProxyApiProxies'>, )
class smarter.apps.proxy.contract.models.ProxyApiProxies(**data)[source]

Bases: AccountApiModel

The Proxies that the caller may use, by name.

model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

proxies: list[ProxyApiProxy]
class smarter.apps.proxy.contract.models.ProxyApiProxy(**data)[source]

Bases: AccountApiModel

A Proxy that the caller may use: its name, provider and urls.

allowed_paths: list[str]
description: str | None
classmethod from_model(proxy, request)[source]

The contract’s model of a Proxy.

Parameters:
  • proxy (Proxy) – The row, whose provider should be fetched with it.

  • request (HttpRequest) – The request, whose host makes the Proxy’s url absolute.

Returns:

The model.

Return type:

ProxyApiProxy

is_active: bool
model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
provider: str
upstream_url: str
url: str

Pydantic models of the prompt history’s REST api responses (/api/v1/prompts/history/).

The prompt history is the chat sessions (PromptHistoryApiSession) of the users whose resources the requesting user may manage, the tool calls that the LLMs made in them (PromptHistoryApiToolCall), and the plugins that they used (PromptHistoryApiPluginUsage).

The models are the outputs of the serializers of smarter.apps.prompt.api.v1.serializers, which the REST api returned before it was modeled, and which clients already read. Their keys are snake_case, unlike the rest of the REST api’s, for the same reason. A plugin is a smarter.apps.plugin.contract.models.PluginApiPluginMeta, in camelCase.

The models forbid extra fields: the api returns exactly what they declare.

smarter.apps.prompt.contract.history.PROMPT_HISTORY_API_MODELS = (<class 'smarter.apps.prompt.contract.history.PromptHistoryApiSession'>, <class 'smarter.apps.prompt.contract.history.PromptHistoryApiToolCall'>, <class 'smarter.apps.prompt.contract.history.PromptHistoryApiPluginUsage'>)

The models whose JSON Schemas the Smarter api’s OpenAPI document includes.

(
    <class 'smarter.apps.prompt.contract.history.PromptHistoryApiSession'>,
    <class 'smarter.apps.prompt.contract.history.PromptHistoryApiToolCall'>,
    <class 'smarter.apps.prompt.contract.history.PromptHistoryApiPluginUsage'>,
)
class smarter.apps.prompt.contract.history.PromptHistoryApiModel(**data)[source]

Bases: BaseModel

Base class of the prompt history’s models: the fields of a row, and a TimestampedModel’s.

created_at: datetime | None
id: int
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

updated_at: datetime | None
class smarter.apps.prompt.contract.history.PromptHistoryApiPluginUsage(**data)[source]

Bases: PromptHistoryApiModel

A use of a plugin in a chat session: a smarter.apps.prompt.models.PromptPluginUsage.

classmethod from_model(row, user=None)[source]

The contract’s model of a use of a plugin.

Parameters:
  • row (PromptPluginUsage) – The row, whose prompt and plugin should be fetched with it.

  • user (object) – The requesting user, for the plugin’s canDelete. None may delete nothing.

Returns:

The model.

Return type:

PromptHistoryApiPluginUsage

input_text: str | None
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

plugin: PluginApiPluginMeta
prompt: PromptHistoryApiSession
class smarter.apps.prompt.contract.history.PromptHistoryApiSession(**data)[source]

Bases: PromptHistoryApiModel

A chat session: one conversation with an LLMClient, a smarter.apps.prompt.models.Prompt.

annotations: list[dict[str, JsonValue]] | dict[str, JsonValue] | None
description: str | None
classmethod from_model(prompt)[source]

The contract’s model of a chat session.

Parameters:

prompt (Prompt) – The row.

Returns:

The model.

Return type:

PromptHistoryApiSession

ip_address: str
llmclient: int
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
session_key: str
url: str
user_agent: str
user_profile: int
version: str | None
class smarter.apps.prompt.contract.history.PromptHistoryApiToolCall(**data)[source]

Bases: PromptHistoryApiModel

A tool call that the LLM made in a chat session: a smarter.apps.prompt.models.PromptToolCall.

classmethod from_model(row)[source]

The contract’s model of a tool call.

Parameters:

row (PromptToolCall) – The row, whose prompt should be fetched with it.

Returns:

The model.

Return type:

PromptHistoryApiToolCall

function_args: str | None
function_name: str | None
model_config = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

plugin: int | None
prompt: PromptHistoryApiSession
request: JsonValue | None
response: JsonValue | None

A mixin of the REST api’s list views whose rows are built from api contract models.

The REST api’s responses are built from Pydantic models of their rows, e.g. smarter.apps.llmclient.contract.models, which the Smarter api’s OpenAPI document (smarter.apps.api.v1.contract.openapi) publishes. A list view that mixes in ContractListMixin sets contract_model, the model of one row, and its GET returns its queryset’s rows, each built by the model’s from_model().

class smarter.lib.drf.views.contract.ContractListMixin[source]

The list() of a DRF ListAPIView whose rows are built from contract_model.

A view whose rows need the request, e.g. for their canDelete, overrides item().

contract_model: type[BaseModel]

The contract model of one row.

It must have a from_model(row) classmethod.

item(row)[source]

The response’s item for a row: its contract model, dumped as JSON.

Parameters:

row (django.db.models.Model) – A row of the view’s queryset.

Returns:

The row’s JSON.

Return type:

TypeAliasType

list(request, *args, **kwargs)[source]

The rows of the view’s queryset, each built by item().

Parameters:

request (Request) – The request.

Returns:

The response, a JSON list.

Return type:

Response