Skip to content

Creating a custom scanner

INFERENCE DEFEND

This article is meant for Inference Defend users.

ROLES AND PERMISSIONS

To complete the tasks described in this section, make sure you have the required permissions.

In addition to the scanners provided with CalypsoAI, you may want to create your own custom scanners with specific configurations depending on your particular requirements.

You can create three types of custom scanners:

Create a GenAI scanner

A GenAI scanner uses generative artificial intelligence to scan and flag text based on an input you can configure.

In this scenario, we are going to set our input as Political figures. The scanner will scan and flag any text that contains a political figure.

To create a GenAI scanner:

  1. Edit the following sample.

    python
    from calypsoai import CalypsoAI
    from calypsoai.datatypes import GenAIScannerConfig, ScanContext, ScannerDirection,
    ScannerVersionInputModel
    
    # Define the URL and token for CalypsoAI
    CALYPSOAI_URL = "https://www.us1.calypsoai.app"
    CALYPSOAI_TOKEN = "ADD-YOUR-TOKEN-HERE"
    
    # Initialize the CalypsoAI client
    cai = CalypsoAI(url=CALYPSOAI_URL, token=CALYPSOAI_TOKEN)
    
    # Configure the scanner
    config = GenAIScannerConfig(input="Political figures", type="custom",
    scanContext=ScanContext.DIRECTIONAL)
    
    version = ScannerVersionInputModel(name="ADD-YOUR-VERSION-NAME-HERE", description="ADD-YOUR-VERSION-DESCRIPTION-HERE", published=False)
    
    response = cai.scanners.create(name='ADD-YOUR-SCANNER-NAME-HERE', config=config,
    direction=ScannerDirection.BOTH, published=False, version=version)
    
    # Print the response
    print(response.model_dump_json(indent=2))
    • Add your token value.
    • In input, provide the input that you want the scanner to scan for and flag.
      In this scenario, the input is Political figures.
    • In version, do the following:

      SCANNER VERSIONS

      When creating a custom scanner, setting a scanner version is optional. If you don't set a version, the system creates a version for you and automatically assigns a version name, with the following additional configuration:

      • description left empty.
      • published set to False.

      For more information, see Working with scanner versions.

      • In name, provide a name for the scanner version.
      • In description, provide a description for the scanner version.
        This is an optional parameter. You can include it to add context and describe the changes made in each new scanner version.
      • In published, enter either True or False.
        If set to True, the scanner version is published and made available for use.
        The default value for this property is False.
    • In response, do the following:
      • In name, provide a name for the scanner.
      • In direction, define the direction of the scan.
        The direction property defines if the scan analyzes the request, the response, or both. You can choose one of the following three options:
        • REQUEST: Only the request (prompt) is scanned. This is the default selection.
        • RESPONSE: Only the LLM response is scanned.
        • BOTH: Both the request and response are scanned.
      • In published, enter either True or False.

        PUBLISHING SCANNER VERSIONS

        • If you don't set a version, or version is invalid, the publishing behavior of the scanner version depends on the value of the published property in response.
        • If version includes the published property, the publishing behavior of the scanner version depends on this value.
        • If the published property is included in both version and response, the publishing behavior of the scanner version depends on the value of the published property in version.
  2. Run the script.

  3. Analyze the response.

    json
    {
        "availability": {
            "global_": true,
            "projectIds": []
        },
        "availableUpdate": null,
        "config": {
            "input": "Political figures",
            "scanContext": "directional",
            "type": "custom"
        },
        "direction": "both",
        "files": [],
        "id": "01973b46-3d66-70b8-94f8-aab4b01d0684",
        "name": "ADD-YOUR-SCANNER-NAME-HERE",
        "packageId": null,
        "projectId": null,
        "scannerTemplateId": "0192afb2-466f-703e-929e-e465d697e653",
        "shared": false,
        "source": {
            "type": "internal"
        },
        "tags": [],
        "vendored": false,
        "versionMeta": {
            "createdAt": "2025-07-29T14:05:14.551745Z",
            "createdBy": null,
            "description": "ADD-YOUR-VERSION-DESCRIPTION-HERE",
            "id": "01985680-6fb7-70b7-a684-960344ebd18b",
            "name": "ADD-YOUR-VERSION-NAME-HERE",
            "published": false
        },
        "published": false
    }

