Budget

Smarter API Budget Manifest Constants.

smarter.apps.account.manifest.models.budget.const.DEFAULT_WARNING_THRESHOLD = 80

Default percentage of a limit at which the budget_warning signal is sent.

Smarter API Manifest - Budget.metadata.

class smarter.apps.account.manifest.models.budget.metadata.SAMBudgetMetadata(*, name: str, description: str | None, version: str | None, tags: List[str] | None = <factory>, annotations: List[dict[str, str | int | float | bool | ~datetime.date | ~datetime.datetime | ~decimal.Decimal | ~uuid.UUID | bytes | list | dict]] | None=<factory>)[source]

Bases: AbstractSAMMetadataBase

Smarter API Budget Manifest - Metadata class.

class_identifier: ClassVar[str] = 'Budget.metadata'
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

Smarter API Manifest - Budget.spec.

A Budget is a set of spending limits. It is enforced on each of the resources in its spec.resources: when a resource’s spending reaches a limit, further charges to it are refused, e.g. a prompt is answered with the budget’s message instead of calling the LLM.

spec:
  config:
    unit: cost              # cost, in USD, or tokens
    period: month           # the billing period of periodicLimit: hour, day, week or month
    periodicLimit: 10.00    # the most that may be spent in a billing period. 0 means no limit.
    absoluteLimit: 100.00   # the most that may be spent in total. 0 means no limit.
    duration: 0             # billing periods after which the budget no longer applies. 0 means never.
    action: block           # block further charges, or warn only
    warningThreshold: 80    # the percentage of a limit at which a warning is sent. 0 means never.
    message: "You have used this month's AI allowance. It renews on the 1st."
  resources:
    - kind: User
      name: student1
    - kind: LLMClient
      name: stackademy_sql
      accountNumber: "3141-5926-5359"   # optional. Defaults to your own account.
    - recordLocator: provider-rc2x       # any resource, by its record locator

Spending is counted from when the budget is attached to a resource. Cost is priced with LLMPrices, in USD per million tokens, and LLMHostCompute nodes with their price per hour.

smarter.apps.account.manifest.models.budget.spec.RESOURCE_KINDS = ('Account', 'User', 'ApiConnection', 'SqlConnection', 'LLMClient', 'LLMHost', 'LLMHostCompute', 'MCPClient', 'Orchestrator', 'Provider', 'Proxy', 'Vectorsearch', 'ApiPlugin', 'SkillPlugin', 'SqlPlugin', 'StaticPlugin', 'WebsearchPlugin')

The kinds of resource that a budget can be attached to by kind and name.

(
    'Account',
    'User',
    'ApiConnection',
    'SqlConnection',
    'LLMClient',
    'LLMHost',
    'LLMHostCompute',
    'MCPClient',
    'Orchestrator',
    'Provider',
    'Proxy',
    'Vectorsearch',
    'ApiPlugin',
    'SkillPlugin',
    'SqlPlugin',
    'StaticPlugin',
    'WebsearchPlugin',
)
class smarter.apps.account.manifest.models.budget.spec.SAMBudgetSpec(*, config: ~smarter.apps.account.manifest.models.budget.spec.SAMBudgetSpecConfig, resources: ~typing.Annotated[list[~smarter.apps.account.manifest.models.budget.spec.SAMBudgetSpecResource], ~annotated_types.MaxLen(max_length=1000)] = <factory>)[source]

Bases: AbstractSAMSpecBase

Smarter API Budget Manifest Budget.spec.

class_identifier: ClassVar[str] = 'Budget.spec'
config: SAMBudgetSpecConfig
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

resources: list[SAMBudgetSpecResource]
class smarter.apps.account.manifest.models.budget.spec.SAMBudgetSpecConfig(*, unit: Literal['cost', 'tokens'] = 'cost', period: Literal['hour', 'day', 'week', 'month'] = 'month', periodicLimit: Annotated[Decimal, Ge(ge=0)] = Decimal('0'), absoluteLimit: Annotated[Decimal, Ge(ge=0)] = Decimal('0'), duration: Annotated[int, Ge(ge=0)] = 0, action: Literal['block', 'warn'] = 'block', warningThreshold: Annotated[int, Ge(ge=0), Le(le=100)] = 80, message: Annotated[str | None, MaxLen(max_length=1000)] = None)[source]

