diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index aa98426b03fde1e2687f587f17a1e024ecb0b388..68c47315c220d0a022c7e999aa41ac3f81f308db 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -1304,7 +1304,7 @@ function refer($tid, $target=null) {
          include STAFFINC_DIR . 'ticket-tasks.inc.php';
     }
 
-    function addTask($tid) {
+    function addTask($tid, $thread_id=NULL) {
         global $thisstaff;
 
         if (!($ticket=Ticket::lookup($tid)))
@@ -1313,6 +1313,9 @@ function refer($tid, $target=null) {
         if (!$ticket->checkStaffPerm($thisstaff, Task::PERM_CREATE))
             Http::response(403, 'Permission denied');
 
+        if ($thread_id && !($thread_entry=ThreadEntry::lookup($thread_id)))
+            Http::response(404, 'Unknown ticket thread');
+
         $info=$errors=array();
 
         if ($_POST) {
@@ -1358,6 +1361,9 @@ function refer($tid, $target=null) {
                 __('Add New Task')
                 );
 
+        if ($thread_entry)
+            $vars['description'] = Format::htmlchars($thread_entry->getBody());
+
          include STAFFINC_DIR . 'templates/task.tmpl.php';
     }
 
diff --git a/include/class.thread_actions.php b/include/class.thread_actions.php
index dffc936310fbe6890569548705cb2d634500c7a9..ed0ae57646dbcbaabb38eb7bf86ca9da13cadfe3 100644
--- a/include/class.thread_actions.php
+++ b/include/class.thread_actions.php
@@ -429,3 +429,42 @@ class TEA_ResendThreadEntry extends TEA_EditAndResendThreadEntry {
     }
 }
 ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_ResendThreadEntry');
+
+class TEA_CreateTask extends ThreadEntryAction {
+    static $id = 'create_task';
+    static $name = /* trans */ 'Create Task';
+    static $icon = 'plus';
+
+    function isVisible() {
+        global $thisstaff;
+
+        return $thisstaff && $thisstaff->hasPerm(Task::PERM_CREATE, false);
+    }
+
+    function getJsStub() {
+        return sprintf(<<<JS
+var url = '%s';
+var redirect = $(this).data('redirect');
+$.dialog(url, [201], function(xhr, resp) {
+    if (!!redirect)
+        $.pjax({url: redirect, container:'#pjax-container'});
+    else
+        $.pjax({url: 'ajax.php/tickets/378/tasks', container: '#tasks_content', push: false});
+});
+JS
+        , $this->getAjaxUrl()
+        );
+    }
+
+    function trigger() {
+        switch ($_SERVER['REQUEST_METHOD']) {
+        case 'GET':
+            return $this->trigger__get();
+        }
+    }
+
+    private function trigger__get() {
+        include STAFFINC_DIR . 'templates/task.tmpl.php';
+    }
+}
+ThreadEntry::registerAction(/* trans */ 'Manage', 'TEA_CreateTask');
diff --git a/include/staff/templates/task.tmpl.php b/include/staff/templates/task.tmpl.php
index 7bcafc77d68a267e0a20f62fdf8480f5edec29b0..cbf6e0a333c166a15eff8078afa8f2735cc6bd34 100644
--- a/include/staff/templates/task.tmpl.php
+++ b/include/staff/templates/task.tmpl.php
@@ -25,7 +25,7 @@ if ($info['error']) {
 <form method="post" class="org" action="<?php echo $info['action'] ?: '#tasks/add'; ?>">
     <?php
         $form = $form ?: TaskForm::getInstance();
-        echo $form->getForm()->asTable(' ',
+        echo $form->getForm($vars)->asTable(' ',
                 array('draft-namespace' => $namespace)
                 );
 
diff --git a/scp/ajax.php b/scp/ajax.php
index 039af6b3e48d838eeabd2506dffbfc67c3055ed7..b08f547670be3503f4b862d43ee0ded6ad093b98 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -154,6 +154,7 @@ $dispatcher = patterns('',
         url_get('^(?P<tid>\d+)/canned-resp/(?P<cid>\w+).(?P<format>json|txt)', 'cannedResponse'),
         url_get('^(?P<tid>\d+)/status/(?P<status>\w+)(?:/(?P<sid>\d+))?$', 'changeTicketStatus'),
         url_post('^(?P<tid>\d+)/status$', 'setTicketStatus'),
+        url('^(?P<tid>\d+)/thread/(?P<thread_id>\d+)/create_task$', 'addTask'),
         url('^(?P<tid>\d+)/thread/(?P<thread_id>\d+)/(?P<action>\w+)$', 'triggerThreadAction'),
         url_get('^status/(?P<status>\w+)(?:/(?P<sid>\d+))?$', 'changeSelectedTicketsStatus'),
         url_post('^status/(?P<state>\w+)$', 'setSelectedTicketsStatus'),