> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.itential.com/itential-gateway/5/using-decorators/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.itential.com/_mcp/server. # Validate and limit service inputs with decorators > Use decorators to limit and validate the inputs passed to a service at execution time. This topic describes how you can use decorators within Gateway to limit the inputs passed into a service that you execute using the `iagctl run service` command. A decorator defines the inputs a service expects: which parameters it accepts, what type they must be, and which are required. When a user runs a service through a workflow, the decorator validates that the correct inputs were provided before execution begins. A single decorator can be shared across multiple services that accept the same inputs, reducing duplication. Think of a decorator as a form definition that you attach to one or more services. ## Decorators in playbooks To best understand decorators, consider an Ansible Playbook service called `simple-ansible` that uses the following playbook. ```yaml --- - name: A Simple Hello World Example hosts: localhost gather_facts: no tasks: - name: Just Say Hello debug: msg: "Hello Mr. gateway this is from '{{ caller }}'" ``` Notice that the example playbook takes in a single variable called `caller`. When running the service, you can use the `--set` flag to pass a value for `caller` to the playbook. ```bash iagctl run ansible-playbook simple-ansible --set caller=documentation ``` ## JSON Schema in decorators Suppose that you want to limit the types of inputs that can pass to the playbook using the `--set` flag. Decorators allow you to limit the available parameters by using defined [JSON Schema](https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01) standards. Consider the example JSON Schema shown below that limits the available inputs to a key of `caller` with values of `documentation` or `learner`. ```json { "$id": "root", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "caller": { "type": "string", "enum": ["documentation", "learner"] } }, "required": [ "caller" ], "additionalProperties": false } ``` You can explore all available options within JSON Schema by referencing the [official spec](https://json-schema.org/draft/2020-12/json-schema-validation). ## Create a decorator resource First, save the JSON schema above as a file called `simple-deco.json`. Next, create a decorator resource called `simple-deco` within Gateway using the `json` schema file that you created in the previous step. ```bash iagctl create decorator simple-deco --schema @./simple-deco.json ``` ## Create a gateway service with decorators Once you create the decorator resource, create a service that uses it. The following example creates an Ansible Playbook service with the `simple-deco` decorator. ```bash iagctl create ansible-playbook ansible-with-deco --repository gateway-resources --working-dir ansibleplaybook --playbook hello-world.yml --decorator simple-deco ``` ```bash Output: Successfully created the Ansible playbook(s) Name: ansible-with-deco Repo Name: gateway-resources Working Dir: ansibleplaybook Playbook(s): hello-world.yml Decorator: simple-deco Description: Tags: Runtime Arguments: ``` Set the `--use` flag when using the service `run` command to get basic, high-level information about the decorator. ```bash iagctl run service ansible-playbook ansible-with-deco --use ``` ```bash Output: Decoration Usage: ----------------------------- The following keys can be set on the command line via the set command. +----------+--------+-------------+--------------------+ | NAME | TYPE | DESCRIPTION | EXAMPLE | +----------+--------+-------------+--------------------+ | caller** | string | | --set caller=value | +----------+--------+-------------+--------------------+ ** is Required ``` ### Successful decoration When you pass in a valid value for `caller` and run the Ansible playbook service, the playbook succeeds. ```bash iagctl run service ansible-playbook ansible-with-deco --set caller=documentation ``` ### Decoration error If you try to pass in a value for `caller` that is not `documentation` or `learner`, you receive an error. ```bash iagctl run service ansible-playbook ansible-with-deco --set caller=someWrongInput ``` ```bash Output: Error: failed to run ansible playbook 'ansible-with-deco': decoration errors have been encountered: should be one of ["documentation", "learner"] /caller ``` Additionally, if you try to set any value for a key that is not `caller`, an error returns. ```bash iagctl run service ansible-playbook ansible-with-deco --set caller=documentation --set someBadKey=value ``` ```bash Output: Error: failed to run ansible playbook 'ansible-with-deco': decoration errors have been encountered: extra input found someBadKey ``` ## Boolean properties in Python script services Decorators support `boolean` as a property type for Python script services. Boolean properties enable flag-style argument passing — instead of `--set verbose=true`, you pass `--set verbose` to set the flag, and omit it entirely to leave it unset. ### Define a boolean property To define a boolean property, set `"type": "boolean"` in the decorator schema: ```json { "$id": "root", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "verbose": { "type": "boolean" }, "host": { "type": "string" } }, "required": [ "host" ] } ``` ### Pass boolean arguments at runtime When a property is defined as `boolean` in the decorator, use bare `--set key` syntax to pass the flag. Omit the key entirely to leave it unset. ```bash # Sets --verbose flag; script receives: python main.py --verbose --host='10.0.0.1' iagctl run service python-script my-script --set verbose --set host=10.0.0.1 # Omits --verbose flag; script receives: python main.py --host='10.0.0.1' iagctl run service python-script my-script --set host=10.0.0.1 ``` How Gateway passes the flag to your script depends on whether the service has a decorator with the property typed as `boolean`: **With a decorator**, Gateway passes the flag as `--verbose`. Parse it in your script using `action='store_true'`: ```python import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument('--verbose', action='store_true', help="Enable verbose output") parser.add_argument('--host', required=True, help="Target host") args = parser.parse_args() if args.verbose: print(f"Connecting to {args.host} with verbose output enabled") else: print(f"Connecting to {args.host}") ``` **Without a decorator**, Gateway passes the flag as `--verbose=true`. Parse it as a string value: ```python import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument('--verbose', default='false', help="Enable verbose output") parser.add_argument('--host', required=True, help="Target host") args = parser.parse_args() if args.verbose.lower() == 'true': print(f"Connecting to {args.host} with verbose output enabled") else: print(f"Connecting to {args.host}") ``` ## Pass large values as files in Python script services Gateway 5.5.2+ Gateway passes decorator property values to a Python script as CLI arguments by default. Linux limits the total size of CLI arguments to roughly 128 KB, so a property with a large value—a full running-config, device session details, or query results—can exceed that limit and cause the script to fail. To avoid this, mark a decorator property as file-backed. Instead of passing the value inline as a CLI argument, Gateway writes it to a temporary file at execution time and passes your script an environment variable that contains the file's path. Gateway deletes the temporary file after the script finishes running, whether it succeeds or fails. ### Define a file-backed property File-backed properties are supported for Python script services only. To mark a property as file-backed, add two keywords to it in the decorator schema: * `x-itential-payload-type: "file"` tells Gateway to write the value to a temporary file instead of passing it inline. * `x-itential-payload-target` sets the name of the environment variable that Gateway uses to pass the file path to your script. The property keeps `"type": "string"` because the underlying content is still text, typically JSON. The `x-itential-payload-*` keywords only change how Gateway delivers the value to your script — they don't change the property's type or validation. ```json { "properties": { "pre_check_result_json": { "type": "string", "description": "Pre-check results, written to a temp file by Gateway rather than inlined", "x-itential-payload-type": "file", "x-itential-payload-target": "PRE_CHECK_RESULT_FILE" } } } ``` ### Read a file-backed value in your script At runtime, check for the environment variable you set in `x-itential-payload-target`. If it's present, open the file at that path to read the value. ```python import os path = os.environ.get("PRE_CHECK_RESULT_FILE") if path: with open(path, "r") as f: pre_check_result_json = f.read() ``` Because a file-backed property is still a normal decorator property, you can still pass it inline with `--set pre_check_result_json=` for local testing or smaller payloads. Gateway only redirects the value to a file when needed. Write your script to check for the CLI argument first, then fall back to the file path, so the same script works whether the value arrives inline or as a file: ```python def load_pre_check_result(arg_value): if arg_value: return arg_value # passed inline via --set pre_check_result_json path = os.environ.get("PRE_CHECK_RESULT_FILE") if not path: raise RuntimeError("pre_check_result_json was not provided as an argument or via PRE_CHECK_RESULT_FILE") with open(path, "r") as f: return f.read() ``` ## Learn more For more information on decorator operations, see the following iagctl CLI commands: * [iagctl create decorator](./iagctl/create-decorator) * [iagctl get decorators](./iagctl/get-decorators) * [iagctl describe decorator](./iagctl/describe-decorator) * [iagctl delete decorator](./iagctl/delete-decorator) > Use decorators to limit and validate the inputs passed to a service at execution time.