Bases: SmarterBasePydanticModel

Smarter API Budget Manifest Budget.spec.config: the budget’s limits.

absoluteLimit: Decimal
action: Literal['block', 'warn']
class_identifier: ClassVar[str] = 'Budget.spec.config'
duration: int
message: str | None
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

period: Literal['hour', 'day', 'week', 'month']
periodicLimit: Decimal
unit: Literal['cost', 'tokens']
warningThreshold: int
class smarter.apps.account.manifest.models.budget.spec.SAMBudgetSpecResource(*, kind: Literal['Account', 'User', 'ApiConnection', 'SqlConnection', 'LLMClient', 'LLMHost', 'LLMHostCompute', 'MCPClient', 'Orchestrator', 'Provider', 'Proxy', 'Vectorsearch', 'ApiPlugin', 'SkillPlugin', 'SqlPlugin', 'StaticPlugin', 'WebsearchPlugin'] | None = None, name: str | None = None, accountNumber: str | None = None, recordLocator: str | None = None)[source]

Bases: SmarterBasePydanticModel

Smarter API Budget Manifest Budget.spec.resources[]: a resource that the budget is enforced on.

Either kind and name, with an optional accountNumber, or a recordLocator.

accountNumber: str | None
class_identifier: ClassVar[str] = 'Budget.spec.resources'
kind: Literal['Account', 'User', 'ApiConnection', 'SqlConnection', 'LLMClient', 'LLMHost', 'LLMHostCompute', 'MCPClient', 'Orchestrator', 'Provider', 'Proxy', 'Vectorsearch', 'ApiPlugin', 'SkillPlugin', 'SqlPlugin', 'StaticPlugin', 'WebsearchPlugin'] | None
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

name: str | None
recordLocator: str | None
validate_identity()[source]

Either a kind and a name, or a recordLocator.

Return type:

SAMBudgetSpecResource

Smarter API Manifest - Budget.status.

class smarter.apps.account.manifest.models.budget.status.SAMBudgetStatus(*, recordLocator: str, created: datetime, modified: datetime, resources: list[SAMBudgetStatusResource] = <factory>)[source]

Bases: AbstractSAMStatusBase

Smarter API Budget Manifest - Status class.

Read only.

class_identifier: ClassVar[str] = 'Budget.status'
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

resources: list[SAMBudgetStatusResource]
class smarter.apps.account.manifest.models.budget.status.SAMBudgetStatusResource(*, recordLocator: str, isActive: bool, startDate: datetime, expiresAt: datetime | None = None, periodicActual: Decimal, periodicPercent: float | None = None, absoluteActual: Decimal, absolutePercent: float | None = None, isLocked: bool, lockReason: str | None = None)[source]

Bases: SmarterBasePydanticModel

The budget versus the actual spending of one of the budget’s resources.

Read only.

absoluteActual: Decimal
absolutePercent: float | None
class_identifier: ClassVar[str] = 'Budget.status.resources'
expiresAt: datetime | None
isActive: bool
isLocked: bool
lockReason: str | None
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

periodicActual: Decimal
periodicPercent: float | None
recordLocator: str
startDate: datetime

Smarter API Budget Manifest.

class smarter.apps.account.manifest.models.budget.model.SAMBudget(*, apiVersion: str, kind: str, metadata: SAMBudgetMetadata, spec: SAMBudgetSpec, status: SAMBudgetStatus | None = None)[source]

Bases: AbstractSAMBase

Smarter API Manifest - Budget.

class_identifier: ClassVar[str] = 'Budget'
metadata: SAMBudgetMetadata
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

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

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Return type:

None

Parameters:
  • self – The BaseModel instance.

  • context – The context.

spec: SAMBudgetSpec
status: SAMBudgetStatus | None