Contract

The Smarter Chat api contract. See The Chat API Contract.

Pydantic models of the Smarter Chat api contract.

They describe the requests and responses of the configuration and prompt apis, and the prompt’s progress events.

These models are the contract’s single source of truth:

  • version 2 responses are built from them, by smarter.apps.prompt.contract.builders,

  • version 1 responses, which are built as before for older clients, are validated against them by the tests,

  • the JSON Schema in chat-contract.schema.json is generated from them (manage.py export_chat_contract_schema), and Smarter Chat generates its TypeScript types from that schema, and validates its test fixtures against it.

No field is a bare list[Any] or dict[str, Any]: lists are of named models, and a value that is stored as arbitrary JSON, e.g. a tool’s result, is a PromptChatApiJson, which is exactly JSON. The models of Django ORM rows (PromptChatApiOrmModel) and of the session’s history have exactly their fields. The LLMClient, the messages, the meta data and the completion allow extra fields, which the LLM providers and the Console use, and which Smarter Chat displays as is. Adding a field is backward compatible. Removing or renaming one that is declared here is not.

smarter.apps.prompt.contract.models.CONTRACT_MODELS: tuple[type[BaseModel], ...] = (<class 'smarter.apps.prompt.contract.models.PromptChatApiMessage'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiErrorBody'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiErrorResponse'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigRequest'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigResponse'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigResponseV1'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptRequest'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptResponse'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptResponseV1'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiCompletionV1'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiFailureV1'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressEvent'>, <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressResult'>)

The models whose JSON Schema is exported.

Their dependencies are exported with them.

(
    <class 'smarter.apps.prompt.contract.models.PromptChatApiMessage'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiErrorBody'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiErrorResponse'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigRequest'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigResponse'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiConfigResponseV1'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptRequest'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptResponse'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiPromptResponseV1'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiCompletionV1'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiFailureV1'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressEvent'>,
    <class 'smarter.apps.prompt.contract.models.PromptChatApiProgressResult'>,
)
smarter.apps.prompt.contract.models.LEGACY_KEY_RENAMES = (('llmclient', 'chatbot'), ('account_number', 'accountNumber'), ('prompt_history', 'chat_history'))

The key renames of version 1 of the configuration, for the versions of Smarter Chat that expect.

‘chatbot’ rather than ‘llmclient’. Each applies to every key that contains it, at every depth.

(
    ('llmclient', 'chatbot'),
    ('account_number', 'accountNumber'),
    ('prompt_history', 'chat_history'),
)
class smarter.apps.prompt.contract.models.PromptChatApiAudioPart(**data)[source]

Bases: PromptChatApiModel

A message’s audio part.

input_audio: PromptChatApiInputAudio
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

type: Literal['input_audio']
class smarter.apps.prompt.contract.models.PromptChatApiChatbotV1(**data)[source]

Bases: PromptChatApiLLMClientBase

The LLMClient, in version 1 of the configuration, whose keys are renamed: llmclient becomes chatbot.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

url_chatbot: str
class smarter.apps.prompt.contract.models.PromptChatApiChoice(**data)[source]

Bases: PromptChatApiModel

A choice of a chat completion.

finish_reason: str | None
index: int
message: PromptChatApiMessage | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiCompletion(**data)[source]

Bases: BaseModel

The LLM’s chat completion, in the format of the OpenAI api, with only these fields.

Smarter’s own additions, smarter and metadata, are not part of it: the messages, plugins and tools are in PromptChatApiPromptResult, and metadata, which describes the tool calls with their plugins’ owners, is returned only to the cli.

choices: list[PromptChatApiChoice]
created: int | None
id: str | None
model: str | None
model_config: ClassVar[ConfigDict] = {'extra': 'ignore'}

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

object: str | None
service_tier: str | None
system_fingerprint: str | None
usage: PromptChatApiUsage | None
class smarter.apps.prompt.contract.models.PromptChatApiCompletionV1(**data)[source]

Bases: PromptChatApiModel

The parsed body of a successful prompt, version 1: a chat completion, with Smarter’s additions.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

smarter: PromptChatApiSmarterCompletionV1
class smarter.apps.prompt.contract.models.PromptChatApiConfig(**data)[source]

Bases: PromptChatApiConfigBase

The configuration, version 2.

PromptConfigView.config() builds one, from which every response is derived: public() for a deployed LLMClient’s own host, and to_v1() for older clients.

