API LLMTool Plugin

An API Plugin allows the Smarter platform to interact with external API services. It defines how to connect, authenticate, and communicate with these services.

Technical References

A Plugin that uses a remote REST API server to retrieve its return data.

Note

This is a complex AI resource that exists within the following class hierarchy

  1. Smarter Secret: The authentication credential for the remote API connection.

  2. Smarter API Connection: The complete connection configuration to the remote REST API server (base url, authentication method, api key, timeout, proxy, etc.).

  3. Smarter API Plugin: The plugin that defines the API endpoint, HTTP method, headers, body and parameters to send to the remote REST API server.

  4. Smarter LLMClient: The prompting resource (LLMClient, Agent, Workflow unit, etcetera) that includes the API Plugin:

1.) Example Smarter Secret Manifest
apiVersion: smarter.sh/v1
kind: Secret
metadata:
  description: |
    An example secret manifest. This is a real credential used for authenticating to
    the Smarter test Remote API. This is a public-access test api
    used for development and testing purposes only.  Do not use this credential
    for production purposes. Password value is the same as the user.
    See the annotations below for connection details.
  name: smarter_test_api
  version: 1.1.0
  tags:
    - example
    - test
    - stackademy
    - api
  annotations:
    - smarter.sh/test-api/host: localhost
    - smarter.sh/test-api/port: "9357"
    - smarter.sh/test-api/user: smarter_test_api
    - smarter.sh/test-api/pwd: smarter_test_api
    - smarter.sh/test-api/access: anyone can access this test database
spec:
  config:
    value: smarter_test_api
2.) Example Smarter API Connection Manifest
apiVersion: smarter.sh/v1
kind: ApiConnection
metadata:
  description: Api connection Stackademy courses catalogue /api/v1/tests/stackademy/course-catalogue/
  name: smarter_test_api
  version: 0.1.0
  tags:
    - test
    - api
    - sample
  annotations:
    - smarter.sh/smarter-test-api/creator: QA Team
    - smarter.sh/smarter-test-api/purpose: unit testing
    - smarter.sh/smarter-test-api/release-date: 2024-06-15
    - smarter.sh/smarter-test-api/backward-compatibility: true
spec:
  connection:
    baseUrl: http://localhost:9357/api/v1/tests
    timeout: 30
    authMethod: none
3.) Example Stackademy API Plugin Manifest
apiVersion: smarter.sh/v1
kind: ApiPlugin
metadata:
  description: Online course catalogue inquiries for fictional Stackademy University that only offers computer science degrees programs.
  name: stackademy_api
  pluginClass: api
  version: 0.1.0
  tags:
    - api
    - courses
    - stackademy
  annotations:
    - smarter.sh/stackademy-api/display-name: Stackademy API
    - smarter.sh/stackademy-api/icon: https://example.com/stackademy-icon.png
    - smarter.sh/stackademy-api/supports-authentication: true
    - smarter.sh/stackademy-api/supports-rate-limiting: true
    - smarter.sh/stackademy-api/documentation-url: https://docs.stackademy.com/api
    - smarter.sh/stackademy-api/contact-email: no-reply@example.com
spec:
  apiData:
    body:
    - default: test
      description: The test to run.
      name: test
      required: true
      type: string
    - default: test2
      description: The second test to run.
      name: test2
      required: false
      type: string
    endpoint: /stackademy/course-catalogue/
    method: GET
    headers:
    - name: X-Debug-Request
      value: true
    - name: X-API-Key
      value: your_api_key_here
    - name: Content-Type
      value: application/json
    - name: Accept
      value: application/json
    - name: X-Request-ID
      value: 12345
    limit: 10
    parameters:
    - default: 500.00
      description: A ceiling on the maximum cost of the course.
      enum: null
      name: max_cost
      required: false
      type: string
    - default: Python
      description: A keyword to search for in the course description.
      enum: null
      name: description
      required: false
      type: string
    testValues:
    - name: max_cost
      value: 500.00
    - name: description
      value: Python
    urlParams: null
  connection: smarter_test_api
  prompt:
    maxTokens: 2048
    model: gpt-6-luna
    provider: openai
    systemRole: You are a helpful assistant for Smarter platform. You can provide
      information about the admin account of the Smarter platform.


    temperature: 1.0
  selector:
    directive: search_terms
    searchTerms:
    - admin
    - Smarter
    - account
4.) Example Stackademy LLMClient Manifest
apiVersion: smarter.sh/v1
kind: LLMClient
metadata:
  name: stackademy_api
  description: Stackademy University course catalogue inquiries using the Stackademy API plugin.
  version: 1.0.0
  tags:
    - stackademy
    - api
    - llmclient
  annotations:
    - smarter.sh/llm-client/stackademy-api/creator: QA Team
    - smarter.sh/llm-client/stackademy-api/purpose: llmclient for Stackademy course1 catalogue inquiries
    - smarter.sh/llm-client/stackademy-api/release-date: 2024-06-15
    - smarter.sh/llm-client/stackademy-api/backward-compatibility: true