Create a regex scanner

A regex scanner uses regular expressions to scan and flag text based on a regex pattern you can configure.

Regex scanners are most useful for finding input that follows a predictable pattern. For example:

  • Email addresses
  • Phone numbers
  • URLs

In this scenario, we are going to create a regex scanner that scans for and flags any text that contains an email address.

To create a regex scanner:

  1. Edit the following sample.

    python
    from calypsoai import CalypsoAI
    from calypsoai.datatypes import RegexScannerConfig, ScannerDirection, ScannerVersionInputModel
    
    # Define the URL and token for CalypsoAI
    CALYPSOAI_URL = "https://www.us1.calypsoai.app"
    CALYPSOAI_TOKEN = "ADD-YOUR-TOKEN-HERE"
    
    # Initialize the CalypsoAI client
    cai = CalypsoAI(url=CALYPSOAI_URL, token=CALYPSOAI_TOKEN)
    
    # Configure the scanner
    config = RegexScannerConfig(pattern=r"\b[\w.-]+@[\w.-]+\.\w+\b", type="regex")
    
    version = ScannerVersionInputModel(name="ADD-YOUR-VERSION-NAME-HERE", description="ADD-YOUR-VERSION-DESCRIPTION-HERE", published=False)
    
    response = cai.scanners.create(name='ADD-YOUR-SCANNER-NAME-HERE', config=config,
    direction=ScannerDirection.BOTH, published=False, version=version)
    
    # Print the response
    print(response.model_dump_json(indent=2))
    • Add your token value.
    • In pattern, provide the regex pattern that you want the scanner to scan for and flag.
      In this scenario, the pattern is scanning for email addresses.
    • In version, do the following:

      SCANNER VERSIONS

      When creating a custom scanner, setting a scanner version is optional. If you don't set a version, the system creates a version for you and automatically assigns a version name, with the following additional configuration:

      • description left empty.
      • published set to False.

      For more information, see Working with scanner versions.

      • In name, provide a name for the scanner version.
      • In description, provide a description for the scanner version.
        This is an optional parameter. You can include it to add context and describe the changes made in each new scanner version.
      • In published, enter either True or False.
        If set to True, the scanner version is published and made available for use.
        The default value for this property is False.
    • In response, do the following:
      • In name, provide a name for the scanner.
      • In direction, define the direction of the scan.
        The direction property defines if the scan analyzes the request, the response, or both. You can choose one of the following three options:
        • REQUEST: Only the request (prompt) is scanned. This is the default selection.
        • RESPONSE: Only the LLM response is scanned.
        • BOTH: Both the request and response are scanned.
      • In published, enter either True or False.

        PUBLISHING SCANNER VERSIONS

        • If you don't set a version, or version is invalid, the publishing behavior of the scanner version depends on the value of the published property in response.
        • If version includes the published property, the publishing behavior of the scanner version depends on this value.
        • If the published property is included in both version and response, the publishing behavior of the scanner version depends on the value of the published property in version.
  2. Run the script.

  3. Analyze the response.

    json
    {
        "availability": {
            "global_": true,
            "projectIds": []
        },
        "availableUpdate": null,
        "config": {
            "pattern": "\\b[\\w.-]+@[\\w.-]+\\.\\w+\\b",
            "type": "regex"
        },
        "direction": "both",
        "files": [],
        "id": "01973b4a-2623-700b-8f59-38f55352124b",
        "name": "ADD-YOUR-SCANNER-NAME-HERE",
        "packageId": null,
        "projectId": null,
        "scannerTemplateId": null,
        "shared": false,
        "source": {
            "type": "internal"
        },
        "tags": [],
        "vendored": false,
        "versionMeta": {
            "createdAt": "2025-07-29T14:12:59.761349Z",
            "createdBy": null,
            "description": "ADD-YOUR-VERSION-DESCRIPTION-HERE",
            "id": "01985687-88f1-7054-9fbb-f97bd76bf8f9",
            "name": "ADD-YOUR-VERSION-NAME-HERE",
            "published": false
        },
        "published": false
    }