contract: Literal[2]
functions: PromptChatApiFunctionList | None
history: PromptChatApiHistory
llmclient: PromptChatApiLLMClient
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

plugins: PromptChatApiPluginList
public()[source]

The public configuration.

A deployed LLMClient’s own host returns it to the pages that embed Smarter Chat.

The LLMClient is reduced to PUBLIC_LLMCLIENT_FIELDS, without e.g. its owner’s profile, the history to the session’s own messages, without the requests that Smarter sent to the LLM, the meta data to PUBLIC_META_DATA_FIELDS, and the plugins and functions to their counts.

Returns:

A new configuration.

Return type:

PromptChatApiConfig

to_v1()[source]

The same configuration, in version 1 of the contract.

Its keys are renamed at every depth: see LEGACY_KEY_RENAMES.

Returns:

The version 1 configuration.

Return type:

PromptChatApiConfigV1

class smarter.apps.prompt.contract.models.PromptChatApiConfigRequest(**data)[source]

Bases: PromptChatApiModel

The configuration api’s request body.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

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

Bases: PromptChatApiEnvelope

The configuration api’s response, version 2.

data: PromptChatApiConfig
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiConfigResponseV1(**data)[source]

Bases: PromptChatApiEnvelope

The configuration api’s response, version 1.

data: PromptChatApiConfigV1
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiConfigV1(**data)[source]

Bases: PromptChatApiConfigBase

The configuration, version 1.

chatbot: PromptChatApiChatbotV1
functions: PromptChatApiFunctionListV1 | None
history: PromptChatApiHistoryV1
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

plugins: PromptChatApiPluginListV1
smarter.apps.prompt.contract.models.PromptChatApiContentPart

A part of a message whose content is a list of parts, by its type.

alias of Annotated[PromptChatApiTextPart | PromptChatApiImagePart | PromptChatApiAudioPart | PromptChatApiFilePart | PromptChatApiRefusalPart, FieldInfo(annotation=NoneType, required=True, discriminator=’type’)]

class smarter.apps.prompt.contract.models.PromptChatApiEnvelope(**data)[source]

Bases: PromptChatApiModel

The fields that every journaled response adds beside data.

api: str
metadata: PromptChatApiJournalMetadata
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiErrorBody(**data)[source]

Bases: PromptChatApiModel

The error of a failed request: the same shape for every error of the configuration and prompt apis.

description: str
errorClass: str
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

status: int
class smarter.apps.prompt.contract.models.PromptChatApiErrorResponse(**data)[source]

Bases: PromptChatApiModel

The body of an error response of the configuration or prompt apis, in both versions of the contract.

api: str | None
error: PromptChatApiErrorBody
metadata: PromptChatApiJournalMetadata | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiFailureV1(**data)[source]

Bases: PromptChatApiModel

The parsed body of a failed prompt, version 1.

error: PromptChatApiProviderErrorV1
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

response: PromptChatApiCompletionV1
class smarter.apps.prompt.contract.models.PromptChatApiFilePart(**data)[source]

Bases: PromptChatApiModel

A message’s file part.

file: PromptChatApiFileRef
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

type: Literal['file']
class smarter.apps.prompt.contract.models.PromptChatApiFileRef(**data)[source]

Bases: PromptChatApiModel

The file of a file part: its base64 data, or the id of an uploaded file.

file_data: str | None
file_id: str | None
filename: str | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiFunctionCall(**data)[source]

Bases: PromptChatApiModel

The function that an assistant message calls.

arguments: str
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

name: str
class smarter.apps.prompt.contract.models.PromptChatApiFunctionList(**data)[source]

Bases: PromptChatApiModel

The LLMClient’s built-in functions.

The list itself is returned only in the complete configuration.

functions: list[PromptChatApiLLMClientFunction]
meta_data: PromptChatApiListMetaData
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiFunctionListV1(**data)[source]

Bases: PromptChatApiModel

The LLMClient’s built-in functions, in version 1.

functions: list[PromptChatApiLLMClientFunctionV1]
meta_data: PromptChatApiListMetaData
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

smarter.apps.prompt.contract.models.PromptChatApiFunctionName

the choices of LLMClientFunctions.name.

See LLMClientFunctions.CHOICES.

Type:

A built-in function’s name

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

class smarter.apps.prompt.contract.models.PromptChatApiHistory(**data)[source]

Bases: PromptChatApiHistoryBase