spec:
  config:
    prompt:
      deployed: false
      provider: openai
      defaultModel: gpt-6-luna
      defaultSystemRole: >
        You are a helpful assistant. When given the opportunity to utilize
        function calling, you should always do so. This will allow you to
        provide the best possible responses to the user.
      defaultTemperature: 1.0
      defaultMaxTokens: 512
      appName: Stackademy
      appAssistant: Stanley
      appWelcomeMessage: Welcome to Stackademy! How can I help you today?
      appExamplePrompts:
        - "Do you offer any courses on AI?"
        - "My budget is $1,000. What courses can I take?"
        - "What is the capital of France?"
      appPlaceholder: "Ask me anything about Stackademy courses..."
      appInfoUrl: https://smarter.sh
      appFileAttachment: false
      subdomain: null
      customDomain: null
    styles:  # Stackademy's colors
      # appLogoUrl: https://cdn.smarter.sh/images/llmclients/stackademy/logo.png  # coming soon: upload, then uncomment
      # appBackgroundImageUrl: https://cdn.smarter.sh/images/llmclients/stackademy/background.png  # coming soon: upload, then uncomment
      # assistantAvatarUrl: https://cdn.smarter.sh/images/llmclients/stackademy/assistant.png  # coming soon: upload, then uncomment
      googleFont: Nunito
      fontSize: 15px
      borderRadius: 16px
      conversationHeader:
        backgroundColor: '#14213d'
        color: '#ffffff'
        infoColor: '#fca311'
      messageList:
        backgroundColor: rgba(255, 255, 255, 0.85)
        color: '#14213d'
      incomingMessage:
        backgroundColor: '#e5e5e5'
        color: '#14213d'
        linkColor: '#0b57d0'
      outgoingMessage:
        backgroundColor: '#fca311'
        color: '#14213d'
      messageInput:
        backgroundColor: '#ffffff'
        editorBackgroundColor: '#f1f1f1'
        placeholderColor: '#6c757d'
      buttons:
        color: '#fca311'
      typingIndicator:
        color: '#fca311'
  plugins:
    - stackademy_api
  functions: []
class smarter.apps.llmtool.plugin.api.ApiPlugin(*args, manifest=None, **kwargs)[source]

Bases: PluginBase

Implements a plugin that sends HTTP requests to a remote REST API server to retrieve data.

This class provides the logic for integrating REST API-based plugins into the Smarter platform. It supports manifest-driven configuration, parameter validation, and authenticated request execution. The plugin can be instantiated from either a manifest (Pydantic model) or an existing Django ORM instance.

Key Features:

  • Accepts plugin configuration via manifest or ORM model.

  • Validates and recasts parameter definitions to conform to OpenAI function calling schema.

  • Interpolates user-provided arguments into {placeholder} path segments of the endpoint, with URL encoding.

  • Sends remaining arguments as URL query string parameters (GET, DELETE) or as JSON body fields (POST, PUT, PATCH).

  • Executes requests using a remote API connection, which supplies the base url, authentication and timeout.

  • Handles errors related to configuration, connection, and request execution.

  • Provides example manifest generation for testing and documentation.

Usage:

  • Instantiate with a manifest or ORM model.

  • Use tool_call_fetch_plugin_response() to execute API requests with arguments from OpenAI tool calls.

  • Use plugin_data_django_model to convert manifest data to a Django ORM-compatible dictionary.

  • Use example_manifest() to generate a sample manifest for this plugin type.

Note

  • Static urlParams, headers and body from the manifest are sent with every request. Arguments from the LLM tool call take precedence over static values of the same name.

  • The maximum number of returned rows is limited to prevent excessive load on the remote API.

  • Only GET responses are cached. Failed requests are never cached.

  • Logging is controlled via feature switches and log level settings.

See also

SAMPluginType

alias of SAMApiPlugin

__init__(*args, manifest=None, **kwargs)[source]

Initialize a PluginBase instance.

Key features:

  • Lazy instantiation of class properties.

  • Supports multiple initialization methods including manifest, database model, and YAML/JSON.

  • Integrates with Django ORM for plugin metadata management.

  • Utilizes Pydantic models for manifest validation and serialization.

  • Provides hooks for plugin selection and prompt customization.

  • Ensures plugin readiness and validation before use.

  • Sends signals upon plugin creation or update.

This constructor supports several ways to create a plugin object:

  • Manifest-based initialization:

    Pass a Pydantic model instance via the manifest argument. This is the preferred method and is typically used when loading plugins from a manifest broker.

  • Database model initialization:

    Provide a Django model plugin ID via plugin_id or a PluginMeta instance via plugin_meta to load an existing plugin from the database.

  • YAML/JSON manifest initialization:

    Supply a YAML or JSON string (or dictionary) via the data argument to create a plugin from a manifest representation.

See ./data/sample-plugins/everlasting-gobstopper.yaml for an example manifest.

The constructor sets up internal state, initializes plugin properties, and triggers plugin creation or update logic as needed. It also sends signals when the plugin is ready.

Parameters:
  • user_profile (Optional[UserProfile]) – The user profile associated with the plugin.

  • selected (bool) – Whether the plugin is initially selected.

  • api_version (Optional[str]) – The API version for the plugin manifest.

  • manifest (SAMApiPlugin | None) – A Pydantic model representing the plugin manifest.

  • plugin_id (Optional[int]) – The Django ORM plugin ID.

  • plugin_meta (Optional[PluginMeta]) – The Django ORM PluginMeta instance.

  • data (Union[SmarterDictType, str, None]) – YAML/JSON manifest as a string or dictionary.

  • name (Optional[str]) – The name of the plugin.

  • kwargs – Additional keyword arguments.

property account: Account | None

Returns the account for the current user.

Handle lazy instantiation from user or user_profile.

Returns:

The account for the current user.

Return type:

Account or None

property account_number: str | None

A helper function to get the account number from the account.

Returns:

The account number for the current account.

Return type:

str or None

property am_ready: bool

Returns True if the AccountMixin is am_ready to be used.

