diff --git a/yasmin/include/yasmin/state_machine.hpp b/yasmin/include/yasmin/state_machine.hpp
index e67fc96..fd64463 100644
--- a/yasmin/include/yasmin/state_machine.hpp
+++ b/yasmin/include/yasmin/state_machine.hpp
@@ -16,6 +16,7 @@
 #ifndef YASMIN_STATE_MACHINE_HPP
 #define YASMIN_STATE_MACHINE_HPP
 
+#include <atomic>
 #include <functional>
 #include <map>
 #include <memory>
@@ -40,14 +41,16 @@ namespace yasmin {
  */
 class StateMachine : public State {
 
-  // Type definitions for callback functions
+  /// Alias for a callback function executed before running the state machine.
   using StartCallbackType = std::function<void(
       std::shared_ptr<yasmin::blackboard::Blackboard>, const std::string &,
       const std::vector<std::string> &)>;
+  /// Alias for a callback function executed before changing the state.
   using TransitionCallbackType = std::function<void(
       std::shared_ptr<yasmin::blackboard::Blackboard>, const std::string &,
       const std::string &, const std::string &,
       const std::vector<std::string> &)>;
+  /// Alias for a callback function executed after running the state machine.
   using EndCallbackType = std::function<void(
       std::shared_ptr<yasmin::blackboard::Blackboard>, const std::string &,
       const std::vector<std::string> &)>;
@@ -225,20 +228,27 @@ class StateMachine : public State {
   std::string to_string();
 
 private:
-  std::map<std::string, std::shared_ptr<State>> states; ///< Map of states
-  std::map<std::string, std::map<std::string, std::string>>
-      transitions;           ///< Map of transitions
-  std::string start_state;   ///< Name of the start state
-  std::string current_state; ///< Name of the current state
-  std::unique_ptr<std::mutex>
-      current_state_mutex; ///< Mutex for current state access
-
-  std::vector<std::pair<StartCallbackType, std::vector<std::string>>>
-      start_cbs; ///< Start callbacks
+  /// Map of states
+  std::map<std::string, std::shared_ptr<State>> states;
+  /// Map of transitions
+  std::map<std::string, std::map<std::string, std::string>> transitions;
+  /// Name of the start state
+  std::string start_state;
+  /// Name of the current state
+  std::string current_state;
+  /// Mutex for current state access
+  std::unique_ptr<std::mutex> current_state_mutex;
+
+  /// Flag to indicate if the state machine has been validated
+  std::atomic_bool validated{false};
+
+  /// Start callbacks executed before the state machine
+  std::vector<std::pair<StartCallbackType, std::vector<std::string>>> start_cbs;
+  /// Transition callbacks executed before changing the state
   std::vector<std::pair<TransitionCallbackType, std::vector<std::string>>>
-      transition_cbs; ///< Transition callbacks
-  std::vector<std::pair<EndCallbackType, std::vector<std::string>>>
-      end_cbs; ///< End callbacks
+      transition_cbs;
+  /// End callbacks executed before the state machine
+  std::vector<std::pair<EndCallbackType, std::vector<std::string>>> end_cbs;
 };
 
 } // namespace yasmin
diff --git a/yasmin/src/yasmin/state_machine.cpp b/yasmin/src/yasmin/state_machine.cpp
index eeb5832..262db59 100644
--- a/yasmin/src/yasmin/state_machine.cpp
+++ b/yasmin/src/yasmin/state_machine.cpp
@@ -85,6 +85,9 @@ void StateMachine::add_state(std::string name, std::shared_ptr<State> state,
   if (this->start_state.empty()) {
     this->set_start_state(name);
   }
+
+  // Mark state machine as no validated
+  this->validated.store(false);
 }
 
 void StateMachine::add_state(std::string name, std::shared_ptr<State> state) {
@@ -194,6 +197,11 @@ void StateMachine::validate() {
 
   YASMIN_LOG_DEBUG("Validating state machine '%s'", this->to_string().c_str());
 
+  if (this->validated.load()) {
+    YASMIN_LOG_DEBUG("State machine '%s' has already been validated",
+                     this->to_string().c_str());
+  }
+
   // Check initial state
   if (this->start_state.empty()) {
     throw std::runtime_error("No initial state set");
@@ -260,6 +268,9 @@ void StateMachine::validate() {
                                "' not registered as outcome or state");
     }
   }
+
+  // State machine has been validated
+  this->validated.store(true);
 }
 
 std::string
diff --git a/yasmin/yasmin/state_machine.py b/yasmin/yasmin/state_machine.py
index 4cd0289..a8a61e6 100644
--- a/yasmin/yasmin/state_machine.py
+++ b/yasmin/yasmin/state_machine.py
@@ -54,6 +54,10 @@ def __init__(self, outcomes: Set[str]) -> None:
         self.__current_state: str = None
         ## A threading lock to manage access to the current state.
         self.__current_state_lock: Lock = Lock()
+
+        ## A flag indicating whether the state machine has been validated.
+        self._validated: bool = False
+
         ## A list of callbacks to call when the state machine starts.
         self.__start_cbs: List[
             Tuple[Callable[[Blackboard, str, List[Any]], None], List[Any]]
@@ -119,6 +123,9 @@ def add_state(
         if not self._start_state:
             self.set_start_state(name)
 
+        ## Mark state machine as no validated
+        self._validated = False
+
     def set_start_state(self, state_name: str) -> None:
         """
         Sets the initial state for the state machine.
@@ -276,6 +283,9 @@ def validate(self) -> None:
         """
         yasmin.YASMIN_LOG_DEBUG(f"Validating state machine '{self}'")
 
+        if self._validated:
+            yasmin.YASMIN_LOG_DEBUG("State machine '{self}' has already been validated")
+
         # terminal outcomes
         terminal_outcomes = []
 
@@ -323,6 +333,9 @@ def validate(self) -> None:
                     f"State machine outcome '{o}' not registered as outcome neither state"
                 )
 
+        # State machine has been validated
+        self._validated = True
+
     def execute(self, blackboard: Blackboard) -> str:
         """
         Executes the state machine starting from the initial state.