The chat session’s history, in version 2.

Only chat_history is public.

llmclient_request_history: list[PromptChatApiLLMClientRequest] | None
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

class smarter.apps.prompt.contract.models.PromptChatApiHistoryV1(**data)[source]

Bases: PromptChatApiHistoryBase

The chat session’s history, in version 1.

chatbot_request_history: list[PromptChatApiLLMClientRequestV1] | None
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

class smarter.apps.prompt.contract.models.PromptChatApiImagePart(**data)[source]

Bases: PromptChatApiModel

A message’s image part.

image_url: PromptChatApiImageUrl
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

type: Literal['image_url']
class smarter.apps.prompt.contract.models.PromptChatApiImageUrl(**data)[source]

Bases: PromptChatApiModel

The image of an image part: an http(s) or base64 data url.

detail: Literal['auto', 'low', 'high'] | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

url: str
class smarter.apps.prompt.contract.models.PromptChatApiInputAudio(**data)[source]

Bases: PromptChatApiModel

The audio of an audio part: base64 encoded.

data: str
format: Literal['wav', 'mp3']
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiJournalMetadata(**data)[source]

Bases: PromptChatApiModel

The journal’s record of a request, which every journaled response carries.

command: str | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

thing: str | None
type smarter.apps.prompt.contract.models.PromptChatApiJson = _AllowAnyJson]

A value that is stored, and returned, as arbitrary JSON: a string, number, boolean, null, or a.

list or object of them. It is used only where the value has no fixed shape, e.g. a tool’s result.

class smarter.apps.prompt.contract.models.PromptChatApiLLMClient(**data)[source]

Bases: PromptChatApiLLMClientBase

The LLMClient, in version 2 of the configuration.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

url_llmclient: str
class smarter.apps.prompt.contract.models.PromptChatApiLLMClientFunction(**data)[source]

Bases: PromptChatApiOrmModel

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

classmethod from_model(function)[source]

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

Parameters:

function (LLMClientFunctions) – The row.

Returns:

The model.

Return type:

PromptChatApiLLMClientFunction

llmclient: int
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

name: Literal['get_current_weather', 'date_calculator', 'calculator'] | None
class smarter.apps.prompt.contract.models.PromptChatApiLLMClientFunctionV1(**data)[source]

Bases: PromptChatApiOrmModel

A built-in function of the LLMClient, in version 1, whose llmclient is renamed chatbot.

chatbot: int
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

name: Literal['get_current_weather', 'date_calculator', 'calculator'] | None
class smarter.apps.prompt.contract.models.PromptChatApiLLMClientPlugin(**data)[source]

Bases: PromptChatApiOrmModel

A plugin of the LLMClient: a smarter.apps.llmclient.models.LLMClientPlugin.

classmethod from_model(plugin)[source]

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

Parameters:

plugin (LLMClientPlugin) – The row, whose plugin_meta and its tags should be prefetched.

Returns:

The model.

Return type:

PromptChatApiLLMClientPlugin

llmclient: int
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

plugin_meta: PromptChatApiPluginMeta
class smarter.apps.prompt.contract.models.PromptChatApiLLMClientPluginV1(**data)[source]

Bases: PromptChatApiOrmModel

A plugin of the LLMClient, in version 1, whose llmclient is renamed chatbot.

chatbot: int
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

plugin_meta: PromptChatApiPluginMeta
class smarter.apps.prompt.contract.models.PromptChatApiLLMClientRequest(**data)[source]

Bases: PromptChatApiOrmModel

A request to the LLMClient’s prompt api: a smarter.apps.llmclient.models.LLMClientRequests.

classmethod from_model(row)[source]

The contract’s model of a request to the LLMClient’s prompt api.

Parameters:

row (LLMClientRequests) – The row.

Returns:

The model.

Return type:

PromptChatApiLLMClientRequest

is_aggregation: bool | None
llmclient: int
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

request: PromptChatApiPromptRequest | None
session_key: str | None
class smarter.apps.prompt.contract.models.PromptChatApiLLMClientRequestV1(**data)[source]

Bases: PromptChatApiOrmModel

A request to the LLMClient’s prompt api, in version 1, whose llmclient is renamed chatbot.

chatbot: int
is_aggregation: bool | None
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

request: PromptChatApiPromptRequest | None
session_key: str | None
class smarter.apps.prompt.contract.models.PromptChatApiLambdaResponseV1(**data)[source]

Bases: PromptChatApiModel

A prompt’s result, version 1: an AWS Lambda style response, whose body is a JSON string.

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

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

statusCode: int
class smarter.apps.prompt.contract.models.PromptChatApiListMetaData(**data)[source]

Bases: PromptChatApiModel

The counts of a list of the LLMClient’s plugins or functions.

functions_returned: int | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

plugins_returned: int | None
total_functions: int | None
total_plugins: int | None
class smarter.apps.prompt.contract.models.PromptChatApiMessage(**data)[source]

Bases: PromptChatApiModel

A message, in the format of the OpenAI chat completion api.

Smarter adds two roles, which are only displayed and never sent to an LLM: smarter, a note about what the backend did, and smarter_error, a failed prompt’s error.

content: str | list[Annotated[PromptChatApiTextPart | PromptChatApiImagePart | PromptChatApiAudioPart | PromptChatApiFilePart | PromptChatApiRefusalPart, FieldInfo(annotation=NoneType, required=True, discriminator='type')]] | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

name: str | None
role: str
tool_call_id: str | None
tool_calls: list[PromptChatApiToolCall] | None
class smarter.apps.prompt.contract.models.PromptChatApiMetaData(**data)[source]

Bases: PromptChatApiModel

The LLMClient’s state.

is_deployed: bool | None
is_valid: bool | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

ready: bool | None
class smarter.apps.prompt.contract.models.PromptChatApiOrmModel(**data)[source]

Bases: BaseModel

Base class of the contract’s models of Django ORM rows.

Their fields are exactly the rows’ fields, so extra fields are forbidden. Each is built from its row by from_model().

created_at: datetime | None
id: int
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

updated_at: datetime | None
smarter.apps.prompt.contract.models.PromptChatApiPluginClass

the choices of PluginMeta.plugin_class.

See PluginMeta.PLUGIN_CLASSES.

Type:

A plugin’s class

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

class smarter.apps.prompt.contract.models.PromptChatApiPluginList(**data)[source]

Bases: PromptChatApiModel

The LLMClient’s plugins.

The list itself is returned only in the complete configuration.

meta_data: PromptChatApiListMetaData
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

plugins: list[PromptChatApiLLMClientPlugin]
class smarter.apps.prompt.contract.models.PromptChatApiPluginListV1(**data)[source]

Bases: PromptChatApiModel

The LLMClient’s plugins, in version 1.

meta_data: PromptChatApiListMetaData
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

plugins: list[PromptChatApiLLMClientPluginV1]
class smarter.apps.prompt.contract.models.PromptChatApiPluginMeta(**data)[source]

Bases: PromptChatApiOrmModel

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

Its owner is left out: the configuration never includes a user’s profile.

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

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

Parameters:

plugin_meta (PluginMeta) – The row, whose tags should be prefetched.

Returns:

The model.

Return type:

PromptChatApiPluginMeta

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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']
tags: list[str]
version: str | None
class smarter.apps.prompt.contract.models.PromptChatApiPluginSelection(**data)[source]

Bases: PromptChatApiOrmModel

A plugin selector’s activation: a smarter.apps.plugin.models.PluginSelectorHistory.

classmethod from_model(row)[source]

The contract’s model of a plugin selector’s activation.

Parameters:

row (PluginSelectorHistory) – The row.

Returns:

The model.

Return type:

PromptChatApiPluginSelection

messages: list[PromptChatApiMessage] | None
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

plugin_selector: int
search_term: str | None
session_key: str | None
class smarter.apps.prompt.contract.models.PromptChatApiProgressEvent(**data)[source]

Bases: PromptChatApiModel

The data of a progress event: a step of a running prompt.

message: str
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

type: Literal['llm_request', 'tool_requested', 'tool_responded', 'plugin_called', 'mcp_tool_called', 'mcp_tool_responded', 'mcp_tool_failed']
smarter.apps.prompt.contract.models.PromptChatApiProgressEventType

The type of a progress event.

See smarter.apps.prompt.progress.PromptProgressEvents.

alias of Literal[‘llm_request’, ‘tool_requested’, ‘tool_responded’, ‘plugin_called’, ‘mcp_tool_called’, ‘mcp_tool_responded’, ‘mcp_tool_failed’]

class smarter.apps.prompt.contract.models.PromptChatApiProgressResult(**data)[source]

Bases: PromptChatApiModel

The data of the final result event.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