This is a convenience property that checks if the account and user are initialized. AccountMixin is considered am_ready if: - self.user is an instance of User - self.user_profile is an instance of UserProfile - self.account is an instance of Account

Returns:

True if the AccountMixin is am_ready to be used.

Return type:

bool

property amnesty_urls: list[str]

Returns a list of URLs that are exempt from certain checks.

Returns:

List of URL path strings that are exempt.

Return type:

list[str]

property api_version: str

Return the api version of the plugin.

Returns:

The api version of the plugin.

Return type:

str

Raises:

SAMValidationError – If the api version is not valid.

See also

  • smarter.common.api.SmarterApiVersions

  • SMARTER_API_MANIFEST_COMPATIBILITY

authenticate(api_token)

Authenticate the user using the provided API token.

The api_token will have been generated by the SmarterTokenAuthentication class and passed by the caller in the Authorization header of the request.

Example

Authorization: Token <api_token>

Parameters:

api_token (bytes) – The API token to authenticate with.

Returns:

True if authentication was successful, False otherwise.

Return type:

bool

bool_environment_variable(var_name, default=False)

Retrieves a boolean value from an environment variable.

This method checks the specified environment variable and returns its value as a boolean. It recognizes common truthy values such as “true”, “1”, “yes”, and “on”. If the variable is not set or cannot be interpreted as a boolean, it returns the provided default value.

Parameters:
  • var_name (str) – The name of the environment variable to check.

  • default (bool) – The default boolean value to return if the environment variable is not set or invalid.

Returns:

The boolean value of the environment variable or the default.

Return type:

bool

cache_invalidations()

Invalidate cached properties related to the plugin.

This method is used to clear any cached data associated with the plugin instance, such as cached Django ORM model instances or serializers. It ensures that subsequent accesses to these properties will fetch fresh data from the database or re-instantiate serializers as needed.

The following properties are invalidated:

  • user_profile

  • plugin_meta

  • plugin_selector

  • plugin_prompt

  • plugin_data

Return type:

None

clone(new_name=None, user_profile=None)

Clone a plugin.

Parameters:
  • new_name (str | None) – The new name for the cloned plugin. If None, a name will be generated.

  • user_profile (UserProfile | None) – The owner of the cloned plugin. If None, the clone has the same owner as the plugin.

Returns:

The id of the cloned plugin if successful, False otherwise.

Return type:

Optional[int]

Raises:

SmarterPluginError – If the plugin is not ready.

create()[source]

Create the plugin in the database.

This method handles the creation of the API plugin in the database by invoking the superclass’s create method. It ensures that all necessary data is properly initialized and stored according to the plugin’s configuration.

Note

This method currently does not implement any additional logic beyond calling the superclass’s create method.

Returns:

None

Return type:

None

property custom_tool: dict[str, Any]

Return the plugin tool definition for OpenAI function calling.

See the OpenAI documentation: https://platform.openai.com/docs/assistants/tools/function-calling/quickstart

Example:

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_temperature",
            "description": "Get the current temperature for a specific location",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "The city and state, e.g., San Francisco, CA"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["Celsius", "Fahrenheit"],
                        "description": "The temperature unit to use. Infer this from the user's location."
                    }
                },
                "required": ["location", "unit"]
            }
        }
    }
]

See also

  • smarter.lib.openai.enum.OpenAIToolCall

  • smarter.lib.openai.enum.OpenAIToolTypes

customize_prompt(messages)

Modify the system prompt based on the plugin object.

Parameters:

messages (list[dict[str, Any]]) – The list of messages to customize.

Returns:

The customized list of messages.

Return type:

list[dict[str, Any]]

property data: dict[str, Any] | None

Return the plugin as a dictionary.

Returns:

The plugin as a dictionary if ready, None otherwise.

Return type:

Optional[dict]

data_to_dict(data)

Converts data to a dictionary, handling different types of input.

This method accepts either a dictionary or a string. If a string is provided, it will attempt to parse it as JSON first, and if that fails, as YAML. If parsing fails or the data type is unsupported, a SmarterValueError is raised.

Parameters:

data (dict[str, Any] | str) – The data to convert, either a dict or a JSON/YAML string.

Returns:

The data as a dictionary.

Return type:

dict[str, Any]

Raises:

SmarterValueError – If the data cannot be converted to a dictionary.

delete()

Delete a plugin.

Returns:

True if the plugin was deleted successfully, False otherwise.

Return type:

bool

Raises:

SmarterPluginError – If the plugin is not ready.

deserves_amnesty(slug)

Determines if a given URL deserves amnesty based on the amnesty URLs list.

This excuses certain endpoints (like health checks) from select middleware checks.

Parameters:

slug (str) – The URL path to check.

Returns:

True if the URL deserves amnesty, False otherwise.

Return type:

bool

dict_is_contained_in(dict1, dict2)

Checks if one dictionary is contained within another.

This method determines if all key-value pairs in dict1 are present in dict2.

Parameters:
  • dict1 (dict[str, Any]) – The dictionary to check for containment.

  • dict2 (dict[str, Any]) – The dictionary to check against for containment.

Returns:

True if dict1 is contained in dict2, False otherwise.

Return type:

bool

dict_is_subset(small, big)

Checks if one dictionary is a subset of another.

This method determines if all key-value pairs in the small dictionary are present in the big dictionary. It returns True if the small dictionary is a subset of the big dictionary, and False otherwise.

Parameters:
  • small (dict[str, Any]) – The dictionary to check as a subset.

  • big (dict[str, Any]) – The dictionary to check against as a superset.

Returns:

True if the small dictionary is a subset of the big dictionary, False otherwise.

Return type:

bool

classmethod example_manifest(kwargs=None)[source]

Use Pydantic models to generate an example manifest for ApiPlugin.

This class method creates a sample manifest dictionary for the ApiPlugin, illustrating the required structure and fields. The example manifest includes metadata, specification, and API query details, demonstrating how to configure the plugin for use within the Smarter platform.

Parameters:

kwargs (dict[str, Any] | None) – Optional dictionary of additional fields to include in the manifest.

Returns:

A dictionary representing the example manifest for the ApiPlugin.

Return type:

dict[str, Any]

See Also:

  • smarter.lib.manifest.enum.SAMKeys

  • smarter.lib.manifest.enum.SAMMetadataKeys

  • smarter.apps.llmtool.manifest.models.api_plugin.model.SAMApiPlugin

  • smarter.apps.llmtool.manifest.models.common.plugin.enum.SAMPluginCommonMetadataClassValues

  • smarter.apps.llmtool.manifest.models.common.plugin.enum.SAMPluginCommonSpecSelectorKeyDirectiveValues

  • smarter.apps.llmtool.manifest.models.common.plugin.enum.SAMPluginCommonSpecPromptKeys

formatted_class_name = '\x1b[1;31mApiPlugin\x1b[0m'
formatted_json(json_obj)

Formats a JSON object as a pretty-printed string with ANSI color codes for logging.

Parameters:

json_obj (dict[str, Any] | list) – The JSON object (dict or list) to format.

Returns:

A string representation of the JSON object with ANSI color codes.

Return type:

str

property formatted_pluginbase_class_name: str

Return the formatted class name for logging.

Returns:

The formatted class name.

Return type:

str

property formatted_state_not_ready: str

Returns the not-ready state formatted for logging.

Returns:

The formatted not-ready state as a string.

Return type:

str

property formatted_state_ready: str

Returns the readiness state formatted for logging.

Returns:

The formatted readiness state as a string.

Return type:

str

formatted_text(text, color_code='\\x1b[1;31m')

Formats text with ANSI color codes for logging.

Parameters:
  • text (str) – The text to format.

  • color_code (str) – The ANSI color code to apply.

Returns:

The formatted text with ANSI color codes.

Return type:

str

formatted_text_blue(text)

Formats text in bold dark blue for logging.

Parameters:

text (str) – The text to format.

Returns:

The formatted text in bold dark blue.

Return type:

str

formatted_text_green(text)

Formats text in bright green for logging.

Parameters:

text (str) – The text to format.

Returns:

The formatted text in bright green.

Return type:

str

formatted_text_red(text)

Formats text in dark red for logging.

Parameters:

text (str) – The text to format.

Returns:

The formatted text in dark red.

Return type:

str

property function_calling_identifier: str

Return the function calling plugin.

Returns:

The function calling plugin identifier.

Return type:

str

Raises:

SmarterPluginError – If the plugin is not ready.

property function_parameters: dict[str, Any] | None

Fetch the function parameters from the Django model.

Return the function parameters in a dictionary formatted according to the OpenAI function calling schema.

Returns:

The function parameters as a dictionary.

Return type:

Optional[SmarterDictType]

generate_fernet_encryption_key()

Generates a Fernet encryption key.

This method creates a new Fernet encryption key, which can be used for secure encryption and decryption of data. The generated key is returned as a URL-safe base64-encoded string.

Returns:

A new Fernet encryption key.

Return type:

str

get_readonly_csv_file(file_path)

Reads a CSV file and returns its contents as a list of dictionaries, one per row.

The file is opened read-only, so reading it never modifies it.

Parameters:

file_path (str) – The path to the CSV file to read.

Returns:

The rows of the CSV file, one dictionary per row, keyed by the column headers.

Return type:

list[dict]

get_readonly_yaml_file(file_path)

Reads a YAML file and returns its contents as a dictionary.

The file is opened read-only, so reading it never modifies it.

Parameters:

file_path (str) – The path to the YAML file to read.

Returns:

The contents of the YAML file, parsed into a dictionary.

Return type:

dict

property health_check_urls: list[str]

Returns a list of URL paths that are considered health check endpoints.

Returns:

List of health check URL path strings.

Return type:

list[str]

property id: int | None

Return the Django ORM PluginMeta id.

Returns:

The id of the plugin.

Return type:

Optional[int]

init(*args, **kwargs)

An optional method that can be called after initialization to perform any additional setup.

This is separate from __init__ to allow for more flexible initialization patterns.

Parameters:
  • args – Positional arguments passed to the init method.

  • kwargs – Keyword arguments passed to the init method.

Return type:

None

Returns:

None

property is_authenticated: bool

Returns True if the user is authenticated and is associated with an Account.

is_valid_yaml(data)

Validate a yaml string.

Parameters:

data (str) – The yaml string to validate.

Returns:

True if the yaml string is valid, False otherwise.

Return type:

bool

property kind: str

Returns the kind identifier for this plugin.

This property provides the canonical string used to distinguish the plugin type within the Smarter platform. The value is derived from the plugin manifest constant and is used for registration, serialization, and manifest validation.

The kind is typically referenced in plugin manifests and API payloads to ensure the correct plugin logic is invoked for API-based plugins.

Returns:

The string identifier representing the plugin kind.

Return type:

str

Example:
>>> plugin = ApiPlugin()
>>> plugin.kind
'api'
log_ready_status()

Logs the ready status of the view.

