diff --git a/workbench_moderation.api.php b/workbench_moderation.api.php
index 7dc8b9c..974f2f8 100644
--- a/workbench_moderation.api.php
+++ b/workbench_moderation.api.php
@@ -26,3 +26,19 @@ function hook_workbench_moderation_access_alter(&$access, $op, $node) {
     $access = FALSE;
   }
 }
+
+/**
+ * Allows modules to respond to state transitions.
+ *
+ * @param $node
+ *  The node that is being transitioned.
+ *
+ * @param $previous_state
+ *  The state of the revision before the transition occurred.
+ *
+ * @param $new_state
+ *  The new state of the revision.
+ */
+function hook_workbench_moderation_transition($node, $previous_state, $new_state) {
+  // Your code here.
+}
diff --git a/workbench_moderation.module b/workbench_moderation.module
index 87fac94..9e86725 100644
--- a/workbench_moderation.module
+++ b/workbench_moderation.module
@@ -1538,6 +1538,10 @@ function workbench_moderation_moderate($node, $state) {
   if (!empty($node->workbench_moderation['published'])) {
     drupal_register_shutdown_function('workbench_moderation_store', $node);
   }
+
+
+  // Notify other modules that the state was changed.
+  module_invoke_all('workbench_moderation_transition', $node, $old_revision->state, $state);
 }
 
 /**
@@ -1926,6 +1930,161 @@ function workbench_moderation_workbench_block() {
   return $output;
 }
 
+
+/**
+ * Implementation of hook_workbench_moderation_transition().
+ */
+function workbench_moderation_workbench_moderation_transition($node, $previous_state, $new_state) {
+  if (module_exists('trigger')) {
+    workbench_moderation_trigger_transition($node, $previous_state, $new_state);
+  }
+
+  if (module_exists('rules')){
+    rules_invoke_event('workbench_moderation_after_moderation_transition', $node, $previous_state, $new_state);
+  }
+}
+
+/**
+ * Implements hook_trigger_info().
+ *
+ * Creates a trigger for each transition.
+ */
+function workbench_moderation_trigger_info() {
+
+  $output = array(
+    'workbench_moderation' => array(
+      'workbench_moderation_transition' => array(
+        'label' => t('After any transition between states occurs.'),
+      ),
+    ),
+  );
+
+  // Get all transitions.
+  $transitions = workbench_moderation_transitions();
+
+  // Add a trigger for each transition.
+  foreach ($transitions as $transition_definition) {
+    $transition_string = 'wmt_' . $transition_definition->from_name . '__' . $transition_definition->to_name;
+    // Hash this string if it's longer than the db field size
+    if (strlen($transition_string) > 32) {
+      $transition_string = md5($transition_string);
+    }
+
+    $output['workbench_moderation'][$transition_string] = array(
+      'label' => t('Transition from the state %from_name to %to_name occurs.', array('%from_name' => $transition_definition->from_name, '%to_name' => $transition_definition->to_name)),
+    );
+  }
+
+  return $output;
+}
+
+/**
+ * transition trigger: Run actions associated with an arbitrary event.
+ *
+ * This function is executed after a transition takes place.
+ *
+ * @param $node
+ *   The node undergoing the transition.
+ * @param $from_state
+ *   The previous workbench moderation state.
+ * @param $state
+ *   The new workbench moderation state.
+ */
+function workbench_moderation_trigger_transition($node, $from_state, $state, $a3 = NULL, $a4 = NULL) {
+  // Ask the trigger module for all actions enqueued for the 'transition' trigger.
+  $aids = trigger_get_assigned_actions('workbench_moderation_transition');
+  // prepare a basic context, indicating group and "hook", and call all the
+  // actions with this context as arguments.
+  $context = array(
+    'group' => 'workbench_moderation',
+    'hook' => 'transition',
+    'from_state' => $from_state,
+    'state' => $state,
+  );
+  actions_do(array_keys($aids), $node, $context, $a3, $a4);
+
+
+  // Ask the trigger module for all actions enqueued for this specific transition.
+  $transition_string = 'wmt_' . $from_state . '__' . $state;
+  // Hash this string if it's longer than the db field size
+  if (strlen($transition_string) > 32) {
+    $transition_string = md5($transition_string);
+  }
+  $aids = trigger_get_assigned_actions($transition_string);
+  $context['hook'] = $transition_string;
+
+  actions_do(array_keys($aids), $node, $context, $a3, $a4);
+}
+
+/**
+ * Implements hook_action_info().
+ */
+function workbench_moderation_action_info() {
+  $info = array();
+  $info['workbench_moderation_set_state_action'] = array(
+    'type' => 'node',
+    'label' => t('Set moderation state'),
+    'configurable' => TRUE,
+    'behavior' => array('changes_property'),
+    'triggers' => array('node_presave', 'node_insert', 'node_update', 'workbench_moderation_transition'),
+  );
+
+  // Get all workbench transitions.
+  $transitions = workbench_moderation_transitions();
+
+  // Add a trigger for each transition.
+  foreach ($transitions as $transition_definition) {
+    $transition_string = 'wmt_' . $transition_definition->from_name . '__' . $transition_definition->to_name;
+    // Hash this string if it's longer than the db field size
+    if (strlen($transition_string) > 32) {
+      $transition_string = md5($transition_string);
+    }
+
+    $info['workbench_moderation_set_state_action']['triggers'][] = $transition_string;
+  }
+
+  return $info;
+}
+
+/**
+ * Form builder; Prepare a form for possible moderation states.
+ */
+function workbench_moderation_set_state_action_form($context) {
+  $form = array();
+
+  $form['state'] = array(
+    '#type' => 'select',
+    '#options' => workbench_moderation_state_labels(),
+    '#default_value' => isset($context['state']) ? $context['state'] : '',
+  );
+
+  $form['force_transition'] = array(
+    '#type' => 'checkbox',
+    '#default_value' => FALSE,
+  );
+
+  return $form;
+}
+
+/**
+ * Process workbench_moderation_set_state_action_form form submissions.
+ */
+function workbench_moderation_set_state_action_submit($form, $form_state) {
+  return array('state' => $form_state['values']['state'], 'force_transition' => $form_state['values']['force_transition']);
+}
+
+/**
+ * Changes the moderation state for a given node.
+ */
+function workbench_moderation_set_state_action($node, $context) {
+  if (empty($context['state'])) return;
+
+  if ((array_key_exists('force_transition', $context) && $context['force_transition']) || _workbench_moderation_moderate_access($node, $context['state'])){
+    workbench_moderation_moderate($node, $context['state']);
+    watchdog('action', 'Change node %nid moderation state to %state.', array('%nid' => $node->nid, '%state' => $context['state']));
+  }
+}
+
 /**
  * Implements hook_ctools_plugin_directory() to let the system know
  * where our task and task_handler plugins are.
diff --git a/workbench_moderation.rules.inc b/workbench_moderation.rules.inc
new file mode 100644
index 0000000..b16b8a8
--- /dev/null
+++ b/workbench_moderation.rules.inc
@@ -0,0 +1,288 @@
+<?php
+
+/**
+ * Implements hook_rules_file_info().
+ */
+function workbench_moderation_rules_file_info() {
+  $items = array();
+  $items[] = 'workbench_moderation.rules';
+
+  return $items;
+}
+
+/**
+ * Implements hook_rules_condition_info().
+ */
+function workbench_moderation_rules_condition_info() {
+  $items = array();
+
+  $items['content_is_using_workbench_moderation'] = array(
+    'group' => t("Node"),
+    'label' => t("Content is using workbench moderation"),
+    'base' => 'workbench_access_rules_condition_content_is_using_workbench_moderation',
+    'parameter' => array(
+      'node' => array('type' => 'node', 'label' => t("Content")),
+    ),
+    'access callback' => 'rules_node_integration_access',
+  );
+
+  $items['content_is_live_revision'] = array(
+    'group' => t("Node"),
+    'label' => t("Content is live revision"),
+    'base' => 'workbench_moderation_rules_condition_content_is_live_revision',
+    'parameter' => array(
+      'node' => array('type' => 'node', 'label' => t("Content")),
+    ),
+    'access callback' => 'rules_node_integration_access',
+  );
+
+  $items['contents_current_state'] = array(
+    'group' => t("Node"),
+    'label' => t("Content's current moderation state"),
+    'base' => 'workbench_moderation_rules_condition_contents_current_state',
+    'parameter' => array(
+      'node' => array('type' => 'node', 'label' => t("Content")),
+      'moderation_state' => array(
+        'type' => 'text',
+        'label' => t("Workbench moderation state"),
+        'options list' => 'workbench_moderation_state_labels',
+        'restriction' => 'input',
+        'save' => TRUE,
+      ),
+    ),
+    'access callback' => 'rules_node_integration_access',
+  );
+
+  $items['contents_previous_state'] = array(
+    'group' => t("Node"),
+    'label' => t("Content's previous moderation state"),
+    'base' => 'workbench_moderation_rules_condition_contents_previous_state',
+    'parameter' => array(
+      'node' => array('type' => 'node', 'label' => t("Content")),
+      'moderation_state' => array(
+        'type' => 'text',
+        'label' => t("Workbench moderation state"),
+        'options list' => 'workbench_moderation_state_labels',
+        'restriction' => 'input',
+        'save' => TRUE,
+      ),
+    ),
+    'access callback' => 'rules_node_integration_access',
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_rules_event_info().
+ */
+function workbench_moderation_rules_event_info() {
+  $items = array();
+
+  $items['workbench_moderation_after_unpublishing_live_content'] = array(
+    'label' => t("After unpublishing live content"),
+    'group' => t("Node"),
+    'variables' => rules_events_node_variables(t("Unpublished content"), FALSE),
+    'access callback' => 'rules_node_integration_access',
+  );
+
+  $items['workbench_moderation_after_unpublishing_live_content']['variables']['live_content'] = array(
+    'type' => 'node',
+    'label' => t("Live workbench content"),
+  );
+
+  $items['workbench_moderation_after_moderation_transition'] = array(
+    'label' => t("After moderation transition"),
+    'group' => t("Node"),
+    'variables' => rules_events_node_variables(t("Content"), FALSE) + array(
+      'previous_state' => array(
+        'type' => 'text',
+        'label' => t('Previous state'),
+      ),
+      'new_state' => array(
+        'type' => 'text',
+        'label' => t('New state'),
+      ),
+    ),
+    'access callback' => 'rules_node_integration_access',
+  );
+
+  return $items;
+}
+
+/**
+ * Implements hook_rules_action_info() on behalf of the workbench_moderation module.
+ */
+function workbench_moderation_rules_action_info() {
+  $items = array();
+
+  $items['workbench_moderation_set_state'] = array(
+    'label' => t("Set moderation state"),
+    'group' => t("Node"),
+    'base' => 'workbench_moderation_set_state_rules_action',
+
+    'parameter' => array(
+      'node' => array(
+        'type' => 'node',
+        'label' => t("Content"),
+      ),
+      'moderation_state' => array(
+        'type' => 'text',
+        'label' => t("Workbench moderation state"),
+        'options list' => 'workbench_moderation_state_labels',
+        'restriction' => 'input',
+      ),
+      'force_transition' => array(
+        'type' => 'boolean',
+        'label' => t("Force transition"),
+        'restriction' => 'input',
+      ),
+    ),
+  );
+
+  $items['workbench_moderation_load_current_state'] = array(
+    'label' => t("Load current moderation state"),
+    'group' => t("Node"),
+    'base' => 'workbench_moderation_load_current_state_rules_action',
+
+    'parameter' => array(
+      'node' => array(
+        'type' => 'node',
+        'label' => t("Content"),
+      ),
+    ),
+    'provides' => array(
+      'workbench_moderation_state' => array(
+        'type' => 'unknown',
+        'label' => t("Workbench moderation state"),
+      ),
+    ),
+  );
+
+  return $items;
+}
+
+/**
+ * Condition: Check if the content is using workbench moderation.
+ *
+ * @param $node
+ *   A node object
+ *
+ * @return
+ *   TRUE/FALSE depending on if the content is using workbench moderation.
+ */
+function workbench_access_rules_condition_content_is_using_workbench_moderation($node) {
+  if (!is_object($node)) {
+    return FALSE;
+  }
+
+  return workbench_moderation_node_type_moderated($node->type);
+}
+
+/**
+ * Condition: Check if the content is live revision
+ *
+ * @param $node
+ *   A node object
+ *
+ * @return
+ *   TRUE/FALSE depending on if the content is live revision.
+ */
+function workbench_moderation_rules_condition_content_is_live_revision($node) {
+  if (!is_object($node)) {
+    return FALSE;
+  }
+
+  return workbench_moderation_node_is_current($node);
+}
+
+/**
+ * Condition: Check if workbench moderation state matched selected state.
+ *
+ * @param $node
+ *   A node object
+ *
+ * @param $moderation_state
+ *   The desired moderation state to compare with
+ *
+ * @return
+ *  TRUE/FALSE depending on if the nodes current state matches selected state.
+ */
+function workbench_moderation_rules_condition_contents_current_state($node, $moderation_state) {
+  if (!is_object($node)) {
+    return FALSE;
+  }
+
+  if ($node->workbench_moderation['current']->state != $moderation_state) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * Condition: Check if workbench moderation previous state matched selected state.
+ *
+ * @param $node
+ *   A node object
+ *
+ * @param $moderation_state
+ *   The desired moderation state to compare with
+ *
+ * @return
+ *  TRUE/FALSE depending on if the nodes previous state matches selected state.
+ */
+function workbench_moderation_rules_condition_contents_previous_state($node, $moderation_state) {
+  if (!is_object($node)) {
+    return FALSE;
+  }
+
+  if ($node->workbench_moderation['current']->from_state != $moderation_state) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+ * Action: Change the moderation state of a given node.
+ *
+ * $param $node
+ *   A node object
+ *
+ * $param $moderation_state
+ *   The desired moderation state to assign.
+
+ * $param $force_transition
+ *   If set to TRUE, then the transition change will be allowed regardless of permissions and allowed transition flow.
+ *   If set to FALSE, then the transition only changes if all transition change requirements are met.
+ *
+ * @return
+ *   An array containing the node object stored in the key called 'node'.
+ */
+function workbench_moderation_set_state_rules_action($node, $moderation_state, $force_transition) {
+  if (is_object($node) && !empty($moderation_state)){
+    actions_do('workbench_moderation_set_state_action', $node, array('state' => $moderation_state, 'force_transition' => $force_transition));
+  }
+
+  return array('node' => $node);
+}
+
+/**
+ * Action: Loads the workbench access states into a variable.
+ *
+ * $param $node
+ *   A node object
+ *
+ * @return
+ *   An array containing the node object stored in the key called 'node' and an array containing the access control states for the given node.
+ */
+function workbench_moderation_load_current_state_rules_action($node) {
+  $state = '';
+
+  if (is_object($node) && property_exists($node, 'workbench_moderation') && isset($node->workbench_moderation['current'])){
+    $state = $node->workbench_moderation['current'];
+  }
+
+  return array('node' => $node, 'workbench_moderation_state' => $state);
+}