response: PromptChatApiPromptResponse | PromptChatApiPromptResponseV1 | PromptChatApiErrorResponse
status: int
class smarter.apps.prompt.contract.models.PromptChatApiPromptPluginUsage(**data)[source]

Bases: PromptChatApiOrmModel

A plugin that the chat session used: a smarter.apps.prompt.models.PromptPluginUsage.

classmethod from_model(row)[source]

The contract’s model of a plugin that the chat session used.

Parameters:

row (PromptPluginUsage) – The row.

Returns:

The model.

Return type:

PromptChatApiPromptPluginUsage

input_text: str | None
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

plugin: int
prompt: int
class smarter.apps.prompt.contract.models.PromptChatApiPromptRequest(**data)[source]

Bases: PromptChatApiModel

The prompt api’s request body: the chat thread, with only the roles that LLMs accept.

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

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

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

Bases: PromptChatApiEnvelope

The prompt api’s response, version 2.

A failed prompt has error too, and its http status is the LLM provider’s. Its data.messages include a smarter_error message, which is also saved in the session’s history.

data: PromptChatApiPromptResult
error: PromptChatApiErrorBody | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiPromptResponseV1(**data)[source]

Bases: PromptChatApiEnvelope

The prompt api’s response, version 1.

data: PromptChatApiLambdaResponseV1
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

class smarter.apps.prompt.contract.models.PromptChatApiPromptResult(**data)[source]

Bases: PromptChatApiModel

The result of a prompt, version 2.

completion: PromptChatApiCompletion | None
contract: Literal[2]
messages: list[PromptChatApiMessage]
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

plugins: list[str]
status: int
tools: list[str]
class smarter.apps.prompt.contract.models.PromptChatApiPromptToolCall(**data)[source]

Bases: PromptChatApiOrmModel

A tool call of the chat session: a smarter.apps.prompt.models.PromptToolCall.

classmethod from_model(row)[source]

The contract’s model of a tool call of the chat session.

Parameters:

row (PromptToolCall) – The row.

Returns:

The model.

Return type:

PromptChatApiPromptToolCall

function_args: str | None
function_name: str | None
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

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

plugin: int | None
prompt: int
request: JsonValue | None
response: JsonValue | None
class smarter.apps.prompt.contract.models.PromptChatApiProviderErrorV1(**data)[source]

Bases: PromptChatApiModel

The LLM provider’s error, version 1.

message: str
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

status: int
class smarter.apps.prompt.contract.models.PromptChatApiRefusalPart(**data)[source]

Bases: PromptChatApiModel

An assistant message’s refusal part.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

refusal: str
type: Literal['refusal']
class smarter.apps.prompt.contract.models.PromptChatApiSmarterCompletionV1(**data)[source]

Bases: PromptChatApiModel

Smarter’s additions to a completion, version 1.

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

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

plugins: list[str]
tools: list[str]
class smarter.apps.prompt.contract.models.PromptChatApiTextPart(**data)[source]

Bases: PromptChatApiModel

A message’s text part, in the format of the OpenAI chat completion api.

model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

text: str
type: Literal['text']
class smarter.apps.prompt.contract.models.PromptChatApiTokenDetails(**data)[source]

Bases: PromptChatApiModel

The breakdown of a completion’s tokens.

audio_tokens: int | None
cached_tokens: int | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

reasoning_tokens: int | None
class smarter.apps.prompt.contract.models.PromptChatApiToolCall(**data)[source]

Bases: PromptChatApiModel

A tool call of an assistant message, in the format of the OpenAI chat completion api.

function: PromptChatApiFunctionCall
id: str
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

type: Literal['function']
class smarter.apps.prompt.contract.models.PromptChatApiUsage(**data)[source]

Bases: PromptChatApiModel

A chat completion’s token usage.

completion_tokens: int | None
completion_tokens_details: PromptChatApiTokenDetails | None
model_config: ClassVar[ConfigDict] = {'extra': 'allow'}

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

prompt_tokens: int | None
prompt_tokens_details: PromptChatApiTokenDetails | None
total_tokens: int | None
smarter.apps.prompt.contract.models.legacy_key_names(value)[source]

A value whose dict keys are renamed for version 1.

See LEGACY_KEY_RENAMES.

Parameters:

value (TypeAliasType) – A JSON value: a dict or a list is renamed, anything else is returned as is.

Returns:

The value, with its keys renamed at every depth.

Return type:

TypeAliasType