property manifest: SAMApiPlugin | None

Retrieve the manifest for this plugin as a Pydantic model.

This property returns the plugin’s manifest, which contains the configuration and specification for the API plugin in the form of a validated Pydantic model. If the manifest is not already set and the plugin is ready, it will be constructed from the current plugin data using the appropriate Pydantic model class.

The manifest is essential for validating plugin configuration, generating OpenAI-compatible schemas, and ensuring the plugin operates with the correct parameters and metadata.

Returns:

The manifest as a SAMApiPlugin Pydantic model instance, or None if unavailable.

Return type:

Optional[SAMApiPlugin]

Note

If the manifest is not present but the plugin is ready, this property will attempt to reconstruct the manifest from the plugin’s JSON representation.

Example:
>>> plugin = ApiPlugin()
>>> manifest = plugin.manifest
>>> print(manifest.spec.apiData.endpoint)
/stackademy/course-catalogue/
mask_string(string='', mask_char='*', mask_length=4, string_length=8)

Masks a string for secure logging.

This utility function masks all but the last unmasked_chars characters of the input string, replacing them with asterisks. It is useful for logging sensitive information like API keys or passwords.

Parameters:
  • string (str | None) – The string to be masked.

  • mask_char (str) – The character used for masking.

  • mask_length (int) – The number of characters to mask.

  • string_length (int) – The length of the string to consider for masking.

Returns:

The masked string.

Return type:

str

property metadata_class: str | None

Return the metadata class, PluginMeta.plugin_class.

Returns:

The metadata class name.

Return type:

Optional[str]

See also:

  • smarter.apps.llmtool.models.PluginMeta

property name: str | None

Return the name of the plugin.

Returns:

The name of the plugin.

Return type:

Optional[str]

Raises:

SmarterPluginError – If the PluginMeta is not of the expected type.

classmethod parameter_factory(name, data_type, description, enum=None, required=False, default=None)

Factory method to create a parameter dictionary for the SQL plugin.

Parameters:
  • name (str) – The name of the parameter.

  • data_type (str) – The data type of the parameter.

  • description (str) – The description of the parameter.

  • enum (list | None) – An optional list of enumerated values for the parameter.

  • required (bool | None) – Whether the parameter is required. Default is False.

  • default (Any) – The default value of the parameter. Default is None.

Returns:

A dictionary representing the parameter.

Return type:

dict[str, Any]

classmethod parameters_to_manifest(parameters)

Convert plugin parameters from the OpenAI function calling schema, as stored in the.

Django ORM, back to the list of parameters used in a plugin manifest.

This is the inverse of the recasting performed by plugin_data_django_model in the SqlPlugin and ApiPlugin subclasses.

Parameters:

parameters (dict[str, Any] | list[dict[str, Any]] | None) – The parameters in OpenAI function calling schema. A list is assumed to already be in manifest format.

Returns:

A list of manifest parameters, or None if there are no parameters.

Return type:

list[dict[str, Any]] | None

Example:

PluginBase.parameters_to_manifest(
    {
        "type": "object",
        "properties": {
            "unit": {"type": "string", "description": "The unit.", "enum": ["Celsius", "Fahrenheit"]}
        },
        "required": ["unit"],
        "additionalProperties": False,
    }
)
# [{"name": "unit", "type": "string", "description": "The unit.", "required": True, "default": None, "enum": ["Celsius", "Fahrenheit"]}]
property params: dict[str, Any] | None

Return the plugin parameters.

Returns:

The plugin parameters.

Return type:

Optional[SmarterDictType]

Example:

`python foo = MyPlugin() print(foo.params) {"key": "value"} `

property plugin_data: PluginDataApi | None

Return the plugin data as a Django ORM instance.

This property provides access to the plugin’s data in the form of a Django ORM model instance. It handles multiple scenarios for retrieving or constructing the plugin data:

  • If the plugin data has already been set, it is returned directly.

  • If both a manifest and plugin metadata are present, the plugin data is constructed from the manifest and metadata.

  • If only plugin metadata is present, the plugin data is retrieved from the database using the metadata.

  • If neither is available, the property returns None.

This logic ensures that the plugin data is always consistent with the current manifest and database state, supporting both creation and update workflows.

Returns:

The plugin data as a PluginDataApi Django ORM instance, or None if unavailable.

Return type:

Optional[PluginDataApi]

Raises:

PluginDataApi.DoesNotExist – If the plugin metadata is present but no corresponding database entry exists.

Note

This property does not create new database entries; it only retrieves or constructs plugin data based on existing manifest and metadata.

Example:
>>> plugin = ApiPlugin()
>>> data = plugin.plugin_data
>>> print(data.endpoint)
/stackademy/course-catalogue/
property plugin_data_class: Type[PluginDataApi]

Return the Django ORM model class used for plugin data.

This property provides the class reference for the Django model that stores API plugin data in the Smarter platform. It is useful for type checking, serialization, and for constructing new instances of plugin data objects.

The returned class can be used to create, query, or update plugin data records in the database. This is especially relevant when integrating with Django’s ORM or when performing migrations and schema validation.

Returns:

The Django ORM model class for API plugin data.

Return type:

Type[PluginDataApi]

Example:
>>> plugin = ApiPlugin()
>>> model_cls = plugin.plugin_data_class
>>> isinstance(model_cls(), PluginDataApi)
True
property plugin_data_django_model: dict[str, Any] | None

Transform the Pydantic model to the PluginDataApi Django ORM model and return the plugin data definition as a JSON object.

