Function engines in SEMOSS provide a powerful way to encapsulate custom logic, external API calls, or even other SEMOSS operations (like Reactors) as well-defined, callable functions. These are particularly useful for extending SEMOSS's capabilities, integrating with third-party services, and for use in advanced AI workflows, such as function calling with Large Language Models (LLMs). Function engines typically extend prerna.engine.impl.function.AbstractFunctionEngine and implement prerna.engine.api.IFunctionEngine.
This interface defines the contract for all function engines:
execute(Map<String, Object> parameterValues): This is the primary method to invoke the function. It takes a map where keys are parameter names and values are the arguments for those parameters. The method returns anObjectwhich is the result of the function's execution.getFunctionName(): Returns the unique name of the function this engine represents.getFunctionDescription(): Returns a human-readable description of what the function does.getParameters(): Returns aList<FunctionParameter>objects. EachFunctionParameter(fromprerna.engine.impl.function.FunctionParameter) describes an expected input parameter, including its name, type (e.g., "string", "number", "boolean", "object", "array"), and description.getRequiredParameters(): Returns aList<String>of parameter names that are mandatory for the function execution.getFunctionDefintionJson(): Generates aorg.json.JSONObjectthat describes the function's signature (name, description, parameters, and required parameters) in a format often compatible with OpenAI's function/tool specification. This allows LLMs to understand how to call the function.buildOpenAIFunctionEngineToolMap(): Returns aMap<String, Object>specifically structured for OpenAI's "tool" (function calling) definition.buildBedrockToolSpec(): Returns aMap<String, Object>structured for AWS Bedrock's tool specification.
This abstract class provides a base for concrete function engine implementations.
- Metadata Loading: Its primary responsibility is to load the function's metadata (name, description, parameters, and required parameters) from the engine's SMSS properties file during the
open()method.FUNCTION_NAME: Property key for the function's name.FUNCTION_DESCRIPTION: Property key for the description.FUNCTION_PARAMETERS: Property key for a JSON string that defines the list ofFunctionParameterobjects (each havingname,type,description).FUNCTION_REQUIRED_PARAMETERS: Property key for a JSON string array listing the names of mandatory parameters.
- SMSS Configuration: It expects the function's signature and any other necessary configurations to be defined within the
.smssfile. - Secrets Integration: Like other abstract engines, it integrates with
SecretsFactoryto load sensitive configurations if needed.
To create a new FUNCTION engine:
- Implement
IFunctionEngine. - Extend
AbstractFunctionEngine: This is highly recommended to leverage the standardized loading of function metadata from SMSS properties. - Implement
execute(Map<String, Object> parameterValues): This is the core method where the actual logic of your function resides.- Retrieve and validate input parameters from the
parameterValuesmap based on the definitions loaded from SMSS. - Perform the function's action. This could involve:
- Calling an external REST API using an HTTP client.
- Executing a local script (e.g., Python, R) via
PyTranslatororRJavaTranslator. - Invoking other Java methods or SEMOSS Reactors.
- Performing complex calculations or data transformations.
- Return the result of the function as an
Object. This result will be wrapped inNounMetadataby the calling Pixel/Reactor.
- Retrieve and validate input parameters from the
- Define SMSS Properties: In the
.smssfile for your new function engine:- Specify
ENGINE_CLASSas your new engine's class name. - Define
FUNCTION_NAME,FUNCTION_DESCRIPTION. - Define
FUNCTION_PARAMETERSas a JSON string representing a list of objects, where each object has "name", "type" (e.g., "string", "number", "object", "array", "boolean"), and "description" keys. - Define
FUNCTION_REQUIRED_PARAMETERSas a JSON string array of required parameter names. - Add any other custom properties your engine needs for its operation (e.g., API endpoints, script paths, default values).
- Specify
- Define
FunctionTypeEnum: Add a new value toprerna.engine.api.FunctionTypeEnumfor your new function type if it represents a distinct category.
- Purpose: Enables the execution of specific functions within local Python scripts, making them callable as SEMOSS function engines.
- Implementation Highlights:
- The
execute()method typically usesprerna.ds.py.PyTranslatorto construct and send a Python command to the Python TCP server. This command would import the specified script and call the target function with the provided parameters. - It handles the translation of input parameters from the Java
Mapto a format suitable for the Python function and translates the Python function's return value back to a JavaObject.
- The
- SMSS Configuration:
PYTHON_SCRIPT_PATH: The file system path to the.pyscript.PYTHON_FUNCTION_NAME: The name of the function to call within the Python script.FUNCTION_NAME,FUNCTION_DESCRIPTION,FUNCTION_PARAMETERS,FUNCTION_REQUIRED_PARAMETERSdefining the function's signature as seen by SEMOSS.- May also include Python environment details if not globally managed.
- Purpose: Allows SEMOSS to make calls to external REST APIs and treat these API endpoints as callable functions.
- Implementation Highlights:
- The
execute()method would use an HTTP client library (e.g., Apache HttpClient, OkHttp) to construct an HTTP request (GET, POST, PUT, etc.). - It maps the input
parameterValuesto HTTP query parameters, path parameters, request headers, or the request body (often JSON) based on how the function engine is configured in its SMSS file. - Handles sending the request, receiving the response, and parsing the response body (e.g., from JSON into a Java Map or List).
- The
- SMSS Configuration:
API_ENDPOINT_URL: The base URL of the REST API.HTTP_METHOD: The HTTP method to use (e.g., "GET", "POST").- Authentication details: This could involve properties for API keys (e.g.,
API_KEY_HEADER_NAME,API_KEY_VALUE), OAuth2 token URLs and credentials, or other auth mechanisms. FUNCTION_NAME,FUNCTION_DESCRIPTION,FUNCTION_PARAMETERS(defining how these map to the API request),FUNCTION_REQUIRED_PARAMETERS.- Potentially, mappings for request/response content types.
- Purpose: An interesting meta-engine that can wrap an existing SEMOSS Reactor, exposing its functionality as if it were a standard function engine.
- Implementation Highlights:
- The
execute()method would internally instantiate and invoke the specified Reactor, passing the function parameters as nouns to the Reactor. - It translates the
NounMetadatareturned by the Reactor into a simpleObjectto fit theIFunctionEngine.execute()signature.
- The
- SMSS Configuration:
REACTOR_CLASS_NAME: The fully qualified class name of the SEMOSS Reactor to wrap.FUNCTION_NAME,FUNCTION_DESCRIPTION,FUNCTION_PARAMETERS(mapping to the Reactor's expected nouns),FUNCTION_REQUIRED_PARAMETERS.
Function engines are one source of executable integrations; native agent tools and project/MCP tools can also expose operations without being function engines. The harness resolves tool schemas and execution policy, while each resource operation enforces its access requirements. A skill can document an integration without automatically attaching or authorizing it.
Use IFunctionEngine and the function implementations for current signatures and configuration. See the harness tool flow and local function examples.