Builders of the Smarter Chat api contract’s responses.

The configuration view builds a PromptChatApiConfig, whose methods derive its responses. These functions serve both views, and turn a prompt’s result into what the client receives:

exception smarter.apps.prompt.contract.builders.PromptChatApiError(message)[source]

Bases: Exception

The base class of the errors that the configuration and prompt apis return.

__init__(message)[source]
exception smarter.apps.prompt.contract.builders.PromptChatApiErrorForbidden(message)[source]

Bases: PromptChatApiError

The LLMClient requires authentication, and the client didn’t provide it.

exception smarter.apps.prompt.contract.builders.PromptChatApiErrorInternal(message)[source]

Bases: PromptChatApiError

An unexpected error.

Its details are logged, never returned.

exception smarter.apps.prompt.contract.builders.PromptChatApiErrorLLMProvider(message)[source]

Bases: PromptChatApiError

The LLM provider rejected the prompt.

exception smarter.apps.prompt.contract.builders.PromptChatApiErrorNotFound(message)[source]

Bases: PromptChatApiError

The LLMClient doesn’t exist, or the client may not use it.

exception smarter.apps.prompt.contract.builders.PromptChatApiErrorNotReady(message)[source]

Bases: PromptChatApiError

The LLMClient exists, but can’t be initialized.

smarter.apps.prompt.contract.builders.chat_error_response(request, error, thing, command)[source]

The error response of the configuration and prompt apis.

It is a PromptChatApiErrorResponse, the same shape in both versions of the contract, without a stack trace.

Parameters:
Returns:

The error response.

Return type:

SmarterJournaledJsonErrorResponse

smarter.apps.prompt.contract.builders.prompt_result_v2(response)[source]

A prompt’s result, in version 2 of the contract.

Parameters:

response (Any) – A prompt’s Lambda style result, as the provider’s handler returns it.

Returns:

The response’s data (a PromptChatApiPromptResult), its error (a PromptChatApiErrorBody, or None if the prompt succeeded), and its http status.

Return type:

tuple[dict[str, Any], dict[str, Any] | None, int]

smarter.apps.prompt.contract.builders.requested_contract(request)[source]

The version of the contract that the client receives.

Parameters:

request (HttpRequest | None) – The configuration or prompt api’s request.

Returns:

CHAT_CONTRACT_V2, the default, unless the X-Smarter-Capabilities header lists chat-contract-v1 (and not chat-contract-v2), or the client is a version of Smarter Chat that lists no contract capability, which reads version 1 only.

Return type:

int

smarter.apps.prompt.contract.builders.without_diagnostics(response)[source]

A prompt’s result without the complete requests to and responses from the LLM.

The provider adds them to the completion’s smarter object, as DIAGNOSTIC_COMPLETION_KEYS, for the smarter cli. They include the system prompt and every tool result, so a browser never receives them. Nor does it receive the completion’s metadata (DIAGNOSTIC_COMPLETION_TOP_KEYS), whose tool calls describe each plugin with its owner’s profile.

Parameters:

response (Any) – A prompt’s Lambda style result, as the provider’s handler returns it.

Returns:

The result, with its body re-serialized without the diagnostic keys. Anything that isn’t a Lambda style result is returned as is.

Return type:

Any

Constants of the Smarter Chat api contract.

The contract is versioned. Version 2 is the default. Version 1, the original shape, is deprecated, and returned only to clients that need it:

  • a client that asks for it, with chat-contract-v1 in the X-Smarter-Capabilities request header, a comma-separated list of the capabilities that the client supports,

  • Smarter Chat (X-Smarter-Client: @smarter.sh/ui-chat) when it lists no contract capability, which is what its versions up to 0.7 do, so that the pages that installed them keep working,

  • the smarter cli’s prompt, whose output its clients parse.

A client may also ask for version 2 explicitly, with chat-contract-v2, as Smarter Chat does. The header is in CORS_ALLOW_HEADERS on every Smarter platform, so a new client can send it to an older platform, which ignores it.

smarter.apps.prompt.contract.const.CAPABILITIES_HEADER = 'HTTP_X_SMARTER_CAPABILITIES'

request.META key of the X-Smarter-Capabilities request header.

smarter.apps.prompt.contract.const.CHAT_CONTRACT_V1 = 1

the original contract, with legacy key names, and the prompt’s completion as a JSON.