See the OpenAI documentation: https://platform.openai.com/docs/guides/function-calling?api-mode=prompt

The Pydantic ‘Parameters’ model is not directly compatible with OpenAI’s function calling schema, and our Django ORM model expects a dictionary format for the parameters. This method converts the Pydantic model to a dictionary suitable for creating a Django ORM model instance.

Raises:
  • SmarterApiPluginError – If the plugin manifest or API data is missing or invalid.

  • SmarterConfigurationError – If the parameters are not in the expected format.

Returns:

A dictionary representing the PluginDataApi Django ORM model.

Return type:

Optional[SmarterDictType]

Example of a correctly formatted dictionary:

{
    "properties": {
        "location": {
            "type": "string",
            "description": "The city and state, e.g., San Francisco, CA"
        },
        "unit": {
            "type": "string",
            "enum": ["Celsius", "Fahrenheit"],
            "description": "The temperature unit to use. Infer this from the user's location."
        }
    },
    "required": ["location", "unit"]
}

Example of a Pydantic model:

[
    {
        "name": "max_cost",
        "type": "float",
        "description": "the maximum cost that a student is willing to pay for a course.",
        "required": False,
        "enum": None,
        "default": None
    },
    {
        "name": "description",
        "type": "string",
        "description": "areas of specialization for courses in the catalogue.",
        "required": False,
        "enum": ["AI", "mobile", "web", "database", "network", "neural networks"],
        "default": None
    }
]
spec:
    selector:
        directive: search_terms
        searchTerms:
        - admin
        - Smarter platform
        - admin account
    prompt:
        provider: openai
        systemRole: >
        You are a helpful assistant for Smarter platform. You can provide information about the admin account of the Smarter platform.
        model: gpt-6-luna
        temperature: 0.0
        maxTokens: 256
    connection: test_api_connection
    apiData:
        endpoint: /v1/weather/{location}/
        method: GET
        headers:
        - name: Accept
          value: application/json
        parameters:
        - name: location
          type: string
          description: The city and state, e.g., San Francisco, CA
          required: true
        - name: unit
          type: string
          enum:
          - Celsius
          - Fahrenheit
          description: The temperature unit to use.
          required: false
          default: Celsius
        testValues:
        - name: location
          value: San Francisco, CA
        - name: unit
          value: Celsius
        limit: 10
property plugin_data_serializer: PluginApiSerializer | None

Return the serializer instance for plugin data.

This property provides a serializer object for the API plugin’s data, allowing conversion between Django ORM model instances and JSON-compatible representations. The serializer is used for validating, serializing, and deserializing plugin data, especially when preparing data for API responses or manifest generation.

If the serializer has not yet been instantiated, it will be created using the current plugin data. This ensures that the serializer always reflects the latest state of the plugin’s data.

Returns:

An instance of PluginApiSerializer for the plugin data, or None if plugin data is unavailable.

Return type:

Optional[PluginApiSerializer]

Example:
>>> plugin = ApiPlugin()
>>> serializer = plugin.plugin_data_serializer
>>> print(serializer.data)
{'endpoint': '/stackademy/course-catalogue/', 'method': 'GET', ...}
property plugin_data_serializer_class: Type[PluginApiSerializer]

Return the serializer class used for API plugin data.

This property provides the class reference for the serializer that is responsible for converting API plugin data between Django ORM model instances and JSON-compatible representations. The serializer class is essential for validation, serialization, and deserialization of plugin data, especially when integrating with APIs or generating manifests.

Use this property when you need to instantiate a new serializer for API plugin data, perform type checks, or access serializer-specific methods and attributes.

Returns:

The serializer class for API plugin data.

Return type:

Type[PluginApiSerializer]

Example:
>>> plugin = ApiPlugin()
>>> serializer_cls = plugin.plugin_data_serializer_class
>>> serializer = serializer_cls(plugin.plugin_data)
>>> isinstance(serializer, PluginApiSerializer)
True
property plugin_meta: PluginMeta | None

Return the plugin meta.

Returns:

The plugin meta.

Return type:

Optional[PluginMeta]

Note

This property will attempt to load the PluginMeta from the database if it has not already been set and if the UserProfile and manifest are available.

property plugin_meta_django_model: dict[str, Any] | None

Return a dict for loading the plugin meta Django ORM model.

Returns:

The plugin meta definition as a json object.

Return type:

Optional[SmarterDictType]

property plugin_meta_serializer: PluginMetaSerializer | None

Return the plugin meta serializer.

Returns:

The plugin meta serializer.

Return type:

Optional[PluginMetaSerializer]

property plugin_prompt: PluginPrompt | None

Return the plugin prompt.

Returns:

The plugin prompt.

Return type:

PluginPrompt

Raises:

SmarterPluginError – If the PluginPrompt does not exist.

property plugin_prompt_django_model: dict[str, Any] | None

Return the plugin prompt definition as a json object that can be used to load the Django ORM model.

Returns:

The plugin prompt definition as a dictionary.

Return type:

Optional[SmarterDictType]

property plugin_prompt_serializer: PluginPromptSerializer | None

Return the plugin prompt serializer.

Returns:

The plugin prompt serializer.

Return type:

Optional[PluginPromptSerializer]

property plugin_selector: PluginSelector | None

Return the plugin selector.

Returns:

The plugin selector.

Return type:

Optional[PluginSelector]

property plugin_selector_django_model: dict[str, Any] | None

Return the plugin selector definition as a json object.

Returns:

The plugin selector definition as a dictionary.

Return type:

Optional[SmarterDictType]

property plugin_selector_history: QuerySet | None

Return the plugin selector history serializer.

Returns:

The plugin selector history queryset.

Return type:

Optional[QuerySet]

property plugin_selector_serializer: PluginSelectorSerializer | None

Return the plugin selector serializer.

Returns:

The plugin selector serializer.

Return type:

Optional[PluginSelectorSerializer]

property ready: bool

Return whether the plugin is ready.

Returns:

True if the plugin is ready, False otherwise.

Return type:

bool

Raises:

SmarterPluginError – If the UserProfile is not set or if any of the plugin components are not of the expected type.

property ready_state: str

Returns a string representation of the am_ready state.

recursive_sort_dict(data)

Recursively sorts a dictionary by its keys.

This method takes a dictionary and returns a new dictionary with all keys sorted in ascending order. If any values are also dictionaries, they will be sorted recursively as well.

Parameters:

data (dict[str, Any]) – The dictionary to sort.

Returns:

A new dictionary with all keys sorted.

Return type:

dict[str, Any]

refresh()

Refresh the plugin.

Returns:

True if the plugin is ready after refresh, False otherwise.

Return type:

bool

reinitialize_plugin()

Reset all plugin-related properties to None.

This method is used to clear the internal state of the plugin instance, including all cached references to Django ORM models, serializers, and other plugin-specific objects. It is typically called during initialization or when reloading a plugin to ensure that no stale data remains.

The following attributes are reset:

  • _plugin_meta: The plugin metadata model instance.

  • _plugin_selector: The plugin selector model instance.

  • _plugin_prompt: The plugin prompt model instance.

  • _plugin_selector_history: The queryset for selector history.

  • _plugin_data: The plugin data model instance.

  • _plugin_prompt_serializer: The serializer for the plugin prompt.

  • _plugin_selector_serializer: The serializer for the plugin selector.

  • _plugin_meta_serializer: The serializer for the plugin metadata.

This ensures that subsequent operations on the plugin will re-fetch or re-create these objects as needed, avoiding issues with outdated or invalid references.

rfc1034_compliant_str(name)

Converts a string to an RFC 1034 compliant format.

This method takes a string and converts it to a format that complies with RFC 1034, which is commonly used for domain names. It replaces invalid characters with hyphens and ensures the resulting string is lowercase.

Parameters:

name (str) – The string to convert to RFC 1034 compliant format.

Returns:

The converted string in RFC 1034 compliant format.

Return type:

str

rfc1034_compliant_to_snake(name)

Converts an RFC 1034 compliant string to snake_case.

This method takes a string in RFC 1034 compliant format and converts it to snake_case. It replaces hyphens with underscores and ensures the resulting string is lowercase.

Parameters:

name (str) – The RFC 1034 compliant string to convert.

Returns:

The converted string in snake_case.

Return type:

str

save()

Save a plugin.

Returns:

True if the plugin was saved successfully, False otherwise.

Return type:

bool

Raises:

SmarterPluginError – If the plugin meta, selector, prompt, or data is not set or is not the correct instance.

selected(user, input_text=None, messages=None)

Determine whether the plugin should be selected for a given user and input context.

This method evaluates plugin selection logic based on the plugin’s selector directive, search terms, and optionally provided input text or message history. It supports both direct text matching and message-based matching, using the plugin’s configured search terms.

Selection is performed as follows:

  • If the plugin selector directive is set to ALWAYS, the plugin is automatically selected.

  • If input_text is provided, the method checks if any search term matches the input using the NLP utility does_refer_to. If a match is found, the plugin is selected and a signal is sent.

  • If messages are provided, the method iterates through user messages and checks for matches against the search terms. If a match is found, the plugin is selected and a signal is sent.

Signals:

  • plugin_selected is sent when the plugin is selected via either input text or messages.

Parameters:
  • user (User) – The user for whom selection is being evaluated.

  • input_text (str | None) – Optional input text to check for search term matches.

  • messages (list[dict[str, Any]] | None) – Optional list of message dictionaries to check for search term matches.

Returns:

True if the plugin is selected, False otherwise.

Return type:

bool

Note

This method requires the plugin to be ready. If the plugin is not ready, it will return False. The method also updates the internal _selected state when a match is found.

setup(*args, **kwargs)

This method is called by Django views during initialization.

It attempts to resolve the account and user information from the request object if it hasn’t already been set.

Parameters:
  • args – Positional arguments passed to the view.

  • kwargs – Keyword arguments passed to the view, may include ‘request’.

Returns:

The result of the superclass setup method.

Return type:

None

smarter_build_absolute_uri(request)

Attempts to get the absolute URI from a request object.

This utility function tries to retrieve the request URL from any valid child class of django.http.HttpRequest. It is especially useful in unit tests or scenarios where the request object may not implement build_absolute_uri().

Parameters:

request (HttpRequest) – The request object.

Returns:

The absolute request URL.

Return type:

str | None

Raises:

SmarterValueError – If the URI cannot be built from the request.

sorted_dict(data)

Returns a new dictionary with keys sorted.

Parameters:

data (dict[str, Any]) – The dictionary to sort.

Returns:

A new dictionary with sorted keys.

Return type:

dict[str, Any]

to_camel_case(data, convert_values=False)

Converts a snake_case string to camelCase.

This method takes a string in snake_case format and converts it to camelCase. It is useful for standardizing naming conventions across different formats.

Parameters:
  • data (TypeVar(ConvertibleCaseT, str, dict[str, Any], list[Any])) – The snake_case string to convert.

  • convert_values (bool) – Whether to convert the values of dictionaries and lists recursively.

