Build your first agent in just a few minutes with [Rasa Copilot](https://hello.rasa.com/?utm_source=docs&utm_medium=referral&utm_campaign=docs_cta).

There is a helper class in Rasa SDK with the role of executing custom slot extraction and validation:

- `ValidationAction`: the base class for custom actions extracting and validating slots.

In order to implement custom slot extraction and validation logic, you can subclass the `ValidationAction` class.

## `ValidationAction` class

##### NLU-based assistants

This section refers to building NLU-based assistants. If you are working with [Conversational AI with Language Models (CALM)](/content/docs/calm/index.html), this content may not apply to you.

You can extend the `ValidationAction` class in the Rasa SDK to define custom extraction and / or validation of slots.

### How to subclass `ValidationAction`

Firstly, you must add the name of this action, `action_validate_slot_mappings`, to the domain `actions` list. Note that you do not need to implement the `name` method in the custom action extending `ValidationAction`, since this is already implemented. If you override the `name` method, the custom validation action will not run because the original name is hardcoded in the call that the default action `action_extract_slots` makes to the action server.

You should create only one subclass of `ValidationAction` which should contain all extraction and validation methods for different slots according to your use-case.

With this option, you do not need to specify the `action` key in the [custom slot mapping](https://legacy-docs-oss.rasa.com/docs/rasa/domain/#custom-slot-mappings), since the default action [`action_extract_slots`](https://legacy-docs-oss.rasa.com/docs/rasa/default-actions/#action_extract_slots) runs `action_validate_slot_mappings` automatically if present in the `actions` section of the domain.

#### Validation of Slots with Predefined Mappings

To validate slots with a predefined mapping, you must write functions named `validate_<slot_name>`.

In the following example, the value for slot `location` is capitalized only if the extracted value is of type string:

```python
from typing import Text, Any, Dict

from rasa_sdk import Tracker, ValidationAction
from rasa_sdk.executor import CollectingDispatcher
from rasa_sdk.types import DomainDict

class ValidatePredefinedSlots(ValidationAction):
    def validate_location(
        self,
        slot_value: Any,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate location value."""
        if isinstance(slot_value, str):
            # validation succeeded, capitalize the value of the "location" slot
            return {"location": slot_value.capitalize()}
        else:
            # validation failed, set this slot to None
            return {"location": None}
```

#### Extraction of Custom Slot Mappings

To define custom extraction code, write an `extract_<slot_name>` method for every slot with a custom slot mapping.

The following example shows the implementation of a custom action that extracts the slot `count_of_insults` to keep track of the user's attitude.

```python
from typing import Dict, Text, Any

from rasa_sdk import Tracker
from rasa_sdk.executor import CollectingDispatcher

class ValidateCustomSlotMappings(ValidationAction):
    async def extract_count_of_insults(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> Dict[Text, Any]:
        intent_of_last_user_message = tracker.get_intent_of_latest_message()
        current_count_of_insults = tracker.get_slot("count_of_insults")
        if intent_of_last_user_message == "insult":
           current_count_of_insults += 1

return {"count_of_insults": current_count_of_insults}
```

### `ValidationAction` class implementation

`ValidationAction` is a subclass of the `Action` Rasa SDK class and the abstract Python `ABC` class. Therefore the class implements the `name` and `run` methods inherited from `Action`. In addition, `ValidationAction` implements more specialized methods that will be called in the `run` method:

- `get_extraction_events`: Extracts custom slots using available `extract_<slot name>` methods
- `get_validation_events`: Validates slots by calling available `validate_<slot name>` methods for each slot
- `required_slots`: Returns slots which the validation action should fill

#### Methods

##### ValidationAction.name

Defines the action's name: this must be hardcoded as `action_validate_slot_mappings`.

- **Returns**:

Name of action

- **Return type**:

`str`

##### ValidationAction.run

```python
async ValidationAction.run(dispatcher, tracker, domain)
```

The `run` method executes the custom extraction code defined in `extract_<slot name>` methods by calling the `get_extraction_events` method, then updates the tracker with the returned events. The `run` method will also execute custom validation code defined in `validate_<slot name>` methods via the `get_validation_events` method and add the returned events to the tracker.

###### **Parameters**

- **dispatcher** – the dispatcher which is used to send messages back to the user. Use `dispatcher.utter_message()` or any other `rasa_sdk.executor.CollectingDispatcher` method.
- **tracker** – the state tracker for the current user. You can access slot values using `tracker.get_slot(slot_name)`, the most recent user message is `tracker.latest_message.text` and any other `rasa_sdk.Tracker` property.
- **domain** – the bot's domain

###### **Returns**

A list of `rasa_sdk.events.Event` instances.

###### **Return type**

`List`
[`Dict`
[`str`, `Any`]
]

##### ValidationAction.required_slots

```python
async ValidationAction.required_slots(domain_slots, dispatcher, tracker, domain)
```

The `required_slots` method will return the `domain_slots` which is a list of all slot names mapped in the domain that do not include any slot mapping with conditions.

###### **Returns**

A list of slot names of type `Text`.

##### ValidationAction.get_extraction_events

```python
async ValidationAction.get_extraction_events(dispatcher, tracker, domain)
```

The `get_extraction_events` method will gather the list of slot names via `required_slots` method call and then loop through every slot name to run the `extract_<slot name>` method if available.

##### **Returns**

A list of `rasa_sdk.events.SlotSet` instances.

##### ValidationAction.get_validation_events

```python
async ValidationAction.get_validation_events(dispatcher, tracker, domain)
```

The `get_validation_events` method will gather the list of slot names to validate via `required_slots` method call. Then it will get a mapping of slots which were recently set and their values via `tracker.slots_to_validate` call. Looping through this mapping of recently extracted slots, it will check if the slot is in `required_slots` then run the `validate_<slot name>` method if available for that slot.

###### **Returns**

A list of `rasa_sdk.events.SlotSet` instances.

### How to implement custom validation in CALM assistants

In CALM assistants, slot validation actions should be implemented like normal [actions](/content/docs/reference/integrations/action-server/sdk-actions/index.html) by subclassing the base `Action` class.

Here is an example of a custom slot validation action in a CALM assistant:

```python
class ValidateLocation(Action):
    def name(self) -> Text:
        return "validate_location"

def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: DomainDict,
    ) -> Dict[Text, Any]:
        """Validate slot value."""
        slot_value = tracker.get_slot("location")
        if isinstance(slot_value, str):
            # validation succeeded, capitalize the value of the "location" slot
            return {"location": slot_value.capitalize()}
        else:
            # validation failed, set this slot to None
            return {"location": None}
```

- [`ValidationAction` class](/content/docs/reference/integrations/action-server/validation-action/#validationaction-class/index.html)
  - [How to subclass `ValidationAction`](/content/docs/reference/integrations/action-server/validation-action/#how-to-subclass-validationaction/index.html)
  - [`ValidationAction` class implementation](/content/docs/reference/integrations/action-server/validation-action/#validationaction-class-implementation/index.html)
  - [How to implement custom validation in CALM assistants](/content/docs/reference/integrations/action-server/validation-action/#how-to-implement-custom-validation-in-calm-assistants/index.html)