string. typing_extensions.deprecated can’t mark a constant (PEP 702 covers classes and functions only), so every version 1 model, and to_v1(), is marked instead.

Type:

Deprecated

smarter.apps.prompt.contract.const.CHAT_CONTRACT_V1_CAPABILITY = 'chat-contract-v1'

The capability with which a client asks for the deprecated version 1 of the contract.

smarter.apps.prompt.contract.const.CHAT_CONTRACT_V2 = 2

plain key names, and the prompt’s messages and completion as JSON.

Type:

The current contract

smarter.apps.prompt.contract.const.CHAT_CONTRACT_V2_CAPABILITY = 'chat-contract-v2'

The capability with which a client asks for version 2 of the contract.

smarter.apps.prompt.contract.const.CLIENT_HEADER = 'HTTP_X_SMARTER_CLIENT'

request.META key of the X-Smarter-Client request header.

smarter.apps.prompt.contract.const.DEFAULT_CHAT_CONTRACT = 2

The version of the contract that a client receives unless it needs version 1.

smarter.apps.prompt.contract.const.DIAGNOSTIC_COMPLETION_KEYS = ('first_iteration', 'second_iteration')

The keys of a completion’s smarter object that hold the complete LLM requests and responses.

They are returned only to the smarter cli, never to a browser.

('first_iteration', 'second_iteration')
smarter.apps.prompt.contract.const.DIAGNOSTIC_COMPLETION_TOP_KEYS = ('metadata',)

metadata describes the.

prompt’s tool calls with each plugin’s PluginMeta, including its owner’s profile.

('metadata', )
Type:

The keys of a completion that are returned only to the smarter cli

smarter.apps.prompt.contract.const.LEGACY_CHAT_CLIENT = '@smarter.sh/ui-chat'

The X-Smarter-Client of Smarter Chat.

Its versions that list no contract capability, up to 0.7, read version 1 only.

smarter.apps.prompt.contract.const.PUBLIC_LLMCLIENT_FIELDS = ('id', 'name', 'description', 'version', 'deployed', 'provider', 'default_model', 'default_system_role', 'app_name', 'app_assistant', 'app_welcome_message', 'app_example_prompts', 'app_placeholder', 'app_info_url', 'app_background_image_url', 'app_logo_url', 'app_file_attachment', 'url_llmclient')

The LLMClient fields of the public configuration.

The public configuration is returned by a deployed LLMClient’s own host, which pages that embed Smarter Chat call. Workbench and platform api urls, and the cli, receive every field.

(
    'id',
    'name',
    'description',
    'version',
    'deployed',
    'provider',
    'default_model',
    'default_system_role',
    'app_name',
    'app_assistant',
    'app_welcome_message',
    'app_example_prompts',
    'app_placeholder',
    'app_info_url',
    'app_background_image_url',
    'app_logo_url',
    'app_file_attachment',
    'url_llmclient',
)
smarter.apps.prompt.contract.const.PUBLIC_META_DATA_FIELDS = ('ready', 'is_valid', 'is_deployed', 'is_custom_domain', 'is_authentication_required')

The meta_data fields of the public configuration.

(
    'ready',
    'is_valid',
    'is_deployed',
    'is_custom_domain',
    'is_authentication_required',
)
smarter.apps.prompt.contract.const.SCHEMA_PATH = '/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/prompt/contract/chat-contract.schema.json'

The JSON Schema of the contract, generated from smarter.apps.prompt.contract.models.

The JSON Schema of the Smarter Chat api contract, generated from its Pydantic models.

manage.py export_chat_contract_schema writes it to chat-contract.schema.json, beside this module, and a test fails if the committed file is out of date. Smarter Chat keeps a copy of it, from which it generates its TypeScript types, and against which it validates its test fixtures.

smarter.apps.prompt.contract.schema.chat_contract_schema()[source]

The contract’s JSON Schema (draft 2020-12): one definition, in $defs, per model.

Returns:

The schema.

Return type:

dict[str, Any]

smarter.apps.prompt.contract.schema.chat_contract_schema_json()[source]

The contract’s JSON Schema, as the text of chat-contract.schema.json.

Returns:

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

Return type:

str

smarter.apps.prompt.contract.schema.write_chat_contract_schema(path='/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/prompt/contract/chat-contract.schema.json')[source]

Write the contract’s JSON Schema.

Parameters:

path (str) – The file to write. Defaults to chat-contract.schema.json, beside this module.

Returns:

The path that was written.

Return type:

str