diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 643d8b4613ad80ee89da610c33843bca7b3d6610..05cf5354c426092df2d32adc814e83b31aac228a 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -652,6 +652,66 @@ function refer($tid, $target=null) {
 
     }
 
+    function release($tid) {
+        global $thisstaff;
+
+        if (!($ticket=Ticket::lookup($tid)))
+            Http::response(404, __('No such ticket'));
+
+        if (!$ticket->checkStaffPerm($thisstaff, Ticket::PERM_RELEASE) && !$thisstaff->isManager())
+            Http::response(403, __('Permission denied'));
+
+        if (!$ticket->isAssigned())
+            $errors['err'] = __('Ticket is not assigned!');
+
+
+        $errors = array();
+        $info = array(':title' => sprintf(__('Ticket #%s: %s'),
+                    $ticket->getNumber(),
+                    __('Release Confirmation')));
+
+        $form = ReleaseForm::instantiate($_POST);
+        $hasData = ($_POST['sid'] || $_POST['tid']);
+
+        $staff = $ticket->getStaff();
+        $team = $ticket->getTeam();
+        if ($_POST) {
+            if ($hasData && $ticket->release($_POST, $errors)) {
+                $data = array();
+
+                if ($staff && !$ticket->getStaff())
+                    $data['staff'] = array($staff->getId(), (string) $staff->getName()->getOriginal());
+                if ($team && !$ticket->getTeam())
+                    $data['team'] = $team->getId();
+                $ticket->logEvent('released', $data);
+
+                $comments = $form->getComments();
+                if ($comments) {
+                    $title = __('Assignment Released');
+                    $_errors = array();
+
+                    $ticket->postNote(
+                        array('note' => $comments, 'title' => $title),
+                        $_errors, $thisstaff, false);
+                }
+
+                $_SESSION['::sysmsgs']['msg'] = __('Ticket assignment released successfully');
+                Http::response(201, $ticket->getId());
+            }
+
+            if (!$hasData)
+                $errors['err'] = __('Please check an assignee to release assignment');
+
+            $form->addErrors($errors);
+            $info['error'] = $errors['err'] ?: __('Unable to release ticket assignment');
+        }
+
+        if($errors && $errors['err'])
+            $info['error'] = $errors['err'] ?: __('Unable to release ticket');
+
+        include STAFFINC_DIR . 'templates/release.tmpl.php';
+    }
+
     function massProcess($action, $w=null)  {
         global $thisstaff, $cfg;
 
diff --git a/include/class.forms.php b/include/class.forms.php
index e13f5f15d41a0c28bebb7d7e8a1108a247d4d241..6f28d71f98dbf476523733f75c87bcaf3b5251fd 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -4928,6 +4928,49 @@ class ClaimForm extends AssignmentForm {
 
 }
 
+class ReleaseForm extends Form {
+    static $id = 'unassign';
+
+    function getFields() {
+        if ($this->fields)
+            return $this->fields;
+
+        $fields = array(
+            'comments' => new TextareaField(array(
+                    'id' => 1, 'label'=> '', 'required'=>false, 'default'=>'',
+                    'configuration' => array(
+                        'html' => true,
+                        'size' => 'small',
+                        'placeholder' => __('Optional reason for releasing assignment'),
+                        ),
+                    )
+                ),
+            );
+
+
+        $this->setFields($fields);
+
+        return $this->fields;
+    }
+
+    function getField($name) {
+        if (($fields = $this->getFields())
+                && isset($fields[$name]))
+            return $fields[$name];
+    }
+
+    function isValid($include=false) {
+        if (!parent::isValid($include))
+            return false;
+
+        return !$this->errors();
+    }
+
+    function getComments() {
+        return $this->getField('comments')->getClean();
+    }
+}
+
 class ReferralForm extends Form {
 
     static $id = 'refer';
diff --git a/include/class.thread.php b/include/class.thread.php
index 3393043e60e91aed5130ae70bf863e26c44c56e3..7cca14af8f1fdc952e917156fc9a4ad6a81e6f0a 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -1871,6 +1871,7 @@ class ThreadEvent extends VerySimpleModel {
 
     // Valid events for database storage
     const ASSIGNED  = 'assigned';
+    const RELEASED  = 'released';
     const CLOSED    = 'closed';
     const CREATED   = 'created';
     const COLLAB    = 'collab';
@@ -1906,6 +1907,7 @@ class ThreadEvent extends VerySimpleModel {
     function getIcon() {
         $icons = array(
             'assigned'  => 'hand-right',
+            'released'  => 'unlock',
             'collab'    => 'group',
             'created'   => 'magic',
             'overdue'   => 'time',
@@ -2092,7 +2094,7 @@ class ThreadEvents extends InstrumentedList {
      * $object - Object to log activity for
      * $state - State name of the activity (one of 'created', 'edited',
      *      'deleted', 'closed', 'reopened', 'error', 'collab', 'resent',
-     *      'assigned', 'transferred')
+     *      'assigned', 'released', 'transferred')
      * $data - (array?) Details about the state change
      * $user - (string|User|Staff) user triggering the state change
      * $annul - (state) a corresponding state change that is annulled by
@@ -2175,6 +2177,30 @@ class AssignmentEvent extends ThreadEvent {
     }
 }
 
+class ReleaseEvent extends ThreadEvent {
+    static $icon = 'unlock';
+    static $state = 'released';
+
+    function getDescription($mode=self::MODE_STAFF) {
+        $data = $this->getData();
+        switch (true) {
+        case isset($data['staff'], $data['team']):
+            $desc = __('Ticket released from <strong>{<Team>data.team}</strong> and <strong>{<Staff>data.staff}</strong> by <b>{somebody}</b> {timestamp}');
+            break;
+        case isset($data['staff']):
+            $desc = __('Ticket released from <strong>{<Staff>data.staff}</strong> by <b>{somebody}</b> {timestamp}');
+            break;
+        case isset($data['team']):
+            $desc = __('Ticket released from <strong>{<Team>data.team}</strong> by <b>{somebody}</b> {timestamp}');
+            break;
+        default:
+            $desc = __('<b>{somebody}</b> released ticket assignment {timestamp}');
+            break;
+        }
+        return $this->template($desc);
+    }
+}
+
 class ReferralEvent extends ThreadEvent {
     static $icon = 'exchange';
     static $state = 'referred';
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 5078b566e1f8c04944cf524ef379ef9b14b37c16..160c5630ee5bd2daff7822abe0a7f325623bc988 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -98,6 +98,7 @@ implements RestrictedAccess, Threadable, Searchable {
     const PERM_CREATE   = 'ticket.create';
     const PERM_EDIT     = 'ticket.edit';
     const PERM_ASSIGN   = 'ticket.assign';
+    const PERM_RELEASE  = 'ticket.release';
     const PERM_TRANSFER = 'ticket.transfer';
     const PERM_REPLY    = 'ticket.reply';
     const PERM_CLOSE    = 'ticket.close';
@@ -119,6 +120,11 @@ implements RestrictedAccess, Threadable, Searchable {
                 /* @trans */ 'Assign',
                 'desc'  =>
                 /* @trans */ 'Ability to assign tickets to agents or teams'),
+            self::PERM_RELEASE => array(
+                'title' =>
+                /* @trans */ 'Release',
+                'desc'  =>
+                /* @trans */ 'Ability to release ticket assignment'),
             self::PERM_TRANSFER => array(
                 'title' =>
                 /* @trans */ 'Transfer',
@@ -2470,8 +2476,15 @@ implements RestrictedAccess, Threadable, Searchable {
         return true;
     }
 
-    function release() {
-        return $this->unassign();
+    function release($info=array(), &$errors) {
+        if ($info['sid'] && $info['tid'])
+            return $this->unassign();
+        elseif ($info['sid'] && $this->setStaffId(0))
+            return true;
+        elseif ($info['tid'] && $this->setTeamId(0))
+            return true;
+
+        return false;
     }
 
     function refer(ReferralForm $form, &$errors, $alert=true) {
diff --git a/include/i18n/en_US/role.yaml b/include/i18n/en_US/role.yaml
index ca76b2650513d4ffcf0d5bb48fa57cb07b203757..9688cae1f82a35011256f89b18a4211b84178313 100644
--- a/include/i18n/en_US/role.yaml
+++ b/include/i18n/en_US/role.yaml
@@ -20,6 +20,7 @@
     ticket.create,
     ticket.edit,
     ticket.assign,
+    ticket.release,
     ticket.transfer,
     ticket.reply,
     ticket.close,
@@ -44,6 +45,7 @@
     ticket.create,
     ticket.edit,
     ticket.assign,
+    ticket.release,
     ticket.transfer,
     ticket.reply,
     ticket.close,
diff --git a/include/staff/templates/release.tmpl.php b/include/staff/templates/release.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..a60fe50a52dd01efc87c27419590a4991da552ba
--- /dev/null
+++ b/include/staff/templates/release.tmpl.php
@@ -0,0 +1,89 @@
+<?php
+global $cfg;
+
+$assignees = array();
+if (($staff = $ticket->getStaff()))
+    $assignees[] = $staff;
+if (($team = $ticket->getTeam()))
+    $assignees[] = $team;
+
+$form = ReleaseForm::instantiate($_POST);
+?>
+<h3 class="drag-handle"><?php echo $info[':title'] ?:  __('Release Confirmation'); ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<div class="clear"></div>
+<hr/>
+<?php
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['warn']) {
+    echo sprintf('<p id="msg_warning">%s</p>', $info['warn']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} elseif ($info['notice']) {
+   echo sprintf('<p id="msg_info"><i class="icon-info-sign"></i> %s</p>',
+           $info['notice']);
+}
+?>
+<form class="mass-action" method="post"
+    action="#tickets/<?php echo $ticket->getId(); ?>/release"
+    name="release">
+    <input type='hidden' name='do' value='release'>
+    <table width="100%">
+        <tbody>
+        <?php if ($staff && $team) { ?>
+            <tr><td>
+                <p>
+                <?php echo __('Please check assignee(s) to release assignment.'); ?>
+                </p>
+            </td></tr>
+        <?php } ?>
+        <?php if(count($assignees) > 1) { ?>
+            <?php foreach($assignees as $assignee) { ?>
+                <tr><td>
+                    <label class="inline checkbox">
+                        <?php echo sprintf(
+                            ($isStaff = $assignee instanceof Staff)
+                                ? '<input type="checkbox" name="sid[]" id="s%d" value="%d">'
+                                : '<input type="checkbox" name="tid[]" id="t%d" value="%d">',
+                            $assignee->getId(),
+                            $assignee->getId()); ?>
+                    </label>
+                    <?php echo '<i class="icon-'.(($isStaff) ? 'user' : 'group').'"></i>'; ?>
+                    <?php echo $assignee->getName(); ?>
+                </td></tr>
+            <?php } ?>
+        <?php } else { ?>
+            <tr><td>
+                <input type="hidden" name="<?php echo (($staff)?'s':'t').'id[]'; ?>" value="()">
+                <p>
+                <?php echo __('Please confirm to continue.'); ?>
+                </p>
+                <p>
+                <?php echo sprintf(
+                            __('Are you sure you want to <b>unassign</b> ticket from <b>%s</b>?'),
+                            ($staff) ?: $team); ?>
+                </p>
+            </td></tr>
+        <?php } ?>
+            <tr><td>
+                <p>
+                <?php print $form->getField('comments')->render(); ?>
+                </p>
+            </td></tr>
+        </tbody>
+    </table>
+    <hr>
+    <p class="full-width">
+        <span class="buttons pull-left">
+            <input type="reset" value="<?php echo __('Reset'); ?>">
+            <input type="button" name="cancel" class="close"
+                value="<?php echo __('Cancel'); ?>">
+        </span>
+        <span class="buttons pull-right">
+            <input type="submit" value="<?php
+            echo __('Release'); ?>">
+        </span>
+    </p>
+</form>
+<div class="clear"></div>
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 21d5646e92a065605f26eefb86e1c9055ab4c2ff..33272a222b17afd06db4b06198263b36ad9ba144 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -20,6 +20,8 @@ if (!$lock && $cfg->getTicketLockMode() == Lock::MODE_ON_VIEW)
     $lock = $ticket->acquireLock($thisstaff->getId());
 $mylock = ($lock && $lock->getStaffId() == $thisstaff->getId()) ? $lock : null;
 $id    = $ticket->getId();    //Ticket ID.
+$isManager = $dept->isManager($thisstaff); //Check if Agent is Manager
+$canRelease = ($isManager || $role->hasPerm(Ticket::PERM_RELEASE)); //Check if Agent can release tickets
 
 //Useful warnings and errors the user might want to know!
 if ($ticket->isClosed() && !$ticket->isReopenable())
@@ -146,14 +148,14 @@ if($ticket->isOverdue())
                 <?php
                  }
 
-                 if($ticket->isOpen() && ($dept && $dept->isManager($thisstaff))) {
-
-                    if($ticket->isAssigned()) { ?>
-                        <li><a  class="confirm-action" id="ticket-release" href="#release"><i class="icon-user"></i> <?php
-                            echo __('Release (unassign) Ticket'); ?></a></li>
-                    <?php
-                    }
-
+                 if ($ticket->isAssigned() && $canRelease) { ?>
+                        <li><a href="#tickets/<?php echo $ticket->getId();
+                            ?>/release" class="ticket-action"
+                             data-redirect="tickets.php?id=<?php echo $ticket->getId(); ?>" >
+                               <i class="icon-unlock"></i> <?php echo __('Release (unassign) Ticket'); ?></a></li>
+                 <?php
+                 }
+                 if($ticket->isOpen() && $isManager) {
                     if(!$ticket->isOverdue()) { ?>
                         <li><a class="confirm-action" id="ticket-overdue" href="#overdue"><i class="icon-bell"></i> <?php
                             echo __('Mark as Overdue'); ?></a></li>
diff --git a/scp/ajax.php b/scp/ajax.php
index 7dc4a56a2a9c690add163d05fed948045ad7cd2a..dfdb7499e7ae093c1a55e20f8937772d6447002e 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -167,6 +167,7 @@ $dispatcher = patterns('',
         url('^(?P<tid>\d+)/field/(?P<fid>\d+)/edit$', 'editField'),
         url('^(?P<tid>\d+)/field/(?P<field>\w+)/edit$', 'editField'),
         url('^(?P<tid>\d+)/assign(?:/(?P<to>\w+))?$', 'assign'),
+        url('^(?P<tid>\d+)/release$', 'release'),
         url('^(?P<tid>\d+)/refer(?:/(?P<to>\w+))?$', 'refer'),
         url('^(?P<tid>\d+)/referrals$', 'referrals'),
         url('^(?P<tid>\d+)/claim$', 'claim'),
diff --git a/scp/tickets.php b/scp/tickets.php
index 1e1a085ab48afbf63f32af2db1329b4ba037fdf3..ca0770817b558436d31691a035011e47abcfb3f4 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -282,19 +282,6 @@ if($_POST && !$errors):
             break;
         case 'process':
             switch(strtolower($_POST['do'])):
-                case 'release':
-                    if(!$ticket->isAssigned() || !($assigned=$ticket->getAssigned())) {
-                        $errors['err'] = __('Ticket is not assigned!');
-                    } elseif($ticket->release()) {
-                        $msg=sprintf(__(
-                            /* 1$ is the current assignee, 2$ is the agent removing the assignment */
-                            'Ticket released (unassigned) from %1$s by %2$s'),
-                            $assigned, $thisstaff->getName());
-                        $ticket->logActivity(__('Ticket unassigned'),$msg);
-                    } else {
-                        $errors['err'] = sprintf('%s %s', __('Problems releasing the ticket.'), __('Please try again!'));
-                    }
-                    break;
                 case 'claim':
                     if(!$role->hasPerm(Ticket::PERM_EDIT)) {
                         $errors['err'] = __('Permission Denied. You are not allowed to assign/claim tickets.');