Create a keyword scanner

A keyword scanner scans for and flags text that contains specific keywords you can configure.

In this scenario, we are going to create a keyword scanner that scans for and flags any text that contains the words hello and world.

To create a keyword scanner:

  1. Edit the following sample.

    python
    from calypsoai import CalypsoAI
    from calypsoai.datatypes import KeywordScannerConfig, ScannerDirection,
    ScannerVersionInputModel
    
    # Define the URL and token for CalypsoAI
    CALYPSOAI_URL = "https://www.us1.calypsoai.app"
    CALYPSOAI_TOKEN = "ADD-YOUR-TOKEN-HERE"
    
    # Initialize the CalypsoAI client
    cai = CalypsoAI(url=CALYPSOAI_URL, token=CALYPSOAI_TOKEN)
    
    # Configure the scanner
    config = KeywordScannerConfig(words=["hello", "world"], type="keyword")
    
    version = ScannerVersionInputModel(name="ADD-YOUR-VERSION-NAME-HERE", description="ADD-YOUR-VERSION-DESCRIPTION-HERE", published=False)
    
    response = cai.scanners.create(name='ADD-YOUR-SCANNER-NAME-HERE', config=config,
    direction=ScannerDirection.BOTH, published=False, version=version)
    
    # Print the response
    print(response.model_dump_json(indent=2))
    • Add your token value.
    • In words, provide the keywords that you want the scanner to scan for and flag.
      In this scenario, the keywords are hello and world.
    • In version, do the following:

      SCANNER VERSIONS

      When creating a custom scanner, setting a scanner version is optional. If you don't set a version, the system creates a version for you and automatically assigns a version name, with the following additional configuration:

      • description left empty.
      • published set to False.

      For more information, see Working with scanner versions.

      • In name, provide a name for the scanner version.
      • In description, provide a description for the scanner version.
        This is an optional parameter. You can include it to add context and describe the changes made in each new scanner version.
      • In published, enter either True or False.
        If set to True, the scanner version is published and made available for use.
        The default value for this property is False.
    • In response, do the following:
      • In name, provide a name for the scanner.
      • In direction, define the direction of the scan.
        The direction property defines if the scan analyzes the request, the response, or both. You can choose one of the following three options:
        • REQUEST: Only the request (prompt) is scanned. This is the default selection.
        • RESPONSE: Only the LLM response is scanned.
        • BOTH: Both the request and response are scanned.
      • In published, enter either True or False.

        PUBLISHING SCANNER VERSIONS

        • If you don't set a version, or version is invalid, the publishing behavior of the scanner version depends on the value of the published property in response.
        • If version includes the published property, the publishing behavior of the scanner version depends on this value.
        • If the published property is included in both version and response, the publishing behavior of the scanner version depends on the value of the published property in version.
  2. Run the script.

  3. Analyze the response.

    json
    {
        "availability": {
            "global_": true,
            "projectIds": []
        },
        "availableUpdate": null,
        "config": {
            "type": "keyword",
            "words": [
                "hello",
                "world"
            ]
        },
        "direction": "both",
        "files": [],
        "id": "01973b52-e9c8-7029-8487-3b52a61d28d6",
        "name": "ADD-YOUR-SCANNER-NAME-HERE",
        "packageId": null,
        "projectId": null,
        "scannerTemplateId": null,
        "shared": false,
        "source": {
            "type": "internal"
        },
        "tags": [],
        "vendored": false,
        "versionMeta": {
            "createdAt": "2025-07-29T14:16:56.574340Z",
            "createdBy": null,
            "description": "ADD-YOUR-VERSION-DESCRIPTION-HERE",
            "id": "0198568b-25fe-7052-9ef5-2a31d3415a94",
            "name": "ADD-YOUR-VERSION-NAME-HERE",
            "published": false
        },
        "published": false
    }

Updated at: