API 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 API database server (host, port, secret, ssh key, username, etc.).

  3. Smarter API Plugin: The plugin that defines the API query and it’s parameters to run against the remote API database 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 Remote SQL test database. This is a public-access test database
    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_user
  version: 1.1.0
  tags:
    - example
    - test
    - stackademy
  annotations:
    - smarter.sh/test-db/host: sql.lawrencemcdaniel.com
    - smarter.sh/test-db/port: "3306"
    - smarter.sh/test-db/db: smarter_test_db
    - smarter.sh/test-db/user: smarter_test_user
    - smarter.sh/test-db/pwd: smarter_test_user
    - smarter.sh/test-db/access: anyone can access this test database
spec:
  config:
    description: smarter_test_user password. Password value is the same as the user.
    value: smarter_test_user
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
    headers: {}
    method: GET
    parameters: {}
    timeout: 30
    useSsl: false
    authenticationMethod: none
    maxOverflow: 10
    poolSize: 5
    port: 8000
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-4o-mini
    provider: openai
    systemRole: You are a helpful assistant for Smarter platform. You can provide
      information about the admin account of the Smarter platform.


    temperature: 0.5
  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
    - llm_client
  annotations:
    - smarter.sh/llm-client/stackademy-api/creator: QA Team
    - smarter.sh/llm-client/stackademy-api/purpose: llm_client 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:
    deployed: false
    provider: openai
    defaultModel: gpt-4o-mini
    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: 0.5
    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
    appBackgroundImageUrl: https://smarter.sh/assets/img/bg.jpg
    appLogoUrl: https://smarter.sh/assets/img/logo.png
    appFileAttachment: false
    subdomain: null
    customDomain: null
  plugins:
    - stackademy_api
  functions: []
class smarter.apps.plugin.plugin.api.ApiPlugin(*args, manifest=None, **kwargs)[source]

Bases: PluginBase

Implements a plugin that executes API queries on a remote API database server to retrieve data.

This class provides mechanisms to:

  • Retrieve and serialize plugin data using Django ORM and Pydantic models.

  • Validate and recast API parameters to conform to OpenAI’s function calling schema.

  • Integrate with Smarter’s plugin manifest and metadata system.

  • Handle plugin instantiation from both manifest and database sources.

  • Manage connections to external APIs using account-specific credentials.

  • Provide example manifest generation for API plugins.

  • Enforce configuration and data integrity through custom error handling.

The plugin expects a manifest describing the API endpoint, parameters, headers, and other metadata. It supports lazy loading and validation of plugin data, and ensures compatibility with Smarter’s plugin infrastructure.

Subclasses must implement the tool_call_fetch_plugin_response and apply methods to define custom API interaction logic.

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 (Optional[SAMApiPlugin]) – 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[dict[str, Any], 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

apply(function_args)[source]

Apply the plugin to the function arguments.

Parameters:

function_args (dict[str, Any]) – The function arguments to pass to the plugin.

Returns:

The response from the plugin.

Return type:

Optional[str]

Raises:
  • SmarterConfigurationError – If the plugin is not ready.

  • NotImplementedError – If the method is not implemented in a subclass.

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)

Clone a plugin.

Parameters:

new_name (Optional[str]) – The new name for the cloned plugin. If None, a name will be generated.

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]) – The list of messages to customize.

Returns:

The customized list of messages.

Return type:

list[dict]

property data: dict | 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 (Union[dict, str]) – The data to convert, either a dict or a JSON/YAML string.

Returns:

The data as a dictionary.

Return type:

dict

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) – The dictionary to check for containment.

  • dict2 (dict) – 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) – The dictionary to check as a subset.

  • big (dict) – 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 (Optional[dict]) – Optional dictionary of additional fields to include in the manifest.

Returns:

A dictionary representing the example manifest for the ApiPlugin.

Return type:

dict

See Also:

  • smarter.lib.manifest.enum.SAMKeys

  • smarter.lib.manifest.enum.SAMMetadataKeys

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

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

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

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

property formatted_class_name: str

Returns the class name formatted for logging.

Returns:

The formatted class name as a string.

Return type:

str

formatted_json(json_obj)

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

Parameters:

json_obj (Union[dict, 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[dict[str, Any]]

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)

Retrieves a read-only file object for a CSV file.

This method opens the specified CSV file in read-only mode and returns a file object that can be used to read its contents. It ensures that the file is not modified during the reading process.

Parameters:

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

Returns:

A read-only file object for the specified CSV file.

Return type:

file

get_readonly_yaml_file(file_path)

Retrieves a read-only file object for a YAML file.

This method opens the specified YAML file in read-only mode and returns a file object that can be used to read its contents. It ensures that the file is not modified during the reading process.

Parameters:

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

Returns:

A read-only file object for the specified YAML file.

Return type:

file

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.api_query)
SELECT * FROM auth_user WHERE username = '{username}';
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 (Optional[str]) – 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.plugin.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 (Optional[list]) – An optional list of enumerated values for the parameter.

  • required (Optional[bool]) – Whether the parameter is required. Default is False.

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

Returns:

A dictionary representing the parameter.

Return type:

dict[str, Any]

property params: dict[str, Any] | None

Return the plugin parameters.

Returns:

The plugin parameters.

Return type:

Optional[dict[str, Any]]

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.api_query)
SELECT * FROM auth_user WHERE username = '{username}';
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[dict[str, Any]]

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-4o-mini
        temperature: 0.0
        maxTokens: 256
    connection: test_api_connection
    apiData:
        apiQuery: >
        SELECT * FROM auth_user WHERE username = '{username}';
        parameters:
        - name: username
            type: string
            description: The username to query.
            required: true
            default: admin
        - name: unit
            type: string
            enum:
            - Celsius
            - Fahrenheit
            description: The temperature unit to use.
            required: false
            default: Celsius
        testValues:
        - name: username
            value: admin
        - 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)
{'api_query': "SELECT * FROM auth_user WHERE username = '{username}';", ...}
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[dict[str, Any]]

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[dict[str, Any]]

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[dict[str, Any]]

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) – The dictionary to sort.

Returns:

A new dictionary with all keys sorted.

Return type:

dict

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 (Optional[str]) – Optional input text to check for search term matches.

  • messages (Optional[list[dict]]) – 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:

Optional[str]

Raises:

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

sorted_dict(data)

Returns a new dictionary with keys sorted.

Parameters:

data (dict) – The dictionary to sort.

Returns:

A new dictionary with sorted keys.

Return type:

dict

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 (Union[str, dict[str, object], list[object], object]) – 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:

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:

Optional[dict[str, Any]]

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"]["api_query"])
SELECT * FROM auth_user WHERE username = '{username}';
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 (Union[str, dict[str, object], list[object], object]) – 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:

Any

tool_call_fetch_plugin_response(function_args)[source]

Fetch information from a Plugin object.

Parameters:

function_args (Union[dict[str, Any], list]) – The function arguments to pass to the plugin.

Returns:

The response from the plugin.

Return type:

Union[dict, list, str, None]

Raises:

NotImplementedError – If the method is not implemented in a subclass.

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

Raises:

SmarterPluginError – If the yaml string is not valid.

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

Bases: SmarterPluginError

Base class for all API plugin errors.

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

Exception.add_note(note) – add a note to the exception

args
property get_formatted_err_message
with_traceback(object, /)

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

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

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