Returns:

The converted string in camelCase.

Return type:

TypeVar(ConvertibleCaseT, str, dict[str, Any], list[Any])

to_json(version='v1')[source]

Serialize the ApiPlugin instance to a JSON-compatible dictionary suitable for Pydantic import.

This method transforms the plugin’s internal state, including its manifest and data, into a dictionary format that can be used to instantiate a Pydantic model. This is primarily used for rendering a plugin manifest for the Smarter API, enabling interoperability between Django ORM models and Pydantic schemas.

The output includes all relevant plugin fields, with the API data section populated from the plugin’s serializer. This ensures that the manifest is complete and conforms to the expected schema for API consumption or further validation.

Parameters:

version (str) – The API version to use for serialization. Only “v1” is supported.

Returns:

A dictionary representing the plugin in JSON format, or None if the plugin is not ready.

Return type:

dict[str, Any] | None

Raises:

SmarterPluginError – If the plugin is not ready, the data is not a valid JSON object, or an unsupported version is specified.

Note:

The returned dictionary is structured for compatibility with Pydantic models and the Smarter API manifest specification. The API data is injected from the plugin’s serializer to ensure accurate representation.

Example:
>>> plugin = ApiPlugin()
>>> manifest_json = plugin.to_json()
>>> print(manifest_json["spec"]["apiData"]["endpoint"])
/stackademy/course-catalogue/
to_snake_case(data, convert_values=False)

Converts a camelCase or PascalCase string to snake_case.

This method takes a string in camelCase or PascalCase format and converts it to snake_case. It is useful for standardizing naming conventions across different formats.

Parameters:
  • data (TypeVar(ConvertibleCaseT, str, dict[str, Any], list[Any])) – The camelCase or PascalCase string to convert.

  • convert_values (bool) – Whether to convert the values of dictionaries and lists recursively.

Returns:

The converted string in snake_case.

Return type:

TypeVar(ConvertibleCaseT, str, dict[str, Any], list[Any])

tool_call_fetch_plugin_response(function_args)[source]

Fetch information from a Plugin object in response to an OpenAI API tool call.

This method processes the arguments received from an OpenAI function call, builds an HTTP request from the plugin’s API data, sends it to the remote REST API server via the plugin’s smarter.apps.connection.models.ApiConnection, and returns the JSON response.

Arguments are mapped onto the request as follows:

  1. Arguments whose names match a {placeholder} in the endpoint are URL encoded and interpolated into the endpoint path, e.g. /v1/weather/{location}/.

  2. For GET and DELETE requests, all remaining arguments are appended to the static urlParams as URL query string parameters.

  3. For POST, PUT and PATCH requests, all remaining arguments are merged into the static JSON body, provided that the body is a JSON object. Otherwise they are sent as URL query string parameters.

Arguments with a null value are omitted, since these are optional parameters for which the LLM did not provide a value. Static headers from the manifest are sent with every request, and authentication headers are added by the connection.

See the OpenAI documentation: https://platform.openai.com/docs/assistants/tools/function-calling/quickstart

Example tool call payload:

"tool_calls": [
    {
        "id": "call_1Ucn2R5WmBh7TtoE197SsP3p",
        "function": {
            "arguments": "{"description":"Python","max_cost":"500.00"}",  # these are the function_args
            "name": "smarter_plugin_0000004468"
        },
        "type": "function"
    }
]

Resulting HTTP request, for the example manifest:

GET {base_url}/stackademy/course-catalogue/?max_cost=500.00&description=Python
Parameters:

function_args (dict[str, Any] | list) – Arguments for the function call, as a dict, list, or JSON string.

Return type:

dict[str, Any] | list | str | None

Returns:

The JSON response of the API request as a dict or list, or an empty string if the request failed or returned no results.

Raises:

SmarterApiPluginError – If plugin data or API connection is invalid, arguments are malformed, or a required endpoint placeholder is missing.

property unformatted_class_name: str

Returns the raw class name without formatting.

Returns:

The unformatted class name as a string.

Return type:

str

This is useful for logging or serialization where the plain class name is needed.

update()

Update a plugin.

Returns:

True if the plugin was updated successfully, False otherwise.

Return type:

bool

Raises:

SmarterPluginError – If the plugin manifest is not set or the plugin does not exist.

property user: AnonymousUser | User | None

Returns the user.

Handle lazy instantiation from user_profile or account.

Returns:

The user.

Return type:

User or None

property user_profile: UserProfile | None

Returns the user_profile for the current user.

Handle lazy instantiation from user or account.

Returns:

The user_profile for the current user.

Return type:

UserProfile or None

property yaml: str

Return the plugin as a yaml string.

Returns:

The plugin as a yaml string.

Return type:

str

Raises:

SmarterPluginError – If the plugin is not ready.

yaml_to_json(yaml_string)

Convert a yaml string to a dictionary.

Parameters:

yaml_string (str) – The yaml string to convert.

Returns:

The converted dictionary.

Return type:

dict[str, Any]

Raises:

SmarterPluginError – If the yaml string is not valid.

exception smarter.apps.llmtool.plugin.api.SmarterApiPluginError(message='')[source]

Bases: SmarterPluginError

Base class for all API plugin errors.

__init__(message='')
add_note(note, /)

Add a note to the exception

args
property get_formatted_err_message
with_traceback(tb, /)

Set self.__traceback__ to tb and return self.

smarter.apps.llmtool.plugin.api.should_log(level)[source]

Check if logging should be done based on the waffle switch.