feat!: hide Coder Tasks behind the enable-ai-tasks flag (#28008)

This commit is contained in:
david-fraley
2026-08-19 14:46:10 -05:00
committed by GitHub
parent a3eb1ee930
commit 8203b2ebaf
85 changed files with 307 additions and 6030 deletions
+5
View File
@@ -9,6 +9,11 @@ func (r *RootCmd) tasksCommand() *serpent.Command {
Use: "task",
Aliases: []string{"tasks"},
Short: "Manage tasks",
// Coder Tasks is hidden from the product. Hiding the command keeps
// it out of `coder --help` and out of the generated CLI reference
// docs, while leaving it usable on deployments that set
// CODER_ENABLE_AI_TASKS.
Hidden: true,
Handler: func(i *serpent.Invocation) error {
return i.Command.HelpHandler(i)
},
-1
View File
@@ -56,7 +56,6 @@ SUBCOMMANDS:
stop Stop a workspace
support Commands for troubleshooting issues with a Coder
deployment.
task Manage tasks
templates Manage templates
tokens Manage personal access tokens
unfavorite Remove a workspace from your favorites
-3
View File
@@ -290,9 +290,6 @@ Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.
is detected. By default it instructs users to update using 'curl -L
https://coder.com/install.sh | sh'.
--hide-ai-tasks bool, $CODER_HIDE_AI_TASKS (default: false)
Hide AI tasks from the dashboard.
--ssh-config-options string-array, $CODER_SSH_CONFIG_OPTIONS
These SSH config options will override the default SSH config options.
Provide options in "key=value" or "key value" format separated by
-21
View File
@@ -1,21 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task
Manage tasks
Aliases: tasks
SUBCOMMANDS:
create Create a task
delete Delete tasks
list List tasks
logs Show a task's logs
pause Pause a task
resume Resume a task
send Send input to a task
status Show the status of a task.
———
Run `coder --help` for a list of global options.
-51
View File
@@ -1,51 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task create [flags] [input]
Create a task
- Create a task with direct input:
$ coder task create "Add authentication to the user service"
- Create a task with stdin input:
$ echo "Add authentication to the user service" | coder task create
- Create a task with a specific name:
$ coder task create --name task1 "Add authentication to the user service"
- Create a task from a specific template / preset:
$ coder task create --template backend-dev --preset "My Preset" "Add
authentication to the user service"
- Create a task for another user (requires appropriate permissions):
$ coder task create --owner user@example.com "Add authentication to the
user service"
OPTIONS:
-O, --org string, $CODER_ORGANIZATION
Select which organization (uuid or name) to use.
--name string
Specify the name of the task. If you do not specify one, a name will
be generated for you.
--owner string (default: me)
Specify the owner of the task. Defaults to the current user.
--preset string, $CODER_TASK_PRESET_NAME (default: none)
-q, --quiet bool
Only display the created task's ID.
--stdin bool
Reads from stdin for the task input.
--template string, $CODER_TASK_TEMPLATE_NAME
--template-version string, $CODER_TASK_TEMPLATE_VERSION
———
Run `coder --help` for a list of global options.
-27
View File
@@ -1,27 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task delete [flags] <task> [<task> ...]
Delete tasks
Aliases: rm
- Delete a single task.:
$ $ coder task delete task1
- Delete multiple tasks.:
$ $ coder task delete task1 task2 task3
- Delete a task without confirmation.:
$ $ coder task delete task4 --yes
OPTIONS:
-y, --yes bool
Bypass confirmation prompts.
———
Run `coder --help` for a list of global options.
-50
View File
@@ -1,50 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task list [flags]
List tasks
Aliases: ls
- List tasks for the current user.:
$ coder task list
- List tasks for a specific user.:
$ coder task list --user someone-else
- List all tasks you can view.:
$ coder task list --all
- List all your running tasks.:
$ coder task list --status running
- As above, but only show IDs.:
$ coder task list --status running --quiet
OPTIONS:
-a, --all bool (default: false)
List tasks for all users you can view.
-c, --column [id|organization id|owner id|owner name|owner avatar url|name|display name|template id|template version id|template name|template display name|template icon|workspace id|workspace name|workspace status|workspace build number|workspace agent id|workspace agent lifecycle|workspace agent health|workspace app id|initial prompt|status|state|message|created at|updated at|state changed] (default: name,status,state,state changed,message)
Columns to display in table output.
-o, --output table|json (default: table)
Output format.
-q, --quiet bool (default: false)
Only display task IDs.
--status pending|initializing|active|paused|error|unknown
Filter by task status.
--user string
List tasks for the specified user (username, "me").
———
Run `coder --help` for a list of global options.
-20
View File
@@ -1,20 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task logs [flags] <task>
Show a task's logs
- Show logs for a given task.:
$ coder task logs task1
OPTIONS:
-c, --column [id|content|type|time] (default: type,content)
Columns to display in table output.
-o, --output table|json (default: table)
Output format.
———
Run `coder --help` for a list of global options.
-25
View File
@@ -1,25 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task pause [flags] <task>
Pause a task
- Pause a task by name:
$ coder task pause my-task
- Pause another user's task:
$ coder task pause alice/my-task
- Pause a task without confirmation:
$ coder task pause my-task --yes
OPTIONS:
-y, --yes bool
Bypass confirmation prompts.
———
Run `coder --help` for a list of global options.
-28
View File
@@ -1,28 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task resume [flags] <task>
Resume a task
- Resume a task by name:
$ coder task resume my-task
- Resume another user's task:
$ coder task resume alice/my-task
- Resume a task without confirmation:
$ coder task resume my-task --yes
OPTIONS:
--no-wait bool
Return immediately after resuming the task.
-y, --yes bool
Bypass confirmation prompts.
———
Run `coder --help` for a list of global options.
-24
View File
@@ -1,24 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task send [flags] <task> [<input> | --stdin]
Send input to a task
Send input to a task. If the task is paused, it will be automatically resumed
before input is sent. If the task is initializing, it will wait for the task
to become ready.
- Send direct input to a task:
$ coder task send task1 "Please also add unit tests"
- Send input from stdin to a task:
$ echo "Please also add unit tests" | coder task send task1 --stdin
OPTIONS:
--stdin bool
Reads the input from stdin.
———
Run `coder --help` for a list of global options.
-30
View File
@@ -1,30 +0,0 @@
coder v0.0.0-devel
USAGE:
coder task status [flags]
Show the status of a task.
Aliases: stat
- Show the status of a given task.:
$ coder task status task1
- Watch the status of a given task until it completes (idle or stopped).:
$ coder task status task1 --watch
OPTIONS:
-c, --column [id|organization id|owner id|owner name|owner avatar url|name|display name|template id|template version id|template name|template display name|template icon|workspace id|workspace name|workspace status|workspace build number|workspace agent id|workspace agent lifecycle|workspace agent health|workspace app id|initial prompt|status|state|message|created at|updated at|state changed|healthy] (default: state changed,status,healthy,state,message)
Columns to display in table output.
-o, --output table|json (default: table)
Output format.
--watch bool (default: false)
Watch the task status output. This will stream updates to the terminal
until the underlying workspace is stopped.
———
Run `coder --help` for a list of global options.
+1 -1
View File
@@ -6,7 +6,7 @@ USAGE:
Get started with a templated template.
OPTIONS:
--id aws-devcontainer|aws-linux|aws-windows|azure-linux|digitalocean-linux|docker|docker-devcontainer|docker-envbuilder|gcp-devcontainer|gcp-linux|gcp-vm-container|gcp-windows|incus|kubernetes|kubernetes-devcontainer|nomad-docker|quickstart|scratch|tasks-docker
--id aws-devcontainer|aws-linux|aws-windows|azure-linux|digitalocean-linux|docker|docker-devcontainer|docker-envbuilder|gcp-devcontainer|gcp-linux|gcp-vm-container|gcp-windows|incus|kubernetes|kubernetes-devcontainer|nomad-docker|quickstart|scratch
Specify a given example template by ID.
———
+5 -3
View File
@@ -597,9 +597,6 @@ client:
# 'webgl', or 'dom'.
# (default: canvas, type: string)
webTerminalRenderer: canvas
# Hide AI tasks from the dashboard.
# (default: false, type: bool)
hideAITasks: false
# Support links to display in the top right drop down menu.
# (default: <unset>, type: struct[[]codersdk.LinkConfig])
supportLinks: []
@@ -794,6 +791,11 @@ workspace_prebuilds:
# limit; disabled when set to zero.
# (default: 3, type: int)
failure_hard_limit: 3
# Enable Coder Tasks. When unset, the Tasks routes are not served, the Tasks UI
# and its URLs are unavailable, the task RBAC permissions are stripped from
# built-in roles, and the CLI task commands are hidden.
# (default: false, type: bool)
enableAITasks: false
# Configure the background chat processing daemon.
chat:
# How many pending chats a worker should acquire per polling cycle.
+30 -93
View File
@@ -34,16 +34,9 @@ import (
"github.com/coder/coder/v2/codersdk"
)
// @Summary Create a new AI task
// @ID create-a-new-ai-task
// @Security CoderSessionToken
// @Accept json
// @Produce json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param request body codersdk.CreateTaskRequest true "Create task request"
// @Success 201 {object} codersdk.Task
// @Router /api/v2/tasks/{user} [post]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
@@ -421,14 +414,9 @@ func deriveTaskCurrentState(
return currentState
}
// @Summary List AI tasks
// @ID list-ai-tasks
// @Security CoderSessionToken
// @Produce json
// @Tags Tasks
// @Param q query string false "Search query for filtering tasks. Supports: `owner:<username/uuid/me>`, `organization:<org-name/uuid>`, `status:<status>`"
// @Success 200 {object} codersdk.TasksListResponse
// @Router /api/v2/tasks [get]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) tasksList(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
apiKey := httpmw.APIKey(r)
@@ -530,15 +518,9 @@ func (api *API) convertTasks(ctx context.Context, requesterID uuid.UUID, dbTasks
return result, nil
}
// @Summary Get AI task by ID or name
// @ID get-ai-task-by-id-or-name
// @Security CoderSessionToken
// @Produce json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID, or task name"
// @Success 200 {object} codersdk.Task
// @Router /api/v2/tasks/{user}/{task} [get]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
apiKey := httpmw.APIKey(r)
@@ -605,14 +587,9 @@ func (api *API) taskGet(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusOK, taskResp)
}
// @Summary Delete AI task
// @ID delete-ai-task
// @Security CoderSessionToken
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID, or task name"
// @Success 202
// @Router /api/v2/tasks/{user}/{task} [delete]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
apiKey := httpmw.APIKey(r)
@@ -677,16 +654,9 @@ func (api *API) taskDelete(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusAccepted)
}
// @Summary Update AI task input
// @ID update-ai-task-input
// @Security CoderSessionToken
// @Accept json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID, or task name"
// @Param request body codersdk.UpdateTaskInputRequest true "Update task input request"
// @Success 204
// @Router /api/v2/tasks/{user}/{task}/input [patch]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) taskUpdateInput(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
@@ -757,16 +727,9 @@ func (api *API) taskUpdateInput(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusNoContent, nil)
}
// @Summary Send input to AI task
// @ID send-input-to-ai-task
// @Security CoderSessionToken
// @Accept json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID, or task name"
// @Param request body codersdk.TaskSendRequest true "Task input request"
// @Success 204
// @Router /api/v2/tasks/{user}/{task}/send [post]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) taskSend(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
task := httpmw.TaskParam(r)
@@ -850,15 +813,9 @@ func convertAgentAPIMessagesToLogEntries(messages []agentapisdk.Message) ([]code
return logs, nil
}
// @Summary Get AI task logs
// @ID get-ai-task-logs
// @Security CoderSessionToken
// @Produce json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID, or task name"
// @Success 200 {object} codersdk.TaskLogsResponse
// @Router /api/v2/tasks/{user}/{task}/logs [get]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) taskLogs(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
task := httpmw.TaskParam(r)
@@ -1129,17 +1086,9 @@ type TaskLogSnapshotEnvelope struct {
Data any `json:"data"`
}
// @Summary Upload task log snapshot
// @ID upload-task-log-snapshot
// @Security CoderSessionToken
// @Accept json
// @Tags Tasks
// @Param task path string true "Task ID" format(uuid)
// @Param format query string true "Snapshot format" enums(agentapi)
// @Param request body object true "Raw snapshot payload (structure depends on format parameter)"
// @Success 204
// @Failure 413 {object} codersdk.Response "Request body exceeds 64 KiB"
// @Router /api/v2/workspaceagents/me/tasks/{task}/log-snapshot [post]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) postWorkspaceAgentTaskLogSnapshot(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
@@ -1275,15 +1224,9 @@ func (api *API) postWorkspaceAgentTaskLogSnapshot(rw http.ResponseWriter, r *htt
rw.WriteHeader(http.StatusNoContent)
}
// @Summary Pause task
// @ID pause-task
// @Security CoderSessionToken
// @Produce json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID" format(uuid)
// @Success 202 {object} codersdk.PauseTaskResponse
// @Router /api/v2/tasks/{user}/{task}/pause [post]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) pauseTask(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
@@ -1352,15 +1295,9 @@ func (api *API) pauseTask(rw http.ResponseWriter, r *http.Request) {
})
}
// @Summary Resume task
// @ID resume-task
// @Security CoderSessionToken
// @Produce json
// @Tags Tasks
// @Param user path string true "Username, user ID, or 'me' for the authenticated user"
// @Param task path string true "Task ID" format(uuid)
// @Success 202 {object} codersdk.ResumeTaskResponse
// @Router /api/v2/tasks/{user}/{task}/resume [post]
// Deprecated: Coder Tasks is deprecated as of v2.36. This route is only
// registered when CODER_ENABLE_AI_TASKS is set, and is planned for removal in
// v2.37.
func (api *API) resumeTask(rw http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
+48
View File
@@ -0,0 +1,48 @@
package coderd_test
import (
"net/http"
"testing"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/testutil"
)
// TestTasksDisabled asserts that a deployment without CODER_ENABLE_AI_TASKS
// serves no Tasks routes, on either the stable or the experimental prefix.
func TestTasksDisabled(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
values := coderdtest.DeploymentValues(t)
values.EnableAITasks = false
client := coderdtest.New(t, &coderdtest.Options{DeploymentValues: values})
coderdtest.CreateFirstUser(t, client)
// Only the user-facing routes are asserted here. The agent-side
// /workspaceagents/me/tasks route is also gated, but it sits behind agent
// authentication, so a user token cannot tell a missing route from a
// rejected one. TestEndpointsDocumented covers its absence, since an
// undocumented registered route fails that test.
for _, route := range []string{
"/api/v2/tasks",
"/api/v2/tasks/me",
"/api/experimental/tasks",
"/api/experimental/tasks/me",
} {
res, err := client.Request(ctx, http.MethodGet, route, nil)
require.NoError(t, err)
_ = res.Body.Close()
require.Equal(t, http.StatusNotFound, res.StatusCode, "route %s should not be registered", route)
}
// Sanity check that unrelated routes still work, so the assertions above
// are not passing because the whole API is broken.
res, err := client.Request(ctx, http.MethodGet, "/api/v2/workspaces", nil)
require.NoError(t, err)
_ = res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
}
+3 -728
View File
@@ -8130,378 +8130,6 @@ const docTemplate = `{
]
}
},
"/api/v2/tasks": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "List AI tasks",
"operationId": "list-ai-tasks",
"parameters": [
{
"type": "string",
"description": "Search query for filtering tasks. Supports: ` + "`" + `owner:\u003cusername/uuid/me\u003e` + "`" + `, ` + "`" + `organization:\u003corg-name/uuid\u003e` + "`" + `, ` + "`" + `status:\u003cstatus\u003e` + "`" + `",
"name": "q",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.TasksListResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}": {
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Create a new AI task",
"operationId": "create-a-new-ai-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"description": "Create task request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.CreateTaskRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/codersdk.Task"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Get AI task by ID or name",
"operationId": "get-ai-task-by-id-or-name",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.Task"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"delete": {
"tags": [
"Tasks"
],
"summary": "Delete AI task",
"operationId": "delete-ai-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "Accepted"
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/input": {
"patch": {
"consumes": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Update AI task input",
"operationId": "update-ai-task-input",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
},
{
"description": "Update task input request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.UpdateTaskInputRequest"
}
}
],
"responses": {
"204": {
"description": "No Content"
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/logs": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Get AI task logs",
"operationId": "get-ai-task-logs",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.TaskLogsResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/pause": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Pause task",
"operationId": "pause-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"format": "uuid",
"description": "Task ID",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/codersdk.PauseTaskResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/resume": {
"post": {
"produces": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Resume task",
"operationId": "resume-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"format": "uuid",
"description": "Task ID",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/codersdk.ResumeTaskResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/send": {
"post": {
"consumes": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Send input to AI task",
"operationId": "send-input-to-ai-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
},
{
"description": "Task input request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.TaskSendRequest"
}
}
],
"responses": {
"204": {
"description": "No Content"
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/templatebuilder/bases": {
"get": {
"produces": [
@@ -12954,63 +12582,6 @@ const docTemplate = `{
}
}
},
"/api/v2/workspaceagents/me/tasks/{task}/log-snapshot": {
"post": {
"consumes": [
"application/json"
],
"tags": [
"Tasks"
],
"summary": "Upload task log snapshot",
"operationId": "upload-task-log-snapshot",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "Task ID",
"name": "task",
"in": "path",
"required": true
},
{
"enum": [
"agentapi"
],
"type": "string",
"description": "Snapshot format",
"name": "format",
"in": "query",
"required": true
},
{
"description": "Raw snapshot payload (structure depends on format parameter)",
"name": "request",
"in": "body",
"required": true,
"schema": {
"type": "object"
}
}
],
"responses": {
"204": {
"description": "No Content"
},
"413": {
"description": "Request body exceeds 64 KiB",
"schema": {
"$ref": "#/definitions/codersdk.Response"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/workspaceagents/{workspaceagent}": {
"get": {
"produces": [
@@ -19956,28 +19527,6 @@ const docTemplate = `{
}
}
},
"codersdk.CreateTaskRequest": {
"type": "object",
"properties": {
"display_name": {
"type": "string"
},
"input": {
"type": "string"
},
"name": {
"type": "string"
},
"template_version_id": {
"type": "string",
"format": "uuid"
},
"template_version_preset_id": {
"type": "string",
"format": "uuid"
}
}
},
"codersdk.CreateTemplateRequest": {
"type": "object",
"required": [
@@ -20906,6 +20455,9 @@ const docTemplate = `{
"docs_url": {
"$ref": "#/definitions/serpent.URL"
},
"enable_ai_tasks": {
"type": "boolean"
},
"enable_authz_recording": {
"type": "boolean"
},
@@ -20936,9 +20488,6 @@ const docTemplate = `{
"healthcheck": {
"$ref": "#/definitions/codersdk.HealthcheckConfig"
},
"hide_ai_tasks": {
"type": "boolean"
},
"http_address": {
"description": "HTTPAddress is a string because it may be set to zero to disable.",
"type": "string"
@@ -23994,14 +23543,6 @@ const docTemplate = `{
}
}
},
"codersdk.PauseTaskResponse": {
"type": "object",
"properties": {
"workspace_build": {
"$ref": "#/definitions/codersdk.WorkspaceBuild"
}
}
},
"codersdk.Permission": {
"type": "object",
"properties": {
@@ -25219,14 +24760,6 @@ const docTemplate = `{
}
}
},
"codersdk.ResumeTaskResponse": {
"type": "object",
"properties": {
"workspace_build": {
"$ref": "#/definitions/codersdk.WorkspaceBuild"
}
}
},
"codersdk.RetentionConfig": {
"type": "object",
"properties": {
@@ -25570,256 +25103,6 @@ const docTemplate = `{
}
}
},
"codersdk.Task": {
"type": "object",
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"current_state": {
"$ref": "#/definitions/codersdk.TaskStateEntry"
},
"display_name": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"initial_prompt": {
"type": "string"
},
"name": {
"type": "string"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"owner_avatar_url": {
"type": "string"
},
"owner_id": {
"type": "string",
"format": "uuid"
},
"owner_name": {
"type": "string"
},
"status": {
"enum": [
"pending",
"initializing",
"active",
"paused",
"unknown",
"error"
],
"allOf": [
{
"$ref": "#/definitions/codersdk.TaskStatus"
}
]
},
"template_display_name": {
"type": "string"
},
"template_icon": {
"type": "string"
},
"template_id": {
"type": "string",
"format": "uuid"
},
"template_name": {
"type": "string"
},
"template_version_id": {
"type": "string",
"format": "uuid"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"workspace_agent_health": {
"$ref": "#/definitions/codersdk.WorkspaceAgentHealth"
},
"workspace_agent_id": {
"format": "uuid",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"workspace_agent_lifecycle": {
"$ref": "#/definitions/codersdk.WorkspaceAgentLifecycle"
},
"workspace_app_id": {
"format": "uuid",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"workspace_build_number": {
"type": "integer"
},
"workspace_id": {
"format": "uuid",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"workspace_name": {
"type": "string"
},
"workspace_status": {
"enum": [
"pending",
"starting",
"running",
"stopping",
"stopped",
"failed",
"canceling",
"canceled",
"deleting",
"deleted"
],
"allOf": [
{
"$ref": "#/definitions/codersdk.WorkspaceStatus"
}
]
}
}
},
"codersdk.TaskLogEntry": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"id": {
"type": "integer"
},
"time": {
"type": "string",
"format": "date-time"
},
"type": {
"$ref": "#/definitions/codersdk.TaskLogType"
}
}
},
"codersdk.TaskLogType": {
"type": "string",
"enum": [
"input",
"output"
],
"x-enum-varnames": [
"TaskLogTypeInput",
"TaskLogTypeOutput"
]
},
"codersdk.TaskLogsResponse": {
"type": "object",
"properties": {
"logs": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.TaskLogEntry"
}
},
"snapshot": {
"type": "boolean"
},
"snapshot_at": {
"type": "string"
}
}
},
"codersdk.TaskSendRequest": {
"type": "object",
"properties": {
"input": {
"type": "string"
}
}
},
"codersdk.TaskState": {
"type": "string",
"enum": [
"working",
"idle",
"complete",
"failed"
],
"x-enum-varnames": [
"TaskStateWorking",
"TaskStateIdle",
"TaskStateComplete",
"TaskStateFailed"
]
},
"codersdk.TaskStateEntry": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"state": {
"$ref": "#/definitions/codersdk.TaskState"
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"uri": {
"type": "string"
}
}
},
"codersdk.TaskStatus": {
"type": "string",
"enum": [
"pending",
"initializing",
"active",
"paused",
"unknown",
"error"
],
"x-enum-varnames": [
"TaskStatusPending",
"TaskStatusInitializing",
"TaskStatusActive",
"TaskStatusPaused",
"TaskStatusUnknown",
"TaskStatusError"
]
},
"codersdk.TasksListResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"tasks": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.Task"
}
}
}
},
"codersdk.TelemetryConfig": {
"type": "object",
"properties": {
@@ -27315,14 +26598,6 @@ const docTemplate = `{
}
}
},
"codersdk.UpdateTaskInputRequest": {
"type": "object",
"properties": {
"input": {
"type": "string"
}
}
},
"codersdk.UpdateTemplateACL": {
"type": "object",
"properties": {
+3 -675
View File
@@ -7233,342 +7233,6 @@
]
}
},
"/api/v2/tasks": {
"get": {
"produces": ["application/json"],
"tags": ["Tasks"],
"summary": "List AI tasks",
"operationId": "list-ai-tasks",
"parameters": [
{
"type": "string",
"description": "Search query for filtering tasks. Supports: `owner:\u003cusername/uuid/me\u003e`, `organization:\u003corg-name/uuid\u003e`, `status:\u003cstatus\u003e`",
"name": "q",
"in": "query"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.TasksListResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}": {
"post": {
"consumes": ["application/json"],
"produces": ["application/json"],
"tags": ["Tasks"],
"summary": "Create a new AI task",
"operationId": "create-a-new-ai-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"description": "Create task request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.CreateTaskRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/codersdk.Task"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}": {
"get": {
"produces": ["application/json"],
"tags": ["Tasks"],
"summary": "Get AI task by ID or name",
"operationId": "get-ai-task-by-id-or-name",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.Task"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"delete": {
"tags": ["Tasks"],
"summary": "Delete AI task",
"operationId": "delete-ai-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "Accepted"
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/input": {
"patch": {
"consumes": ["application/json"],
"tags": ["Tasks"],
"summary": "Update AI task input",
"operationId": "update-ai-task-input",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
},
{
"description": "Update task input request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.UpdateTaskInputRequest"
}
}
],
"responses": {
"204": {
"description": "No Content"
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/logs": {
"get": {
"produces": ["application/json"],
"tags": ["Tasks"],
"summary": "Get AI task logs",
"operationId": "get-ai-task-logs",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.TaskLogsResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/pause": {
"post": {
"produces": ["application/json"],
"tags": ["Tasks"],
"summary": "Pause task",
"operationId": "pause-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"format": "uuid",
"description": "Task ID",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/codersdk.PauseTaskResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/resume": {
"post": {
"produces": ["application/json"],
"tags": ["Tasks"],
"summary": "Resume task",
"operationId": "resume-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"format": "uuid",
"description": "Task ID",
"name": "task",
"in": "path",
"required": true
}
],
"responses": {
"202": {
"description": "Accepted",
"schema": {
"$ref": "#/definitions/codersdk.ResumeTaskResponse"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/tasks/{user}/{task}/send": {
"post": {
"consumes": ["application/json"],
"tags": ["Tasks"],
"summary": "Send input to AI task",
"operationId": "send-input-to-ai-task",
"parameters": [
{
"type": "string",
"description": "Username, user ID, or 'me' for the authenticated user",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Task ID, or task name",
"name": "task",
"in": "path",
"required": true
},
{
"description": "Task input request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.TaskSendRequest"
}
}
],
"responses": {
"204": {
"description": "No Content"
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/templatebuilder/bases": {
"get": {
"produces": ["application/json"],
@@ -11511,57 +11175,6 @@
}
}
},
"/api/v2/workspaceagents/me/tasks/{task}/log-snapshot": {
"post": {
"consumes": ["application/json"],
"tags": ["Tasks"],
"summary": "Upload task log snapshot",
"operationId": "upload-task-log-snapshot",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "Task ID",
"name": "task",
"in": "path",
"required": true
},
{
"enum": ["agentapi"],
"type": "string",
"description": "Snapshot format",
"name": "format",
"in": "query",
"required": true
},
{
"description": "Raw snapshot payload (structure depends on format parameter)",
"name": "request",
"in": "body",
"required": true,
"schema": {
"type": "object"
}
}
],
"responses": {
"204": {
"description": "No Content"
},
"413": {
"description": "Request body exceeds 64 KiB",
"schema": {
"$ref": "#/definitions/codersdk.Response"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/api/v2/workspaceagents/{workspaceagent}": {
"get": {
"produces": ["application/json"],
@@ -18065,28 +17678,6 @@
}
}
},
"codersdk.CreateTaskRequest": {
"type": "object",
"properties": {
"display_name": {
"type": "string"
},
"input": {
"type": "string"
},
"name": {
"type": "string"
},
"template_version_id": {
"type": "string",
"format": "uuid"
},
"template_version_preset_id": {
"type": "string",
"format": "uuid"
}
}
},
"codersdk.CreateTemplateRequest": {
"type": "object",
"required": ["name", "template_version_id"],
@@ -18976,6 +18567,9 @@
"docs_url": {
"$ref": "#/definitions/serpent.URL"
},
"enable_ai_tasks": {
"type": "boolean"
},
"enable_authz_recording": {
"type": "boolean"
},
@@ -19006,9 +18600,6 @@
"healthcheck": {
"$ref": "#/definitions/codersdk.HealthcheckConfig"
},
"hide_ai_tasks": {
"type": "boolean"
},
"http_address": {
"description": "HTTPAddress is a string because it may be set to zero to disable.",
"type": "string"
@@ -21961,14 +21552,6 @@
}
}
},
"codersdk.PauseTaskResponse": {
"type": "object",
"properties": {
"workspace_build": {
"$ref": "#/definitions/codersdk.WorkspaceBuild"
}
}
},
"codersdk.Permission": {
"type": "object",
"properties": {
@@ -23138,14 +22721,6 @@
}
}
},
"codersdk.ResumeTaskResponse": {
"type": "object",
"properties": {
"workspace_build": {
"$ref": "#/definitions/codersdk.WorkspaceBuild"
}
}
},
"codersdk.RetentionConfig": {
"type": "object",
"properties": {
@@ -23471,245 +23046,6 @@
}
}
},
"codersdk.Task": {
"type": "object",
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"current_state": {
"$ref": "#/definitions/codersdk.TaskStateEntry"
},
"display_name": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"initial_prompt": {
"type": "string"
},
"name": {
"type": "string"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"owner_avatar_url": {
"type": "string"
},
"owner_id": {
"type": "string",
"format": "uuid"
},
"owner_name": {
"type": "string"
},
"status": {
"enum": [
"pending",
"initializing",
"active",
"paused",
"unknown",
"error"
],
"allOf": [
{
"$ref": "#/definitions/codersdk.TaskStatus"
}
]
},
"template_display_name": {
"type": "string"
},
"template_icon": {
"type": "string"
},
"template_id": {
"type": "string",
"format": "uuid"
},
"template_name": {
"type": "string"
},
"template_version_id": {
"type": "string",
"format": "uuid"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"workspace_agent_health": {
"$ref": "#/definitions/codersdk.WorkspaceAgentHealth"
},
"workspace_agent_id": {
"format": "uuid",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"workspace_agent_lifecycle": {
"$ref": "#/definitions/codersdk.WorkspaceAgentLifecycle"
},
"workspace_app_id": {
"format": "uuid",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"workspace_build_number": {
"type": "integer"
},
"workspace_id": {
"format": "uuid",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"workspace_name": {
"type": "string"
},
"workspace_status": {
"enum": [
"pending",
"starting",
"running",
"stopping",
"stopped",
"failed",
"canceling",
"canceled",
"deleting",
"deleted"
],
"allOf": [
{
"$ref": "#/definitions/codersdk.WorkspaceStatus"
}
]
}
}
},
"codersdk.TaskLogEntry": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"id": {
"type": "integer"
},
"time": {
"type": "string",
"format": "date-time"
},
"type": {
"$ref": "#/definitions/codersdk.TaskLogType"
}
}
},
"codersdk.TaskLogType": {
"type": "string",
"enum": ["input", "output"],
"x-enum-varnames": ["TaskLogTypeInput", "TaskLogTypeOutput"]
},
"codersdk.TaskLogsResponse": {
"type": "object",
"properties": {
"logs": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.TaskLogEntry"
}
},
"snapshot": {
"type": "boolean"
},
"snapshot_at": {
"type": "string"
}
}
},
"codersdk.TaskSendRequest": {
"type": "object",
"properties": {
"input": {
"type": "string"
}
}
},
"codersdk.TaskState": {
"type": "string",
"enum": ["working", "idle", "complete", "failed"],
"x-enum-varnames": [
"TaskStateWorking",
"TaskStateIdle",
"TaskStateComplete",
"TaskStateFailed"
]
},
"codersdk.TaskStateEntry": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"state": {
"$ref": "#/definitions/codersdk.TaskState"
},
"timestamp": {
"type": "string",
"format": "date-time"
},
"uri": {
"type": "string"
}
}
},
"codersdk.TaskStatus": {
"type": "string",
"enum": [
"pending",
"initializing",
"active",
"paused",
"unknown",
"error"
],
"x-enum-varnames": [
"TaskStatusPending",
"TaskStatusInitializing",
"TaskStatusActive",
"TaskStatusPaused",
"TaskStatusUnknown",
"TaskStatusError"
]
},
"codersdk.TasksListResponse": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"tasks": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.Task"
}
}
}
},
"codersdk.TelemetryConfig": {
"type": "object",
"properties": {
@@ -25117,14 +24453,6 @@
}
}
},
"codersdk.UpdateTaskInputRequest": {
"type": "object",
"properties": {
"input": {
"type": "string"
}
}
},
"codersdk.UpdateTemplateACL": {
"type": "object",
"properties": {
+51 -36
View File
@@ -785,7 +785,7 @@ func New(options *Options) *API {
Entitlements: options.Entitlements,
Telemetry: options.Telemetry,
Logger: options.Logger.Named("site"),
HideAITasks: options.DeploymentValues.HideAITasks.Value(),
AITasksEnabled: options.DeploymentValues.EnableAITasks.Value(),
AIGatewayEnabled: options.DeploymentValues.AI.BridgeConfig.Enabled.Value(),
})
if err != nil {
@@ -1329,27 +1329,33 @@ func New(options *Options) *API {
// NOTE(DanielleMaywood):
// Tasks have been promoted to stable, but we have guaranteed a single release transition period
// where these routes must remain. These should be removed no earlier than Coder v2.30.0
r.Route("/tasks", func(r chi.Router) {
r.Use(apiKeyMiddleware)
//
// Coder Tasks is hidden unless the deployment opts in, so the routes are
// only registered when CODER_ENABLE_AI_TASKS is set. Requests to an
// unregistered path fall through to the route not found handler above.
if options.DeploymentValues.EnableAITasks {
r.Route("/tasks", func(r chi.Router) {
r.Use(apiKeyMiddleware)
r.Get("/", api.tasksList)
r.Get("/", api.tasksList)
r.Route("/{user}", func(r chi.Router) {
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database, api.HTTPAuth.Authorize))
r.Post("/", api.tasksCreate)
r.Route("/{user}", func(r chi.Router) {
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database, api.HTTPAuth.Authorize))
r.Post("/", api.tasksCreate)
r.Route("/{task}", func(r chi.Router) {
r.Use(httpmw.ExtractTaskParam(options.Database))
r.Get("/", api.taskGet)
r.Delete("/", api.taskDelete)
r.Patch("/input", api.taskUpdateInput)
r.Post("/send", api.taskSend)
r.Get("/logs", api.taskLogs)
r.Post("/pause", api.pauseTask)
r.Post("/resume", api.resumeTask)
r.Route("/{task}", func(r chi.Router) {
r.Use(httpmw.ExtractTaskParam(options.Database))
r.Get("/", api.taskGet)
r.Delete("/", api.taskDelete)
r.Patch("/input", api.taskUpdateInput)
r.Post("/send", api.taskSend)
r.Get("/logs", api.taskLogs)
r.Post("/pause", api.pauseTask)
r.Post("/resume", api.resumeTask)
})
})
})
})
}
r.Route("/users/{user}/skills", func(r chi.Router) {
r.Use(
apiKeyMiddleware,
@@ -1933,9 +1939,13 @@ func New(options *Options) *API {
r.Route("/experimental", func(r chi.Router) {
r.Post("/chat-context/refresh", api.workspaceAgentRefreshChatContext)
})
r.Route("/tasks/{task}", func(r chi.Router) {
r.Post("/log-snapshot", api.postWorkspaceAgentTaskLogSnapshot)
})
// Agent-side Coder Tasks reporting, registered only when the
// deployment opts in, for the same reason as the /tasks trees.
if options.DeploymentValues.EnableAITasks {
r.Route("/tasks/{task}", func(r chi.Router) {
r.Post("/log-snapshot", api.postWorkspaceAgentTaskLogSnapshot)
})
}
})
r.Route("/{workspaceagent}", func(r chi.Router) {
r.Use(
@@ -2205,27 +2215,32 @@ func New(options *Options) *API {
r.Get("/{os}/{arch}", api.initScript)
})
r.Route("/ai/providers", aiProvidersHandler(api, apiKeyMiddleware))
r.Route("/tasks", func(r chi.Router) {
r.Use(apiKeyMiddleware)
// Coder Tasks is hidden unless the deployment opts in, so the routes are
// only registered when CODER_ENABLE_AI_TASKS is set. Requests to an
// unregistered path fall through to the route not found handler above.
if options.DeploymentValues.EnableAITasks {
r.Route("/tasks", func(r chi.Router) {
r.Use(apiKeyMiddleware)
r.Get("/", api.tasksList)
r.Get("/", api.tasksList)
r.Route("/{user}", func(r chi.Router) {
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database, api.HTTPAuth.Authorize))
r.Post("/", api.tasksCreate)
r.Route("/{user}", func(r chi.Router) {
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database, api.HTTPAuth.Authorize))
r.Post("/", api.tasksCreate)
r.Route("/{task}", func(r chi.Router) {
r.Use(httpmw.ExtractTaskParam(options.Database))
r.Get("/", api.taskGet)
r.Delete("/", api.taskDelete)
r.Patch("/input", api.taskUpdateInput)
r.Post("/send", api.taskSend)
r.Get("/logs", api.taskLogs)
r.Post("/pause", api.pauseTask)
r.Post("/resume", api.resumeTask)
r.Route("/{task}", func(r chi.Router) {
r.Use(httpmw.ExtractTaskParam(options.Database))
r.Get("/", api.taskGet)
r.Delete("/", api.taskDelete)
r.Patch("/input", api.taskUpdateInput)
r.Post("/send", api.taskSend)
r.Get("/logs", api.taskLogs)
r.Post("/pause", api.pauseTask)
r.Post("/resume", api.resumeTask)
})
})
})
})
}
})
if options.SwaggerEndpoint {
+4
View File
@@ -1866,6 +1866,10 @@ func DeploymentValues(t testing.TB, mut ...func(*codersdk.DeploymentValues)) *co
opts := cfg.Options()
err := opts.SetDefaults()
require.NoError(t, err)
// Tasks ship disabled. Tests exercise the enabled behavior by default so
// the Tasks suite keeps running; tests for the disabled path opt out
// explicitly via the mutators.
cfg.EnableAITasks = true
for _, fn := range mut {
fn(cfg)
}
+7 -1
View File
@@ -20,7 +20,13 @@ func TestEndpointsDocumented(t *testing.T) {
require.NoError(t, err, "can't parse swagger comments")
require.NotEmpty(t, swaggerComments, "swagger comments must be present")
_, _, api := coderdtest.NewWithAPI(t, nil)
// Coder Tasks has no swagger annotations because it is withdrawn from the
// product, so verify against a deployment where its routes are not
// registered.
values := coderdtest.DeploymentValues(t)
values.EnableAITasks = false
_, _, api := coderdtest.NewWithAPI(t, &coderdtest.Options{DeploymentValues: values})
coderdtest.VerifySwaggerDefinitions(t, api.APIHandler, swaggerComments, coderdtest.WithSwaggerRoutePrefix("/api/v2"))
}
+11 -8
View File
@@ -749,7 +749,7 @@ type DeploymentValues struct {
AdditionalCSPPolicy serpent.StringArray `json:"additional_csp_policy,omitempty" typescript:",notnull"`
WorkspaceHostnameSuffix serpent.String `json:"workspace_hostname_suffix,omitempty" typescript:",notnull"`
Prebuilds PrebuildsConfig `json:"workspace_prebuilds,omitempty" typescript:",notnull"`
HideAITasks serpent.Bool `json:"hide_ai_tasks,omitempty" typescript:",notnull"`
EnableAITasks serpent.Bool `json:"enable_ai_tasks,omitempty" typescript:",notnull"`
AI AIConfig `json:"ai,omitempty"`
StatsCollection StatsCollectionConfig `json:"stats_collection,omitempty" typescript:",notnull"`
TemplateBuilder TemplateBuilderConfig `json:"template_builder,omitempty"`
@@ -4320,14 +4320,17 @@ Write out the current server config as YAML to stdout.`,
Hidden: true,
},
{
Name: "Hide AI Tasks",
Description: "Hide AI tasks from the dashboard.",
Flag: "hide-ai-tasks",
Env: "CODER_HIDE_AI_TASKS",
Name: "Enable AI Tasks",
Description: "Enable Coder Tasks. When unset, the Tasks routes are not served, the Tasks UI and its URLs are unavailable, the task RBAC permissions are stripped from built-in roles, and the CLI task commands are hidden.",
Flag: "enable-ai-tasks",
Env: "CODER_ENABLE_AI_TASKS",
Default: "false",
Value: &c.HideAITasks,
Group: &deploymentGroupClient,
YAML: "hideAITasks",
Value: &c.EnableAITasks,
YAML: "enableAITasks",
// Hidden keeps Tasks out of the generated CLI and configuration
// reference documentation while the feature is withdrawn from the
// product.
Hidden: true,
},
// Chat Options
{
@@ -503,15 +503,6 @@ The upgrade message to display to users when a client/server mismatch is detecte
- CLI flag: [`--cli-upgrade-message`](../../reference/cli/server.md#--cli-upgrade-message)
- YAML key: `client.cliUpgradeMessage`
### Hide AI tasks
Hide AI tasks from the dashboard.
- Environment variable: `CODER_HIDE_AI_TASKS`
- CLI flag: [`--hide-ai-tasks`](../../reference/cli/server.md#--hide-ai-tasks)
- YAML key: `client.hideAITasks`
- Default value: `false`
### SSH config options
These SSH config options will override the default SSH config options. Provide options in "key=value" or "key value" format separated by commas. Using this incorrectly can break SSH to your deployment, use cautiously. The following options are not allowed: Host, Match, Include, ProxyCommand, ProxyJump, LocalCommand, PermitLocalCommand, RemoteCommand, KnownHostsCommand, PKCS11Provider, SecurityKeyProvider, SmartcardDevice, XAuthLocation. Option values must not contain newline, carriage return, or NUL characters.
-99
View File
@@ -1,99 +0,0 @@
# Agent compatibility
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
Coder Tasks works with a range of AI coding agents, each with different levels
of support for preserving conversation context across pause and resume cycles.
This page covers which agents support resume, what session data they store,
and what to watch out for when configuring persistent storage.
## Compatibility levels
Agents with **full support** automatically resume the previous session when a
task resumes. The conversation history, tool calls, and context are all
preserved, so the agent picks up exactly where it left off.
Agents with **partial support** have resume wiring in the module but it is
either off by default or has known bugs. A module update is needed before resume
works reliably. See the linked tracking issue for details.
Agents with **planned support** have native session persistence but the registry
module does not wire it yet. These agents start a fresh conversation on each
resume until the module is updated.
Agents marked **not supported** cannot resume a previous session. They start a
fresh conversation on each resume, even if some chat history is visible in the
UI.
## Compatibility matrix
| Agent | Module | Min version | Support | Tracking | Session data paths | Min storage |
|-----------------|----------------------------------------------------------------------------------|-------------|---------------|--------------------------------------------------------------|------------------------------------------------------|---------------------------|
| Claude Code | [claude-code](https://registry.coder.com/modules/coder/claude-code) | >= 4.8.0 | Full | - | `~/.claude/` | 100 MB (can grow to GB) |
| Codex | [codex](https://registry.coder.com/modules/coder-labs/codex) | >= 4.2.0 | Full | - | `~/.codex/`, `~/.codex-module/` | 100 MB |
| Copilot | [copilot](https://registry.coder.com/modules/coder-labs/copilot) | - | Partial | [registry#741](https://github.com/coder/registry/issues/741) | `~/.copilot/` | 50 MB |
| OpenCode | [opencode](https://registry.coder.com/modules/coder-labs/opencode) | - | Partial | [registry#742](https://github.com/coder/registry/issues/742) | `~/.local/share/opencode/`, `~/.config/opencode/` | 50 MB |
| Auggie | [auggie](https://registry.coder.com/modules/coder-labs/auggie) | - | Planned | [registry#743](https://github.com/coder/registry/issues/743) | `~/.augment/` | 50 MB |
| Goose | [goose](https://registry.coder.com/modules/coder/goose) | - | Planned | [registry#744](https://github.com/coder/registry/issues/744) | `~/.local/share/goose/sessions/`, `~/.config/goose/` | 50 MB |
| Amazon Q | [amazon-q](https://registry.coder.com/modules/coder/amazon-q) | - | Planned | [registry#746](https://github.com/coder/registry/issues/746) | `~/.local/share/amazon-q/`, `~/.aws/amazonq/` | 50 MB |
| Gemini | [gemini](https://registry.coder.com/modules/coder-labs/gemini) | - | Planned | [registry#745](https://github.com/coder/registry/issues/745) | `~/.gemini/` | 200 MB (can reach 400 MB) |
| Cursor CLI | [cursor-cli](https://registry.coder.com/modules/coder-labs/cursor-cli) | - | Planned | [registry#747](https://github.com/coder/registry/issues/747) | `~/.cursor/` | 50 MB |
| Sourcegraph Amp | [sourcegraph-amp](https://registry.coder.com/modules/coder-labs/sourcegraph-amp) | - | Planned | [registry#748](https://github.com/coder/registry/issues/748) | `~/.config/amp/` (config only) | 10 MB |
| Aider | [aider](https://registry.coder.com/modules/coder/aider) | - | Not supported | [registry#739](https://github.com/coder/registry/issues/739) | `.aider.chat.history.md` (workdir) | 50 MB |
## Persistent storage
Every agent's session data lives under the home directory, so persisting the
home directory with a volume mount is the simplest way to cover all agents at
once. This also preserves the AgentAPI state file that Coder uses to stream chat
content between the agent and the Tasks UI.
See
[Resource persistence](../admin/templates/extending-templates/resource-persistence.md)
for configuration patterns.
## Agent-specific notes
**Claude Code**: Session files are JSONL and grow unbounded. Long-running
tasks can accumulate multiple gigabytes of data in `~/.claude/projects/`.
Monitor disk usage and consider periodic cleanup.
**Goose**: Sessions are stored in a SQLite database with WAL mode enabled. You
must preserve the `-wal` and `-shm` sidecar files alongside the main database,
or the session database may become corrupted.
**Amazon Q**: The Amazon Q Developer CLI has been rebranded to Kiro CLI. The
existing module pins a specific CLI version. An authentication tarball is stored
alongside session data; if it is lost, the agent must re-authenticate.
**Gemini**: Session data can reach 400 MB for long-running tasks. You can set
the `general.sessionRetention` configuration value to control how long sessions
are retained.
**Sourcegraph Amp**: Conversation threads are stored server-side on
Sourcegraph servers, so only local configuration in `~/.config/amp/` needs
persistence. The workspace must have network connectivity to Sourcegraph for
resume to work.
**Auggie**: May require connectivity to the Augment cloud backend for session
resume. Behavior in fully headless or network-restricted environments is not
fully verified.
**Aider**: The `--restore-chat-history` flag performs a lossy reconstruction
from a Markdown log file, but the agent loses full conversation context on each
restart and does not support MCP for status reporting. When
`enable_state_persistence` is enabled in the module, the Coder UI preserves chat
history across pause and resume, but Aider itself starts each session fresh with no
memory of previous conversations.
## Next steps
- [Task lifecycle](./tasks-lifecycle.md) for how pause and resume work and
what your template needs.
- [Set up Coder Tasks](./tasks.md) in your template.
- [Build a custom agent](./custom-agents.md) with MCP support.
-15
View File
@@ -306,18 +306,3 @@ While plan mode is active:
This keeps planning turns focused on analysis and plan authoring rather than
implementation. Once you click **Implement plan**, the next turn runs in normal
mode again.
## Comparison to Coder Tasks
Coder Agents is a new approach that differs from
[Coder Tasks](../tasks.md) in several ways:
| Aspect | Coder Agents | Coder Tasks |
|---------------------|--------------------------------------|----------------------------------------------------------------|
| Agent execution | Runs in the control plane | Runs inside the workspace |
| Agent harness | Built-in, no installation needed | Requires Claude Code, Codex, or similar installed in workspace |
| API keys | Stored in control plane only | Injected into workspace environment |
| Chat state | Persisted in database | Stored in workspace |
| Workspace selection | Automatic, based on task description | Manual, user selects template |
| Sub-agents | Built-in parallel delegation | Not supported |
| Modern chat UI | Native chat with diffs, queuing | Terminal-based interface |
@@ -1,6 +1,12 @@
# Migrating from the Tasks API to the Chats API
The [Tasks API](../../reference/api/tasks.md) (`/api/v2/tasks`) and the
> [!WARNING]
> Coder Tasks is deprecated as of Coder v2.36 and is no longer available by
> default. Coder Tasks product and API reference documentation is no longer
> published in the current documentation. To read about Coder Tasks, use a
> previous version of the Coder documentation, from a release before v2.36.
The Tasks API (`/api/v2/tasks`) and the
[Chats API](../../reference/api/chats.md) (`/api/v2/chats`) serve similar
goals (programmatic access to AI-powered coding agents) but they differ
significantly in architecture, capabilities, and usage patterns.
@@ -10,13 +16,13 @@ to the Chats API.
## When to migrate
Coder Tasks is being deprecated. Support continues on the ESR release and
through Coder v2.36. See the deprecation notice on the [Coder Tasks](../tasks.md) page for the full timeline.
Migrate now. Coder Tasks was deprecated as of Coder v2.36 and is no longer
available by default.
If you currently run workflows on the Tasks API, you should plan to
migrate to the Chats API and [Coder Agents](./index.md). Coder Agents
runs the agent loop in the Coder control plane rather than inside the
workspace, and is the supported path going forward.
If you currently run workflows on the Tasks API, migrate to the Chats API and
[Coder Agents](./index.md). Coder Agents runs the agent loop in the Coder
control plane rather than inside the workspace, and is the supported path
going forward.
The two systems are not interchangeable. Tasks and Chats are separate
resources with separate APIs, so plan to update your integrations rather
+1 -1
View File
@@ -50,7 +50,7 @@ In internal testing, we have seen significant improvements in agent performance
LLMs and agents can be dangerous if not run with proper boundaries. Be sure not to give agents full permissions on behalf of a user, and instead use separate identities with limited scope whenever interacting autonomously.
[Learn more about securing AI agents](./security.md)
[Learn more about the Agent Firewall](./agent-firewall/index.md)
## Keep it Simple
-15
View File
@@ -1,15 +0,0 @@
# Tasks CLI
The Tasks CLI documentation has moved to the auto-generated CLI reference pages:
- [task](../reference/cli/task.md) - Main tasks command
- [task create](../reference/cli/task_create.md) - Create a task
- [task delete](../reference/cli/task_delete.md) - Delete tasks
- [task list](../reference/cli/task_list.md) - List tasks
- [task logs](../reference/cli/task_logs.md) - Show a task's logs
- [task pause](../reference/cli/task_pause.md) - Pause a task
- [task resume](../reference/cli/task_resume.md) - Resume a task
- [task send](../reference/cli/task_send.md) - Send input to a task
- [task status](../reference/cli/task_status.md) - Show task status
For the complete CLI reference, see the [CLI documentation](../reference/cli/index.md).
-66
View File
@@ -1,66 +0,0 @@
# Custom Agents
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
Custom agents beyond the ones listed in the [Coder registry](https://registry.coder.com/modules?search=tag%3Aagent) can be used with Coder Tasks.
## Prerequisites
- A Coder deployment with v2.21 or later
- A [Coder workspace / template](../admin/templates/creating-templates.md)
- A custom agent that supports Model Context Protocol (MCP)
## Getting Started
Coder uses the [MCP protocol](https://modelcontextprotocol.io/introduction) to report activity back to the Coder control plane. From there, activity is displayed in the Coder dashboard.
First, your template will need a [coder_app](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app) for the agent. This can be a web app or command run in the terminal and ideally gives the user a UI to interact with or view more details about the agent.
From there, the agent can run the MCP server with the `coder exp mcp server` command. You will need to set the `CODER_MCP_APP_STATUS_SLUG` environment variable to match the slug in the coder_app resource. `CODER_AGENT_TOKEN` must also be set, but will be present inside a Coder workspace.
## Example
Inside a Coder workspace, run the following commands:
```sh
coder login
export CODER_MCP_APP_STATUS_SLUG=my-agent
# Use your own agent's logic and syntax here:
any-custom-agent configure-mcp --name "coder" --command "coder exp mcp server"
```
This will start the MCP server and report activity back to the Coder control plane on behalf of the coder_app resource.
> [!NOTE]
> See [this version of the Goose module](https://github.com/coder/registry/blob/release/coder/goose/v1.3.0/registry/coder/modules/goose/main.tf) source code for a real-world example of configuring reporting via MCP. Note that in addition to setting up reporting, you'll need to make your template [compatible with Tasks](./tasks.md#option-2-create-or-duplicate-your-own-template), which is not shown in the example.
## Pause and resume
Custom agents can support task pause and resume by enabling state
persistence on the agentapi module. Set `enable_state_persistence = true`
so that AgentAPI saves and restores conversation history across pause and
resume cycles:
```tf
module "agentapi" {
source = "registry.coder.com/coder/agentapi/coder"
version = ">= 2.2.0"
agent_id = coder_agent.main.id
enable_state_persistence = true
# ...
}
```
Your template also needs persistent storage and a sufficient graceful
shutdown timeout. See [Task lifecycle](./tasks-lifecycle.md) for the full
requirements.
## Contributing
We welcome contributions for various agents via the [Coder registry](https://registry.coder.com/modules?tag=agent)! See our [contributing guide](https://github.com/coder/registry/blob/main/CONTRIBUTING.md) for more information.
-263
View File
@@ -1,263 +0,0 @@
# Guide: Create a GitHub to Coder Tasks Workflow
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
## Background
Most software engineering organizations track and manage their codebase through GitHub, and use project management tools like Asana, Jira, or even GitHub's Projects to coordinate work. Across these systems, engineers are frequently performing the same repetitive workflows: triaging and addressing bugs, updating documentation, or implementing well-defined changes for example.
Coder Tasks provides a method for automating these repeatable workflows. With a Task, you can direct an agent like Claude Code to update your documentation or even diagnose and address a bug. By connecting GitHub to Coder Tasks, you can build out a GitHub workflow that will for example:
1. Trigger an automation to take a pre-existing issue
1. Automatically spin up a Coder Task with the context from that issue and direct an agent to work on it
1. Focus on other higher-priority needs, while the agent addresses the issue
1. Get notified that the issue has been addressed, and you can review the proposed solution
This guide walks you through how to configure GitHub and Coder together so that you can tag Coder in a GitHub issue comment, and securely delegate work to coding agents in a Coder Task.
## Implementing the GHA
The below steps outline how to use the Coder [Create Task Action GHA](https://github.com/coder/create-task-action) in a GitHub workflow to solve a bug. The guide makes the following assumptions:
- You have access to a Coder Server that is running. If you don't have a Coder Server running, follow our [Get started guide](../get-started/index.md)
- Your Coder Server is accessible from GitHub
- You have an AI-enabled Task Template that can successfully create a Coder Task. If you don't have a Task Template available, follow our [Getting Started with Tasks Guide](https://coder.com/docs/ai-coder/tasks#getting-started-with-tasks)
- Check the [Requirements section of the GHA](https://github.com/coder/create-task-action?tab=readme-ov-file#requirements) for specific version requirements for your Coder deployment and the following
- GitHub OAuth is configured in your Coder Deployment
- Users have linked their GitHub account to Coder via `/settings/external-auth`
This guide can be followed for other use cases beyond bugs like updating documentation or implementing a small feature, but may require minor changes to file names and the prompts provided to the Coder Task.
### Step 1: Create a GitHub Workflow file
In your repository, create a new file in the `./.github/workflows/` directory named `triage-bug.yaml`. Within that file, add the following code:
```yaml
name: Start Coder Task
on:
issues:
types:
- labeled
permissions:
issues: write
jobs:
coder-create-task:
runs-on: ubuntu-latest
if: github.event.label.name == 'coder'
steps:
- name: Coder Create Task
uses: coder/create-task-action@v0
with:
coder-url: ${{ secrets.CODER_URL }}
coder-token: ${{ secrets.CODER_TOKEN }}
coder-organization: "default"
coder-template-name: "my-template"
coder-task-name-prefix: "gh-task"
coder-task-prompt: "Use the gh CLI to read ${{ github.event.issue.html_url }}, write an appropriate plan for solving the issue to PLAN.md, and then wait for feedback."
github-user-id: ${{ github.event.sender.id }}
github-issue-url: ${{ github.event.issue.html_url }}
github-token: ${{ github.token }}
comment-on-issue: true
```
This code will perform the following actions:
- Create a Coder Task when you apply the `coder` label to an existing GitHub issue
- Pass as a prompt to the Coder Task:
1. Use the GitHub CLI to access and read the content of the linked GitHub issue
1. Generate an initial implementation plan to solve the bug
1. Write that plan to a `PLAN.md` file
1. Wait for additional input
- Post an update on the GitHub ticket with a link to the task
The prompt text can be modified to not wait for additional human input, but continue with implementing the proposed solution and creating a PR for example. Note that this example prompt uses the GitHub CLI `gh`, which must be installed in your Coder template. The CLI will automatically authenticate using the user's linked GitHub account via Coder's external auth.
### Step 2: Setup the Required Secrets & Inputs
The GHA has multiple required inputs that require configuring before the workflow can successfully operate.
You must set the following inputs as secrets within your repository:
- `coder-url`: the URL of your Coder deployment, e.g. https://coder.example.com
- `coder-token`: follow our [API Tokens documentation](https://coder.com/docs/admin/users/sessions-tokens#long-lived-tokens-api-tokens) to generate a token. Note that the token must be an admin/org-level with the "Read users in organization" and "Create tasks for any user" permissions
You must also set `coder-template-name` as part of this. The GHA example has this listed as a secret, but the value doesn't need to be stored as a secret. The template name can be determined the following ways:
- By viewing the URL of the template in the UI, e.g. `https://<your-coder-url>/templates/<org-name>/<template-name>`
- Using the Coder CLI:
```sh
# List all templates in your organization
coder templates list
```
You can also choose to modify the other [input parameters](https://github.com/coder/create-task-action?tab=readme-ov-file#inputs) to better fit your desired workflow.
#### Template Requirements for GitHub CLI
If your prompt uses the GitHub CLI `gh`, your template must pass the user's GitHub token to the agent. Add this to your template's Terraform:
```tf
data "coder_external_auth" "github" {
id = "github" # Must match your CODER_EXTERNAL_AUTH_0_ID
}
resource "coder_agent" "dev" {
# ... other config ...
env = {
GITHUB_TOKEN = data.coder_external_auth.github.access_token
}
}
```
Note that tokens passed as environment variables represent a snapshot at task creation time and are not automatically refreshed during task execution.
- If your GitHub external auth is configured as a GitHub App with token expiration enabled (the default), tokens expire after 8 hours
- If configured as a GitHub OAuth App or GitHub App with expiration disabled, tokens remain valid unless unused for 1 year
Because of this, we recommend to:
- Keep tasks under 8 hours to avoid token expiration issues
- For longer workflows, break work into multiple sequential tasks
- If authentication fails mid-task, users must re-authenticate at /settings/external-auth and restart the task
For more information, see our [External Authentication documentation](https://coder.com/docs/admin/external-auth#configure-a-github-oauth-app).
### Step 3: Test Your Setup
Create a new GitHub issue for a bug in your codebase. We recommend a basic bug, for this test, like “The sidebar color needs to be red” or “The text ‘Coder Tasks are Awesome’ needs to appear in the top left corner of the screen”. You should adapt the phrasing to be specific to your codebase.
Add the `coder` label to that GitHub issue. You should see the following things occur:
- A comment is made on the issue saying `Task created: https://<your-coder-url>/tasks/username/task-id`
- A Coder Task will spin up, and you'll receive a Tasks notification to that effect
- You can click the link to follow the Task's progress in creating a plan to solve your bug
Depending on the complexity of the task and the size of your repository, the Coder Task may take minutes or hours to complete. Our recommendation is to rely on Task Notifications to know when the Task completes, and further action is required.
And that’s it! You may now enjoy all the hours you have saved because of this easy integration.
### Step 4: Adapt this Workflow to your Processes
Following the above steps sets up a GitHub Workflow that will
1. Allow you to label bugs with `coder`
1. A coding agent will determine a plan to address the bug
1. You'll receive a notification to review the plan and prompt the agent to proceed, or change course
We recommend that you further adapt this workflow to better match your process. For example, you could:
- Modify the prompt to implement the plan it came up with, and then create a PR once it has a solution
- Update your GitHub issue template to automatically apply the `coder` label to attempt to solve bugs that have been logged
- Modify the underlying use case to handle updating documentation, implementing a small feature, reviewing bug reports for completeness, or even writing unit tests
- Modify the workflow trigger for other scenarios such as:
```yaml
# Comment-based trigger slash commands
on:
issue_comment:
types: [created]
jobs:
trigger-on-comment:
runs-on: ubuntu-latest
if: startsWith(github.event.comment.body, '/coder')
# On Pull Request Creation
jobs:
on-pr-opened:
runs-on: ubuntu-latest
# No if needed - just runs on PR open
# On changes to a specific directory
on:
pull_request:
paths:
- 'docs/**'
- 'src/api/**'
- '*.md'
jobs:
on-docs-changed:
runs-on: ubuntu-latest
# Runs automatically when files in these paths change
```
## Summary
This guide shows you how to automatically delegate routine engineering work to AI coding agents by connecting GitHub issues to Coder Tasks. When you label an issue (like a bug report or documentation update), a coding agent spins up in a secure Coder workspace, reads the issue context, and works on solving it while you focus on higher-priority tasks. The agent reports back with a proposed solution for you to review and approve, turning hours of repetitive work into minutes of oversight. This same pattern can be adapted to handle documentation updates, test writing, code reviews, and other automatable workflows across your development process.
## Troubleshooting
### "No Coder user found with GitHub user ID X"
**Cause:** The user who triggered the workflow hasn't linked their GitHub account to Coder.
**Solution:**
1. Ensure GitHub OAuth is configured in your Coder deployment (see [External Authentication docs](https://coder.com/docs/admin/external-auth#configure-a-github-oauth-app))
1. Have the user visit `https://<your-coder-url>/settings/external-auth` and link their GitHub account
1. Retry the workflow by re-applying the `coder` label or however else the workflow is triggered
### "Failed to create task: 403 Forbidden"
**Cause:** The `coder-token` doesn't have the required permissions.
**Solution:** The token must have:
- Read users in organization
- Create tasks for any user
Generate a new token with these permissions at `https://<your-coder-url>/deployment/general`. See the [Coder Create Task GHA requirements](https://github.com/coder/create-task-action?tab=readme-ov-file#requirements) for more specific information.
### "Template 'my-template' not found"
**Cause:** The `coder-template-name` is incorrect or the template doesn't exist in the specified organization.
**Solution:**
1. Verify the template name using: `coder templates list`
1. Update the `coder-template-name` input in your workflow file to match exactly, or input secret or variable saved in GitHub
1. Ensure the template exists in the organization specified by `coder-organization`
### Task fails with "authentication failed" or "Bad credentials" after running for hours
**Symptoms:**
- Task starts successfully and works initially
- After some time passes, `gh` CLI commands fail with:
- `authentication failed`
- `Bad credentials`
- `HTTP 401 Unauthorized`
- `error getting credentials` from git operations
**Cause:** The GitHub token expired during task execution. Tokens passed as environment variables are captured at task creation time and expire after 8 hours (for GitHub Apps with expiration enabled). These tokens are not automatically refreshed during task execution.
**Diagnosis:**
From within the running task workspace, check if the token is still valid:
```sh
# Check if the token still works
curl -H "Authorization: token ${GITHUB_TOKEN}" \
https://api.github.com/user
```
If this returns 401 Unauthorized or Bad credentials, the token has expired.
**Solution:**
1. Have the user re-authenticate at `https://<your-coder-url>/settings/external-auth`
1. Verify the GitHub provider shows "Authenticated" with a green checkmark
1. Re-trigger the workflow to create a new task with a fresh token
-36
View File
@@ -1,36 +0,0 @@
> [!NOTE]
> Features mentioned on this page, such as AI Gateway and Agent Firewall,
> are part of [AI Governance](./ai-governance.md), which is included with a
> Premium license.
As the AI landscape is evolving, we are working to ensure Coder remains a secure
platform for running AI agents just as it is for other cloud development
environments.
## Use Trusted Models
Most agents can be configured to either use a local LLM (e.g. llama3), an agent
proxy (e.g. OpenRouter), or a Cloud-Provided LLM (e.g. AWS Bedrock). Research
which models you are comfortable with and configure your Coder templates to use
those.
## Set up Firewalls and Proxies
Many enterprises run Coder workspaces behind a firewall or a proxy to prevent
threats or bad actors. These same protections can be used to ensure AI agents do
not access or upload sensitive information.
## Separate API keys and scopes for agents
Many agents require API keys to access external services. It is recommended to
create a separate API key for your agent with the minimum permissions required.
This will likely involve editing your template for Agents to set different
scopes or tokens from the standard one.
Additional guidance and tooling is coming in future releases of Coder.
## Set Up Agent Firewall
Agent Firewall is a process-level firewall that lets you restrict and
audit what AI agents can access within Coder workspaces. To learn more about
this feature, see [Agent Firewall](./agent-firewall/index.md).
-209
View File
@@ -1,209 +0,0 @@
# Understanding Coder Tasks
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
## What is a Task?
Coder Tasks is Coder's platform for managing coding agents. With Coder Tasks, you can:
- Run an AI Agent like Claude Code or OpenAI's Codex in your Workspace to assist in day-to-day development and building
- Kick off AI-enabled workflows such as upgrading a vulnerable package and automatically opening a GitHub Pull Requests with the patch
- Configure a background operation where an automated agent can detect a failure in your CI/CD pipeline, spin up a Coder Workspace, apply a fix, and prepare a PR _without_ manual input
![Tasks UI](../images/guides/ai-agents/tasks-ui.png)Coder Tasks Dashboard view to see all available tasks.
Coder Tasks allows you and your organization to build and automate workflows to fully leverage AI. Tasks operate through Coder Workspaces. We support interacting with an agent through the Task UI and CLI. Some Tasks can also be accessed through the Coder Workspace IDE; see [connect via an IDE](../user-guides/workspace-access/index.md).
## Why Use Tasks?
Coder Tasks make both developer-driven _and_ autonomous agentic workflows first-class citizens within your organization. Without Coder Tasks, teams revert to ad-hoc scripts, one-off commands, or manual checklists even for tasks that LLMs could automate. These workarounds can help a single engineer, but don't scale or provide consistency across an organization that is attempting to use AI as a true force multiplier.
Coder Tasks exist to solve these types of problems:
- **Consistency:** Capture a known, safe, & secure workflow once that can then be run anywhere
- **Reproducibility:** Every task runs from a Coder Workspace, so results are reliable
- **Productivity:** Eliminate manual processes from developer processes enabling them to focus on less defined and harder-to-do issues
- **Scalability:** Once a workflow is captured in a task, it can be reused by other teams within your organization scaling with you as you grow
- **Flexibility:** Support both developer _AND_ autonomous agentic workflows
### Example Task Workflow
Coder Tasks aren't limited to manual operation. They can operate as event-driven automations triggered by your team's everyday activities. Tasks can be thought of through two different type of triggers: manual and event-driven. In the below diagram, the user reported bug could result in a task being spun up via:
- **Event-Driven:** An automatic hook in your git repository
- **Manual:** An engineer reviewing the bug backlog manually creates a task
Other common triggers for event-based workflows include PRs being created/updated, a failure in your CI/CD pipeline, or issues being created/updated in your repository.
![Example Background Task](../images/guides/ai-agents/background-task-example.png)Example of Background Coder Tasks operation.
## How to Make a Task Template
If you need a refresher on Coder Templates, check out our [starting guide here](https://coder.com/docs/tutorials/template-from-scratch).
### What Makes a Task Template
Task Templates are regular Coder Templates with a few additional resources defined. These resources include the logic that lets the Coder UI and infrastructure recognize a Task, and prepare the system for automated execution and AI-driven workflows rather than development environments for developers and builders.
There are two approaches to turning a Template into a Task Template:
#### Using a Registry Module
You can use a pre-existing agent module that [Coder maintains](https://registry.coder.com/modules). When using an agent module, you must define:
- `coder_ai_task` resource: links a `coder_app` to a Task.
- **Agentic Module** that defines the agent you want to use, e.g. Claude Code, Codex CLI, Gemini CLI
Coder maintains various agentic modules; see [Coder Labs](https://registry.coder.com/contributors/coder-labs). These modules, in addition to defining connection information for the specific agent, reference the [AgentAPI module](https://registry.coder.com/modules/coder/agentapi) which provides connection, reporting, and agent life cycle management operations. The modules also output the specific `coder_app` identifier for the specific agent running inside the workspace.
The following code snippet can be dropped into any existing template in Coder v2.28 or above to modify it into a Claude-Code enabled task template. This snippet also includes space for a setup script that will prime the agent for execution.
> [!NOTE]
> This requires at least version 2.13.0 of the `coder/coder` Terraform provider.
```tf
data "coder_parameter" "setup_script" {
name = "setup_script"
display_name = "Setup Script"
type = "string"
form_type = "textarea"
description = "Script to run before running the agent"
mutable = false
default = ""
}
data "coder_task" "me" {}
resource "coder_ai_task" "task" {
app_id = module.claude-code.task_app_id
}
# The Claude Code module does the automatic task reporting
# Other agent modules: https://registry.coder.com/modules?search=agent
# Or use a custom agent:
module "claude-code" {
source = "registry.coder.com/coder/claude-code/coder"
version = "4.0.0"
agent_id = coder_agent.example.id
workdir = "/home/coder/project"
claude_api_key = var.anthropic_api_key
# OR
# claude_code_oauth_token = var.anthropic_oauth_token
claude_code_version = "1.0.82" # Pin to a specific version
agentapi_version = "v0.6.1"
ai_prompt = data.coder_task.me.prompt
model = "sonnet"
# Optional: run your pre-flight script
# pre_install_script = data.coder_parameter.setup_script.value
permission_mode = "plan"
mcp = <<-EOF
{
"mcpServers": {
"my-custom-tool": {
"command": "my-tool-server",
"args": ["--port", "8080"]
}
}
}
EOF
}
# Rename to `anthropic_oauth_token` if using the Oauth Token
variable "anthropic_api_key" {
type = string
description = "Generate one at: https://console.anthropic.com/settings/keys"
sensitive = true
}
```
Let's break down this snippet:
- The `module "claude-code"` sets up the Task template to use Claude Code. Coder's Registry supports many other agent modules like [OpenAI's Codex](https://registry.coder.com/modules/coder-labs/codex) or [Gemini CLI](https://registry.coder.com/modules/coder-labs/gemini)
- Each module defines its own specific inputs. Claude Code expects the `claude_api_key` input, but OpenAI based agents expect `OPENAI_API_KEY` for example. You'll want to check the specific module's defined variables to know what exactly needs to be defined. You will also generally need to pass `data.coder_task.me.prompt`
- Each module outputs the UUID of the `coder_app` related to the AI agent. In the above example, the output is named `task_app_id`. See the relevant documentation for the module for more detailed information.
- You can define specific scripts to run before the module is installed, `pre_install_script`, or after install, `pre_install_script`. For example, you could define a setup script that calls to AWS S3 and pulls specific files you want your agent to have access to
#### Using a Custom Agent
Coder allows you to define a custom agent. When doing so, you must define:
- A `coder_app` resource that uses [`coder/agentapi`](https://github.com/coder/agentapi) to run the custom agent. **AgentAPI** provides runtime execution logistics for the task.
- A `coder_ai_task` resource which associates the `coder_app` related to the AI agent with the Task.
You can find the latest [AgentAPI binary here](https://github.com/coder/agentapi/releases). You can alternatively import and use the [AgentAPI module](https://registry.coder.com/modules/coder/agentapi?tab=variables) Coder maintains.
Read more about [custom agents here](https://coder.com/docs/ai-coder/custom-agents).
#### Putting it all Together
Coder recommends using pre-existing agent modules when making a Task Template. Making a Task Template boils down to:
1. Identify the existing agent you want access to in our [Registry](https://registry.coder.com/modules).
1. Add the agent's module to your existing template.
1. Define the `coder_ai_task` resource and `coder_task` data source.
1. Wire in the module's inputs and outputs:
- Pass the prompt from the `coder_task` data source into the module.
- Pass the module's `task_app_id` output into the `coder_ai_task` resource.
and you're all set to go! If you want to build your own custom agent, read up on our [Custom Agents](https://coder.com/docs/ai-coder/custom-agents) documentation.
In summary, Task Templates are highly flexible. You can swap out modules depending on which agent you want to run, adjust their inputs based on the provider's requirements, and layer on custom setup scripts to tailor the environment to your workflow. Whether that means using a different LLM, pointing to a new API key, or pulling files from S3 at startup, the template structure makes it easy to adapt tasks without having to rebuild everything from scratch.
## Task Template Design Principles
Coder Tasks, being based in a given Workspace, operate on very similar principles:
- **Specificity & Refinability:** Tasks, just like Templates, are made to address a specific problem and evolve with that problem and your team over time
- **Security:** Because Tasks are defined through templates, you can define and restrict what access an agent running inside a Task has access to
- **Frugality:** Tasks only consume resources when running. You should design your Task Template to provide just enough compute and storage so that your task can effectively complete its job, reducing infrastructure cost
- **Model Applicability:** Task Templates can specify which model is most appropriate, meaning you can fine tune your Task based on its job, be that a code-focused model for fixing bugs or a generalized LLM to write summaries and updates on Pull Requests
- **Automation:** Coder Tasks provide a comprehensive set of built-in APIs, status monitoring, and notification systems. This allows for you and your team to build seamless integrations with external automation workflows
Together, these principles make up the core idea of designing task templates. Tasks are programmable, secure, and cost-efficient agents that integrate seamlessly into your team's workflow. By treating task templates as living and adaptable designs, you can evolve them with your team and needs without sacrificing clarity or control. The result is a system where automation, resource management, and security are baked into the foundation letting developers focus less on orchestration details and more on solving the problems that matter.
These design principles aren’t just technical guidelines; they're the lens through which to understand what Tasks are and how to use them effectively. By grounding Tasks in specificity, security, frugality, applicability, and automation, you ensure they remain reliable building blocks for both individual workflows and larger team processes.
### Practical Considerations
Tasks don't expose template parameters at runtime. If users need to choose different compute, region, or tooling options for example, you can define workspace presets in the template and have users select a preset when starting the Task. See workspace presets for details: ../admin/templates/extending-templates/parameters#workspace-presets.
### Identity, Security, and Access
By default, agents running with Coder Tasks always act as the authenticated developer. External auth tokens tie actions directly back to a specific user, so Git operations like cloning, pushing, or creating a PR are executed under the developer's personal OAuth tokens. Workspace SSH keys are generated per user, and external service integrations authenticate with the developer's personal credentials. This preserves audit trails and ensures actions stay traceable. Authentication (who the user is) subsequently stays separate from authorization (what the user can do), with identity providers acting as the source of truth. For human users, OIDC or SSO ensure sessions are consistent, centralized, and easy to govern.
For automated or background use cases, Tasks can also run under service identities. These behave like CI jobs: locked down, narrowly scoped, and managed by the organization. Service accounts or bot identities cover headless API-driven systems, while GitHub Apps enable fine-grained repository access under your organization's control. If long-lived API tokens are needed, they should be tied to service accounts with strict roles and rotation policies. In practice, the default should always be user-context execution for developer workflows while service accounts are reserved for production automation, CI/CD pipelines, and cross-team integrations. This balance keeps developer productivity high while aligning with organizational security requirements.
## How Tasks Fit Into Coder
Coder's platform is built around three core concepts that work together:
**Coder Templates** define the infrastructure and tool configurations that can be reused across your organization. They're the "blueprint" that ensures consistency and captures your team's working preferences.
**Coder Workspaces** are the individual development environments that are spun up from templates. They provide developers with consistent, reproducible environments to perform their job.
**Tasks** extend this model to AI agents and automated workflows. The same template-driven approach is now optimized to allow for autonomous execution that can be independent from human interaction.
### Platform Integration
Tasks aren't a separate system bolted onto Coder, but a natural extension of your existing infrastructure.
- **Security:** Tasks inherit the same access controls, secrets management, and network policies as developer workspaces
- **Resource Management:** Tasks have access to the same compute pools, storage, and scaling policies you've already configured
- **Observability:** Tasks use the same underlying infrastructure for monitoring, and appear in their own custom task-specific dashboards
### Developer Experience Continuity
Coder understands that every team is in a different place in its AI adoption plan. Some teams are still working with AI assistants to speed up development, while other teams are adopting background tasks to automate PR reviews and small bug fixes.
Naturally, your team might want to jump into a task, for example when the agent encounters an issue or needs human input. With Coder Tasks, you're able to jump into the existing Coder Workspace environment backing the task execution so that you can push the work forward. There's no context switching between tools; it's the same workspace you're already used to and the agent's work becomes yours.
-197
View File
@@ -1,197 +0,0 @@
# Task lifecycle
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
Tasks can pause when idle and resume when you interact with them again.
Pausing frees compute resources while preserving conversation context, so
the agent can pick up where it left off. This page covers how pause and
resume work, what gets preserved, and what your template needs.
> [!NOTE]
> Task pause and resume is in beta. Some details may change in future releases.
## How tasks pause
Tasks pause in two ways:
- **Auto-pause**: The workspace idle timeout expires. Tasks use the
template's existing `default_ttl` and `activity_bump` settings, the same
ones that control regular workspace auto-stop. When a task auto-pauses,
the build reason is recorded as "idle timeout" and a notification is sent
to the task owner.
- **Manual pause**: You can pause a task through the CLI with
`coder task pause`, the API, or the pause button in the Tasks UI.
When a task pauses, the workspace stops. Compute resources are freed and
persistent storage remains intact. Stopping a task workspace manually (via
the workspace UI or `coder stop`) triggers the same pause behavior,
including log snapshot capture and state persistence. Similarly, starting
the workspace (`coder start`) resumes the task.
### Activity detection for tasks
AI agent activity extends the workspace deadline just like SSH or IDE
connections do. When an agent reports "working" status through Coder Tasks,
the workspace deadline is bumped by the template's `activity_bump` duration.
This prevents auto-pause while the agent is actively working.
See [Workspace scheduling](../user-guides/workspace-scheduling.md) for the
full list of activity types.
## What gets preserved
Three things survive a pause:
1. **Log snapshot**: Up to 30 of the last messages from the conversation
are captured during shutdown and stored server-side. While paused,
`coder task logs` and the Tasks UI show this snapshot so you can see
what the agent was working on.
1. **AgentAPI state**: When state persistence is enabled, the full
conversation history is saved to a file on persistent storage. After
resume, the Tasks UI shows the complete chat history.
1. **AI agent session**: Agents that support session persistence (such as
Claude Code via `~/.claude/`) retain their own context on persistent
storage. On resume, the agent picks up where it left off with full
memory of the previous conversation.
> [!NOTE]
> Log snapshots and AgentAPI state persistence are best-effort. If the
> shutdown script is interrupted or times out, the workspace still stops
> normally, but the snapshot may not be captured and chat history may be
> empty after resume.
If `enable_state_persistence` is true but the AI agent does not support
session resume, the UI shows previous messages but the agent starts fresh
with no memory of the conversation. This is expected behavior. See
[Agent compatibility](./agent-compatibility.md) for which agents support
full session resume.
## Resuming a task
You can resume a paused task in several ways:
- **CLI**: `coder task resume <task>`
- **UI**: Click the **Resume** button on the task page or in the tasks list
Resume starts the workspace, runs startup scripts, starts AgentAPI (which
loads its state file if state persistence is enabled), and starts the AI
agent (which resumes its session if supported).
> [!NOTE]
> Resume requires a full workspace build, which can take several minutes
> depending on your template.
## Requirements
### Persistent storage
Templates must have persistent storage (Docker volume, Kubernetes PVC, or
similar) that survives workspace stop and start cycles. Without it, the AI
agent's session files and the AgentAPI state file are lost on stop.
See
[Resource persistence](../admin/templates/extending-templates/resource-persistence.md)
for configuration patterns.
### Compatible module version
AI agent registry modules handle shutdown scripts and state persistence
through the agentapi base module. To enable pause and resume, use a module
version that includes this support.
For Claude Code, update the module version in your template:
```tf
module "claude-code" {
source = "registry.coder.com/coder/claude-code/coder"
version = ">= 4.8.0, < 5.0.0" # Pause/resume support (Tasks/AgentAPI). Removed in v5.
agent_id = coder_agent.main.id
# ...
}
```
Versions 4.8.0 and above set `enable_state_persistence = true`, which
configures the shutdown script and state file automatically.
See [Agent compatibility](./agent-compatibility.md) for the minimum module
version per agent.
#### The `enable_state_persistence` variable
The `enable_state_persistence` variable controls whether AgentAPI saves and
restores conversation history across pause and resume cycles. It defaults to
`false` in the agentapi base module. Agent modules that support session
persistence, like `claude-code`, override this to `true` in their module
definition.
When `enable_state_persistence` is `false`, the shutdown script still runs to
capture log snapshots, but skips saving AgentAPI state. On resume, chat
history is not restored.
If you are building a [custom agent](./custom-agents.md#pause-and-resume),
set this variable on the agentapi module directly.
### Graceful shutdown timeout
> [!WARNING]
> Without this configuration, log snapshots and state persistence may
> silently fail. The container runtime can terminate the container before
> the shutdown script finishes.
The shutdown script runs inside the workspace container. The container
runtime controls how long the process has to shut down before it is
force-terminated. The defaults are often too short:
- **Docker**: 10 seconds
- **Kubernetes**: 30 seconds
The grace period covers not just this shutdown script but also the workspace
agent's own graceful shutdown and any other modules that run shutdown
scripts. Set at least **1 minute** as a baseline. **5 minutes** is
recommended to account for slow disks, multiple shutdown scripts, and other
modules performing cleanup.
**Docker**: Add to your `docker_container` resource:
```tf
resource "docker_container" "workspace" {
# Both attributes are needed for graceful shutdown.
destroy_grace_seconds = 300 # 5 minutes
stop_timeout = 300
stop_signal = "SIGINT"
# ...
}
```
**Kubernetes**: Add to your `kubernetes_pod` resource:
```tf
resource "kubernetes_pod" "main" {
timeouts {
delete = "6m" # Must exceed the grace period below.
}
spec {
termination_grace_period_seconds = 300 # 5 minutes
}
}
```
If the container is terminated before the shutdown script finishes, the workspace
still stops normally but log snapshots may be missing and chat history may
not be restored after resume.
## Next steps
- [Agent compatibility](./agent-compatibility.md) for session persistence
support and minimum module versions.
- [Resource persistence](../admin/templates/extending-templates/resource-persistence.md)
for configuring persistent storage in templates.
- [Workspace scheduling](../user-guides/workspace-scheduling.md) for how
auto-stop and activity detection work.
-171
View File
@@ -1,171 +0,0 @@
# Migrating Task Templates for Coder version 2.28.0
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
Prior to Coder version 2.28.0, the definition of a Coder task was different to the above. It required the following to be defined in the template:
1. A Coder parameter specifically named `"AI Prompt"`,
2. A `coder_workspace_app` that runs the `coder/agentapi` binary,
3. A `coder_ai_task` resource in the template that sets `sidebar_app.id`. This was generally defined in Coder modules specific to AI Tasks.
Note that 2 and 3 were generally handled by the `coder/agentapi` Terraform module.
> [!IMPORTANT]
> The pre-2.28.0 definition is no longer supported as of Coder 2.30.0. You must update your Tasks-enabled templates to use the new format described below.
You can view an [example migration here](https://github.com/coder/coder/pull/20420). Alternatively, follow the steps below:
## Upgrade Steps
1. Update the Coder Terraform provider to at least version 2.13.0:
```diff
terraform {
required_providers {
coder = {
source = "coder/coder"
- version = "x.y.z"
+ version = ">= 2.13"
}
}
}
```
1. Define a `coder_ai_task` resource and `coder_task` data source in your template:
```diff
+data "coder_task" "me" {}
+resource "coder_ai_task" "task" {}
```
1. Update the version of the respective AI agent module (e.g. `claude-code`) to at least 4.0.0 and provide the prompt from `data.coder_task.me.prompt` instead of the "AI Prompt" parameter.
```diff
module "claude-code" {
source = "registry.coder.com/coder/claude-code/coder"
- version = "4.0.0"
+ version = "4.0.0"
...
- ai_prompt = data.coder_parameter.ai_prompt.value
+ ai_prompt = data.coder_task.me.prompt
}
```
1. Add the `coder_ai_task` resource and set `app_id` to the `task_app_id` output of the Claude module.
> [!NOTE]
> Refer to the documentation for the specific module you are using for the exact name of the output.
```diff
resource "coder_ai_task" "task" {
+ app_id = module.claude-code.task_app_id
}
```
## Coder Tasks format pre-2.28
Below is a minimal illustrative example of a Coder Tasks template pre-2.28.0.
**Note that this is NOT a full template.**
```tf
terraform {
required_providers {
coder = {
source = "coder/coder"
}
}
}
data "coder_workspace" "me" {}
resource "coder_agent" "main" { ... }
# The prompt is passed in via the specifically named "AI Prompt" parameter.
data "coder_parameter" "ai_prompt" {
name = "AI Prompt"
mutable = true
}
# This coder_app is the interface to the Coder Task.
# This is assumed to be a running instance of coder/agentapi
resource "coder_app" "ai_agent" {
...
}
# Assuming that the below script runs `coder/agentapi` with the prompt
# defined in ARG_AI_PROMPT
resource "coder_script" "agentapi" {
agent_id = coder_agent.main.id
run_on_start = true
script = <<EOT
#!/usr/bin/env bash
ARG_AI_PROMPT=${data.coder_parameter.ai_prompt.value} \
/tmp/run_agentapi.sh
EOT
...
}
# The coder_ai_task resource associates the task to the app.
resource "coder_ai_task" "task" {
sidebar_app {
id = coder_app.ai_agent.id
}
}
```
## Tasks format from 2.28 onwards
In v2.28 and above, the following changes were made:
- The explicitly named "AI Prompt" parameter is no longer supported. The task prompt is now available in the `coder_ai_task` resource (provider version 2.12 and above) and `coder_task` data source (provider version 2.13 and above).
- Modules no longer define the `coder_ai_task` resource. These must be defined explicitly in the template.
- The `sidebar_app` field of the `coder_ai_task` resource is now deprecated. In its place, use `app_id`.
Example (**not** a full template):
```tf
terraform {
required_providers {
coder = {
source = "coder/coder"
version = ">= 2.13.0"
}
}
}
data "coder_workspace" "me" {}
# The prompt is now available in the coder_task data source.
data "coder_task" "me" {}
resource "coder_agent" "main" { ... }
# This coder_app is the interface to the Coder Task.
# This is assumed to be a running instance of coder/agentapi (for instance, started via `coder_script`).
resource "coder_app" "ai_agent" {
...
}
# Assuming that the below script runs `coder/agentapi` with the prompt
# defined in ARG_AI_PROMPT
resource "coder_script" "agentapi" {
agent_id = coder_agent.main.id
run_on_start = true
script = <<EOT
#!/usr/bin/env bash
ARG_AI_PROMPT=${data.coder_task.me.prompt} \
/tmp/run_agentapi.sh
EOT
...
}
# The coder_ai_task resource associates the task to the app.
resource "coder_ai_task" "task" {
app_id = coder_app.ai_agent.id
}
```
-176
View File
@@ -1,176 +0,0 @@
# Coder Tasks
> [!WARNING]
> Starting June 2, 2026, Coder Tasks will move to a 12-month Extended Support Release (ESR) for Premium customers.
>
> Tasks will be removed from new Coder releases beginning with v2.37 (September 1, 2026) and will only be available via the ESR during the support period.
>
> We recommend transitioning to [Coder Agents](./agents/index.md), the long-term replacement.
Coder Tasks is an interface for running & managing coding agents such as Claude Code and Aider, powered by Coder workspaces.
![Tasks UI](../images/guides/ai-agents/tasks-ui.png)
Coder Tasks is best for cases where the IDE is secondary, such as prototyping or running long-running background jobs. However, tasks run inside full workspaces so developers can [connect via an IDE](../user-guides/workspace-access/index.md) to take a task to completion.
You can also interact with Coder Tasks from your IDE. The [Coder extension for VS Code](https://marketplace.visualstudio.com/items?itemName=coder.coder-remote) (and compatible forks like Cursor) enables you to create, monitor, and manage Tasks directly from the IDE, eliminating the need to context-switch to a browser. After logging in, you get access to a dedicated Tasks view in the sidebar that lets you select a template, configure parameters, prompt an agent, and track task status or download logs. Your tasks run in Coder workspaces with access to your repos, credentials, and internal network.
![VS Code IDE Extension](../images/guides/ai-agents/vs_code_tasks_extension.png)
The Task details view shows the user's complete chat, workspace status and, build or startup logs so you can understand what the Task is doing and troubleshoot failures. This makes it easier to confirm progress and diagnose issues without leaving the Task workflow.
![VS Code IDE Extension Details View](../images/guides/ai-agents/vs_code_tasks_extension_details.png)
> [!NOTE]
> Both Community and Premium deployments include 1,000 Agent Workspace Builds for proof-of-concept use. Community deployments do not have access to [AI Gateway](./ai-gateway/index.md) or [Agent Firewall](./agent-firewall/index.md). To scale beyond the 1,000 build limit or use AI Governance features, [AI Governance](./ai-governance.md), included with a Premium license, provides expanded usage pools that grow with your user count. [Contact us](https://coder.com/contact) to discuss pricing.
## Supported Agents (and Models)
Any terminal-based agent that supports Model Context Protocol (MCP) can be integrated with Coder Tasks, including your own custom agents.
Out of the box, agents like Claude Code and Goose are supported with built-in modules that can be added to a template. [See all modules compatible with Tasks in the Registry](https://registry.coder.com/modules?search=tag%3Atasks).
Enterprise LLM Providers such as AWS Bedrock, GCP Vertex and proxies such as LiteLLM can be used as well in order to keep intellectual property private. Self-hosted models such as llama4 can also be configured with specific agents, such as Aider and Goose.
## Architecture
Each task runs inside its own Coder workspace for isolation purposes. Agents like Claude Code also run in the workspace, and can be pre-installed via a module in the Coder Template. Agents then communicate with your LLM provider, so no GPUs are directly required in your workspaces for inference.
![High-Level Architecture](../images/guides/ai-agents/architecture-high-level.png)
Coder's [built-in modules for agents](https://registry.coder.com/modules?search=tag%3Atasks) will pre-install the agent alongside [AgentAPI](https://github.com/coder/agentapi). AgentAPI is an open source project developed by Coder which improves status reporting and the Chat UI, regardless of which agent you use.
## Getting Started with Tasks
### Option 1&rpar; Import and Modify Our Example Template
Our example template is the best way to experiment with Tasks with a [real world demo app](https://github.com/gothinkster/realworld). The application is running in the background and you can experiment with coding agents.
![Tasks UI with realworld app](../images/guides/ai-agents/realworld-ui.png)
Try prompts such as:
- "rewrite the backend in go"
- "document the project structure"
- "change the primary color theme to purple"
To import the template and begin configuring it, import the example [Run Coder Tasks on Docker](../../examples/templates/tasks-docker) template.
### Option 2&rpar; Create or Duplicate Your Own Template
A template becomes a Task-capable template if it defines a `coder_ai_task` resource. Coder analyzes template files during template version import to determine if these requirements are met. Try adding this terraform block to an existing template where you'll add our Claude Code module.
> [!NOTE]
> The `coder_ai_task` resource is not defined within the [Claude Code Module](https://registry.coder.com/modules/coder/claude-code?tab=readme). You need to define it yourself.
```tf
terraform {
required_providers {
coder = {
source = "coder/coder"
version = ">= 2.13"
}
}
}
data "coder_parameter" "setup_script" {
name = "setup_script"
display_name = "Setup Script"
type = "string"
form_type = "textarea"
description = "Script to run before running the agent"
mutable = false
default = ""
}
data "coder_task" "me" {}
resource "coder_ai_task" "task" {
app_id = module.claude-code.task_app_id
}
# The Claude Code module does the automatic task reporting
# Other agent modules: https://registry.coder.com/modules?search=agent
# Or use a custom agent:
module "claude-code" {
source = "registry.coder.com/coder/claude-code/coder"
version = "4.0.0"
agent_id = coder_agent.example.id
workdir = "/home/coder/project"
claude_api_key = var.anthropic_api_key
# OR
# claude_code_oauth_token = var.anthropic_oauth_token
claude_code_version = "1.0.82" # Pin to a specific version
agentapi_version = "v0.6.1"
ai_prompt = data.coder_task.me.prompt
model = "sonnet"
# Optional: run your pre-flight script
# pre_install_script = data.coder_parameter.setup_script.value
permission_mode = "plan"
mcp = <<-EOF
{
"mcpServers": {
"my-custom-tool": {
"command": "my-tool-server",
"args": ["--port", "8080"]
}
}
}
EOF
}
# Rename to `anthropic_oauth_token` if using the Oauth Token
variable "anthropic_api_key" {
type = string
description = "Generate one at: https://console.anthropic.com/settings/keys"
sensitive = true
}
```
Because Tasks run unpredictable AI agents, often for background tasks, we recommend creating a separate template for Coder Tasks with limited permissions. You can always duplicate your existing template, then apply separate network policies/firewalls/permissions to the template. From there, follow the docs for one of our [built-in modules for agents](https://registry.coder.com/modules?search=tag%3Atasks) in order to add it to your template, configure your LLM provider.
Alternatively, follow our guide for [custom agents](./custom-agents.md).
> [!IMPORTANT]
> Upgrading from Coder v2.27 or earlier? See the [Tasks Migration Guide](./tasks-migration.md) for breaking changes in v2.28.0.
## Customizing the Task UI
The Task UI displays all workspace apps declared in a Task template. You can customize the app shown in the sidebar using the `app_id` field on the `coder_ai_task` resource.
If a workspace app has the special `"preview"` slug, a navbar will appear above it. This is intended for templates that let users preview a web app they’re working on.
We plan to introduce more customization options in future releases.
## Automatically name your tasks
Coder can automatically generate a name your tasks if you set the `ANTHROPIC_API_KEY` environment variable on the Coder server. Otherwise, tasks will be given randomly generated names.
## Opting out of Tasks
If you tried Tasks and decided you don't want to use it, you can hide the Tasks tab by starting `coder server` with the `CODER_HIDE_AI_TASKS=true` environment variable or the `--hide-ai-tasks` flag.
## Pausing and resuming tasks
Tasks automatically pause when the workspace reaches its idle timeout,
freeing compute resources. While paused, you can view a snapshot of the
last conversation messages. When you resume or send a new message, the
workspace restarts and the agent picks up where it left off if the agent
and template support session persistence.
For details on how pause and resume works and what your template needs,
see [Task lifecycle](./tasks-lifecycle.md).
## Command Line Interface
See [Tasks CLI](./cli.md).
## Next Steps
<children></children>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

@@ -22,11 +22,15 @@ templates. Over subsequent releases, Tasks matured significantly through UI
refinement, improved reliability, and underlying task-status improvements in the
server and database layers. By 2.29, Tasks were formally promoted to general
availability, with full CLI support, a task-specific UI, and consistent
visibility of task states across the dashboard. This transition establishes
Tasks as a stable automation and job-execution primitive within
Coder—particularly suited for long-running background operations like bug fixes,
documentation generation, PR reviews, and testing/QA.For more information, read
our documentation [here](https://coder.com/docs/ai-coder/tasks).
visibility of task states across the dashboard. This transition established
Tasks as a stable automation and job-execution primitive within Coder,
particularly suited for long-running background operations like bug fixes,
documentation generation, PR reviews, and testing/QA.
> [!NOTE]
> Coder Tasks has since been deprecated and is no longer available in current
> releases. [Coder Agents](../../ai-coder/agents/index.md) is the long-term
> replacement.
### AI Gateway
@@ -181,8 +181,8 @@ updates, or change administrator expectations:
| `--secure-auth-cookie` defaulted independently from the access URL. | Secure auth cookies are enabled automatically when `CODER_ACCESS_URL` uses HTTPS. | Confirm reverse proxies send the correct scheme headers. To preserve old behavior, explicitly set `CODER_SECURE_AUTH_COOKIE=false`. |
| SFTP and SCP connections always landed in `$HOME`. | SFTP and SCP now respect the workspace agent `dir` setting. | Update scripts that relied on implicit `$HOME` paths. Prefer explicit absolute paths for file transfers. |
| `coder_agent` `dir` attribute accepted any path without warning. | `dir` is deprecated and emits a warning. Non-`$HOME`/`~` values also break [Coder Desktop file sync](../../user-guides/desktop/desktop-connect-sync.md). | Set `dir` to `$HOME` or omit it on `coder_agent` resources. The attribute still works in 2.34 but will be removed in a future release. |
| Pre-2.28 Tasks templates might still exist in older deployments. | The pre-2.28 Tasks template format is no longer supported as of 2.30. | Update Tasks templates to use `app_id` instead of the deprecated `sidebar_app` flow. See the [Tasks migration guide](../../ai-coder/tasks-migration.md). |
| Tasks is the primary AI coding workflow. | Coder Agents is the long-term replacement, and Tasks is supported through the 2.34 ESR window (into 2026). | Plan migration from the Tasks API to the Chats API and Coder Agents. See [Migrating from the Tasks API to the Chats API](../../ai-coder/agents/tasks-to-chats-migration.md). |
| Pre-2.28 Tasks templates might still exist in older deployments. | The pre-2.28 Tasks template format is no longer supported as of 2.30. | Update Tasks templates to use `app_id` instead of the deprecated `sidebar_app` flow. |
| Tasks is the primary AI coding workflow. | Coder Agents is the long-term replacement, and Tasks is supported through the 2.34 ESR window (into 2026). | Plan migration from the Tasks API to the Chats API and [Coder Agents](../../ai-coder/agents/index.md). See [Migrating from the Tasks API to the Chats API](../../ai-coder/agents/tasks-to-chats-migration.md). |
| AI Gateway injected MCP tools can be used for tool exposure. | Injected MCP tools are deprecated. | Move new integrations toward Coder Agents MCP server configuration or the MCP server flow. See [AI Gateway MCP](../../ai-coder/ai-gateway/mcp.md) and [MCP servers](../../ai-coder/agents/platform-controls/mcp-servers.md). |
| AI Bridge is opt-in via `CODER_AIBRIDGE_ENABLED` (default `false`). | The toggle is renamed to `CODER_AI_GATEWAY_ENABLED` and now defaults to `true`. | The in-memory AI Gateway now starts on every deployment. Set `CODER_AI_GATEWAY_ENABLED=false`, or the deprecated `CODER_AIBRIDGE_ENABLED` alias which still works, to keep the old behavior. |
| AI Gateway providers are configured with `CODER_AIBRIDGE_PROVIDER_*` or `CODER_AI_GATEWAY_PROVIDER_*` env vars. | Provider configuration is stored in the database. Env vars seed the database once on first startup, then are deprecated. | After upgrade, visit `/ai/settings/providers` to verify seeded providers, then remove the env vars. Coderd fails to start if env vars drift from the seeded database row. See [AI Gateway providers](../../ai-coder/ai-gateway/providers.md). |
+1 -97
View File
@@ -1126,7 +1126,7 @@
},
{
"title": "Tasks to Chats API Migration",
"description": "Migrate your integrations from the Coder Tasks API to the newer Coder Agents Chats API.",
"description": "Migrate your integrations from the deprecated Coder Tasks API to the Coder Agents Chats API.",
"path": "./ai-coder/agents/tasks-to-chats-migration.md"
}
]
@@ -1351,53 +1351,6 @@
"description": "Connect external AI coding agents to Coder using its built-in Model Context Protocol server.",
"path": "./ai-coder/mcp-server.md",
"state": ["beta"]
},
{
"title": "Coder Tasks",
"description": "Run and manage coding agents like Claude Code and Codex on your own infrastructure with Coder Tasks.",
"path": "./ai-coder/tasks.md",
"children": [
{
"title": "Understanding Coder Tasks",
"description": "Understand the core principles and concepts behind Coder Tasks for managing coding agents.",
"path": "./ai-coder/tasks-core-principles.md"
},
{
"title": "Custom Agents",
"description": "Run custom coding agents beyond the Coder Registry defaults with Coder Tasks.",
"path": "./ai-coder/custom-agents.md"
},
{
"title": "Task Lifecycle",
"description": "Learn how Coder Tasks pause when idle and resume on interaction, and what state is preserved.",
"path": "./ai-coder/tasks-lifecycle.md"
},
{
"title": "Agent Compatibility",
"description": "See which AI coding agents support session persistence across workspace restarts in Coder Tasks.",
"path": "./ai-coder/agent-compatibility.md"
},
{
"title": "Tasks Migration Guide",
"description": "Migrate your task templates for the Coder Tasks changes introduced in version 2.28.0.",
"path": "./ai-coder/tasks-migration.md"
},
{
"title": "Security \u0026 Agent Firewall",
"description": "Learn about security and the Agent Firewall when running AI coding agents in Coder",
"path": "./ai-coder/security.md"
},
{
"title": "Create a GitHub to Coder Tasks Workflow",
"description": "Build a workflow that triggers Coder Tasks from GitHub issues and pull requests.",
"path": "./ai-coder/github-to-tasks.md"
},
{
"title": "Tasks to Chats API Migration",
"description": "Migrate your integrations from the Coder Tasks API to the newer Coder Agents Chats API.",
"path": "./ai-coder/agents/tasks-to-chats-migration.md"
}
]
}
]
},
@@ -1672,10 +1625,6 @@
"title": "Secrets",
"path": "./reference/api/secrets.md"
},
{
"title": "Tasks",
"path": "./reference/api/tasks.md"
},
{
"title": "TemplateBuilder",
"path": "./reference/api/templatebuilder.md"
@@ -2307,51 +2256,6 @@
"description": "Generate a support bundle to troubleshoot issues connecting to a workspace.",
"path": "reference/cli/support_bundle.md"
},
{
"title": "task",
"description": "Manage tasks",
"path": "reference/cli/task.md"
},
{
"title": "task create",
"description": "Create a task",
"path": "reference/cli/task_create.md"
},
{
"title": "task delete",
"description": "Delete tasks",
"path": "reference/cli/task_delete.md"
},
{
"title": "task list",
"description": "List tasks",
"path": "reference/cli/task_list.md"
},
{
"title": "task logs",
"description": "Show a task's logs",
"path": "reference/cli/task_logs.md"
},
{
"title": "task pause",
"description": "Pause a task",
"path": "reference/cli/task_pause.md"
},
{
"title": "task resume",
"description": "Resume a task",
"path": "reference/cli/task_resume.md"
},
{
"title": "task send",
"description": "Send input to a task",
"path": "reference/cli/task_send.md"
},
{
"title": "task status",
"description": "Show the status of a task.",
"path": "reference/cli/task_status.md"
},
{
"title": "templates",
"description": "Manage templates",
+1 -1
View File
@@ -325,6 +325,7 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
"scheme": "string",
"user": {}
},
"enable_ai_tasks": true,
"enable_authz_recording": true,
"enable_terraform_debug_mode": true,
"ephemeral_deployment": true,
@@ -371,7 +372,6 @@ curl -X GET http://coder-server:8080/api/v2/deployment/config \
"refresh": 0,
"threshold_database": 0
},
"hide_ai_tasks": true,
"http_address": "string",
"http_cookies": {
"host_prefix": true,
+3 -785
View File
@@ -5195,28 +5195,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|-------|--------|----------|--------------|-------------|
| `key` | string | false | | |
## codersdk.CreateTaskRequest
```json
{
"display_name": "string",
"input": "string",
"name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|------------------------------|--------|----------|--------------|-------------|
| `display_name` | string | false | | |
| `input` | string | false | | |
| `name` | string | false | | |
| `template_version_id` | string | false | | |
| `template_version_preset_id` | string | false | | |
## codersdk.CreateTemplateRequest
```json
@@ -6177,6 +6155,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
"scheme": "string",
"user": {}
},
"enable_ai_tasks": true,
"enable_authz_recording": true,
"enable_terraform_debug_mode": true,
"ephemeral_deployment": true,
@@ -6223,7 +6202,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
"refresh": 0,
"threshold_database": 0
},
"hide_ai_tasks": true,
"http_address": "string",
"http_cookies": {
"host_prefix": true,
@@ -6805,6 +6783,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
"scheme": "string",
"user": {}
},
"enable_ai_tasks": true,
"enable_authz_recording": true,
"enable_terraform_debug_mode": true,
"ephemeral_deployment": true,
@@ -6851,7 +6830,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
"refresh": 0,
"threshold_database": 0
},
"hide_ai_tasks": true,
"http_address": "string",
"http_cookies": {
"host_prefix": true,
@@ -7188,6 +7166,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
| `disable_path_apps` | boolean | false | | |
| `disable_workspace_sharing` | boolean | false | | |
| `docs_url` | [serpent.URL](#serpenturl) | false | | |
| `enable_ai_tasks` | boolean | false | | |
| `enable_authz_recording` | boolean | false | | |
| `enable_terraform_debug_mode` | boolean | false | | |
| `ephemeral_deployment` | boolean | false | | |
@@ -7196,7 +7175,6 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
| `external_auth_github_default_provider_enable` | boolean | false | | |
| `external_token_encryption_keys` | array of string | false | | |
| `healthcheck` | [codersdk.HealthcheckConfig](#codersdkhealthcheckconfig) | false | | |
| `hide_ai_tasks` | boolean | false | | |
| `http_address` | string | false | | Http address is a string because it may be set to zero to disable. |
| `http_cookies` | [codersdk.HTTPCookieConfig](#codersdkhttpcookieconfig) | false | | |
| `job_hang_detector_interval` | integer | false | | |
@@ -10515,245 +10493,6 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
| `name` | string | true | | |
| `regenerate_token` | boolean | false | | |
## codersdk.PauseTaskResponse
```json
{
"workspace_build": {
"build_number": 0,
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
"job": {
"available_workers": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"canceled_at": "2019-08-24T14:15:22Z",
"completed_at": "2019-08-24T14:15:22Z",
"created_at": "2019-08-24T14:15:22Z",
"error": "string",
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"input": {
"error": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
},
"logs_overflowed": true,
"metadata": {
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_name": "string",
"workspace_build_transition": "start",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string"
},
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"queue_position": 0,
"queue_size": 0,
"started_at": "2019-08-24T14:15:22Z",
"status": "pending",
"tags": {
"property1": "string",
"property2": "string"
},
"type": "template_version_import",
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
"worker_name": "string"
},
"matched_provisioners": {
"available": 0,
"count": 0,
"most_recently_seen": "2019-08-24T14:15:22Z"
},
"max_deadline": "2019-08-24T14:15:22Z",
"reason": "initiator",
"resources": [
{
"agents": [
{
"api_version": "string",
"apps": [
{
"command": "string",
"display_name": "string",
"external": true,
"group": "string",
"health": "disabled",
"healthcheck": {
"interval": 0,
"threshold": 0,
"url": "string"
},
"hidden": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"open_in": "slim-window",
"sharing_level": "owner",
"slug": "string",
"statuses": [
{
"agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
"app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
"created_at": "2019-08-24T14:15:22Z",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"message": "string",
"needs_user_attention": true,
"state": "working",
"uri": "string",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
],
"subdomain": true,
"subdomain_name": "string",
"tooltip": "string",
"url": "string"
}
],
"architecture": "string",
"connection_timeout_seconds": 0,
"created_at": "2019-08-24T14:15:22Z",
"directory": "string",
"disconnected_at": "2019-08-24T14:15:22Z",
"display_apps": [
"vscode"
],
"environment_variables": {
"property1": "string",
"property2": "string"
},
"expanded_directory": "string",
"first_connected_at": "2019-08-24T14:15:22Z",
"health": {
"healthy": false,
"reason": "agent has lost connection"
},
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"instance_id": "string",
"last_connected_at": "2019-08-24T14:15:22Z",
"latency": {
"property1": {
"latency_ms": 0,
"preferred": true
},
"property2": {
"latency_ms": 0,
"preferred": true
}
},
"lifecycle_state": "created",
"log_sources": [
{
"created_at": "2019-08-24T14:15:22Z",
"display_name": "string",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
],
"logs_length": 0,
"logs_overflowed": true,
"metadata": [
{
"description": {
"display_name": "string",
"interval": 0,
"key": "string",
"script": "string",
"timeout": 0
},
"result": {
"age": 0,
"collected_at": "2019-08-24T14:15:22Z",
"error": "string",
"value": "string"
}
}
],
"name": "string",
"operating_system": "string",
"parent_id": {
"uuid": "string",
"valid": true
},
"ready_at": "2019-08-24T14:15:22Z",
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"scripts": [
{
"cron": "string",
"display_name": "string",
"exit_code": 0,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"log_path": "string",
"log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
"run_on_start": true,
"run_on_stop": true,
"script": "string",
"start_blocks_login": true,
"status": "ok",
"timeout": 0
}
],
"started_at": "2019-08-24T14:15:22Z",
"startup_script_behavior": "blocking",
"status": "connecting",
"subsystems": [
"envbox"
],
"troubleshooting_url": "string",
"updated_at": "2019-08-24T14:15:22Z",
"version": "string"
}
],
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"hide": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
"metadata": [
{
"key": "string",
"sensitive": true,
"value": "string"
}
],
"name": "string",
"type": "string",
"workspace_transition": "start"
}
],
"status": "pending",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"template_version_name": "string",
"template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
"transition": "start",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string",
"workspace_owner_avatar_url": "string",
"workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
"workspace_owner_name": "string"
}
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|-------------------|----------------------------------------------------|----------|--------------|-------------|
| `workspace_build` | [codersdk.WorkspaceBuild](#codersdkworkspacebuild) | false | | |
## codersdk.Permission
```json
@@ -11884,245 +11623,6 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
| `message` | string | false | | Message is an actionable message that depicts actions the request took. These messages should be fully formed sentences with proper punctuation. Examples: - "A user has been created." - "Failed to create a user." |
| `validations` | array of [codersdk.ValidationError](#codersdkvalidationerror) | false | | Validations are form field-specific friendly error messages. They will be shown on a form field in the UI. These can also be used to add additional context if there is a set of errors in the primary 'Message'. |
## codersdk.ResumeTaskResponse
```json
{
"workspace_build": {
"build_number": 0,
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
"job": {
"available_workers": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"canceled_at": "2019-08-24T14:15:22Z",
"completed_at": "2019-08-24T14:15:22Z",
"created_at": "2019-08-24T14:15:22Z",
"error": "string",
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"input": {
"error": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
},
"logs_overflowed": true,
"metadata": {
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_name": "string",
"workspace_build_transition": "start",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string"
},
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"queue_position": 0,
"queue_size": 0,
"started_at": "2019-08-24T14:15:22Z",
"status": "pending",
"tags": {
"property1": "string",
"property2": "string"
},
"type": "template_version_import",
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
"worker_name": "string"
},
"matched_provisioners": {
"available": 0,
"count": 0,
"most_recently_seen": "2019-08-24T14:15:22Z"
},
"max_deadline": "2019-08-24T14:15:22Z",
"reason": "initiator",
"resources": [
{
"agents": [
{
"api_version": "string",
"apps": [
{
"command": "string",
"display_name": "string",
"external": true,
"group": "string",
"health": "disabled",
"healthcheck": {
"interval": 0,
"threshold": 0,
"url": "string"
},
"hidden": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"open_in": "slim-window",
"sharing_level": "owner",
"slug": "string",
"statuses": [
{
"agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
"app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
"created_at": "2019-08-24T14:15:22Z",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"message": "string",
"needs_user_attention": true,
"state": "working",
"uri": "string",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
],
"subdomain": true,
"subdomain_name": "string",
"tooltip": "string",
"url": "string"
}
],
"architecture": "string",
"connection_timeout_seconds": 0,
"created_at": "2019-08-24T14:15:22Z",
"directory": "string",
"disconnected_at": "2019-08-24T14:15:22Z",
"display_apps": [
"vscode"
],
"environment_variables": {
"property1": "string",
"property2": "string"
},
"expanded_directory": "string",
"first_connected_at": "2019-08-24T14:15:22Z",
"health": {
"healthy": false,
"reason": "agent has lost connection"
},
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"instance_id": "string",
"last_connected_at": "2019-08-24T14:15:22Z",
"latency": {
"property1": {
"latency_ms": 0,
"preferred": true
},
"property2": {
"latency_ms": 0,
"preferred": true
}
},
"lifecycle_state": "created",
"log_sources": [
{
"created_at": "2019-08-24T14:15:22Z",
"display_name": "string",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
],
"logs_length": 0,
"logs_overflowed": true,
"metadata": [
{
"description": {
"display_name": "string",
"interval": 0,
"key": "string",
"script": "string",
"timeout": 0
},
"result": {
"age": 0,
"collected_at": "2019-08-24T14:15:22Z",
"error": "string",
"value": "string"
}
}
],
"name": "string",
"operating_system": "string",
"parent_id": {
"uuid": "string",
"valid": true
},
"ready_at": "2019-08-24T14:15:22Z",
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"scripts": [
{
"cron": "string",
"display_name": "string",
"exit_code": 0,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"log_path": "string",
"log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
"run_on_start": true,
"run_on_stop": true,
"script": "string",
"start_blocks_login": true,
"status": "ok",
"timeout": 0
}
],
"started_at": "2019-08-24T14:15:22Z",
"startup_script_behavior": "blocking",
"status": "connecting",
"subsystems": [
"envbox"
],
"troubleshooting_url": "string",
"updated_at": "2019-08-24T14:15:22Z",
"version": "string"
}
],
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"hide": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
"metadata": [
{
"key": "string",
"sensitive": true,
"value": "string"
}
],
"name": "string",
"type": "string",
"workspace_transition": "start"
}
],
"status": "pending",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"template_version_name": "string",
"template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
"transition": "start",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string",
"workspace_owner_avatar_url": "string",
"workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
"workspace_owner_name": "string"
}
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|-------------------|----------------------------------------------------|----------|--------------|-------------|
| `workspace_build` | [codersdk.WorkspaceBuild](#codersdkworkspacebuild) | false | | |
## codersdk.RetentionConfig
```json
@@ -12521,274 +12021,6 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
| `redirect_http` | boolean | false | | |
| `supported_ciphers` | array of string | false | | |
## codersdk.Task
```json
{
"created_at": "2019-08-24T14:15:22Z",
"current_state": {
"message": "string",
"state": "working",
"timestamp": "2019-08-24T14:15:22Z",
"uri": "string"
},
"display_name": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initial_prompt": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"owner_avatar_url": "string",
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
"owner_name": "string",
"status": "pending",
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_agent_health": {
"healthy": false,
"reason": "agent has lost connection"
},
"workspace_agent_id": {
"uuid": "string",
"valid": true
},
"workspace_agent_lifecycle": "created",
"workspace_app_id": {
"uuid": "string",
"valid": true
},
"workspace_build_number": 0,
"workspace_id": {
"uuid": "string",
"valid": true
},
"workspace_name": "string",
"workspace_status": "pending"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|-----------------------------|----------------------------------------------------------------------|----------|--------------|-------------|
| `created_at` | string | false | | |
| `current_state` | [codersdk.TaskStateEntry](#codersdktaskstateentry) | false | | |
| `display_name` | string | false | | |
| `id` | string | false | | |
| `initial_prompt` | string | false | | |
| `name` | string | false | | |
| `organization_id` | string | false | | |
| `owner_avatar_url` | string | false | | |
| `owner_id` | string | false | | |
| `owner_name` | string | false | | |
| `status` | [codersdk.TaskStatus](#codersdktaskstatus) | false | | |
| `template_display_name` | string | false | | |
| `template_icon` | string | false | | |
| `template_id` | string | false | | |
| `template_name` | string | false | | |
| `template_version_id` | string | false | | |
| `updated_at` | string | false | | |
| `workspace_agent_health` | [codersdk.WorkspaceAgentHealth](#codersdkworkspaceagenthealth) | false | | |
| `workspace_agent_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `workspace_agent_lifecycle` | [codersdk.WorkspaceAgentLifecycle](#codersdkworkspaceagentlifecycle) | false | | |
| `workspace_app_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `workspace_build_number` | integer | false | | |
| `workspace_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `workspace_name` | string | false | | |
| `workspace_status` | [codersdk.WorkspaceStatus](#codersdkworkspacestatus) | false | | |
#### Enumerated Values
| Property | Value(s) |
|--------------------|-------------------------------------------------------------------------------------------------------------------|
| `status` | `active`, `error`, `initializing`, `paused`, `pending`, `unknown` |
| `workspace_status` | `canceled`, `canceling`, `deleted`, `deleting`, `failed`, `pending`, `running`, `starting`, `stopped`, `stopping` |
## codersdk.TaskLogEntry
```json
{
"content": "string",
"id": 0,
"time": "2019-08-24T14:15:22Z",
"type": "input"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|-----------|----------------------------------------------|----------|--------------|-------------|
| `content` | string | false | | |
| `id` | integer | false | | |
| `time` | string | false | | |
| `type` | [codersdk.TaskLogType](#codersdktasklogtype) | false | | |
## codersdk.TaskLogType
```json
"input"
```
### Properties
#### Enumerated Values
| Value(s) |
|-------------------|
| `input`, `output` |
## codersdk.TaskLogsResponse
```json
{
"logs": [
{
"content": "string",
"id": 0,
"time": "2019-08-24T14:15:22Z",
"type": "input"
}
],
"snapshot": true,
"snapshot_at": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|---------------------------------------------------------|----------|--------------|-------------|
| `logs` | array of [codersdk.TaskLogEntry](#codersdktasklogentry) | false | | |
| `snapshot` | boolean | false | | |
| `snapshot_at` | string | false | | |
## codersdk.TaskSendRequest
```json
{
"input": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `input` | string | false | | |
## codersdk.TaskState
```json
"working"
```
### Properties
#### Enumerated Values
| Value(s) |
|-----------------------------------------|
| `complete`, `failed`, `idle`, `working` |
## codersdk.TaskStateEntry
```json
{
"message": "string",
"state": "working",
"timestamp": "2019-08-24T14:15:22Z",
"uri": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|-------------|------------------------------------------|----------|--------------|-------------|
| `message` | string | false | | |
| `state` | [codersdk.TaskState](#codersdktaskstate) | false | | |
| `timestamp` | string | false | | |
| `uri` | string | false | | |
## codersdk.TaskStatus
```json
"pending"
```
### Properties
#### Enumerated Values
| Value(s) |
|-------------------------------------------------------------------|
| `active`, `error`, `initializing`, `paused`, `pending`, `unknown` |
## codersdk.TasksListResponse
```json
{
"count": 0,
"tasks": [
{
"created_at": "2019-08-24T14:15:22Z",
"current_state": {
"message": "string",
"state": "working",
"timestamp": "2019-08-24T14:15:22Z",
"uri": "string"
},
"display_name": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initial_prompt": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"owner_avatar_url": "string",
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
"owner_name": "string",
"status": "pending",
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_agent_health": {
"healthy": false,
"reason": "agent has lost connection"
},
"workspace_agent_id": {
"uuid": "string",
"valid": true
},
"workspace_agent_lifecycle": "created",
"workspace_app_id": {
"uuid": "string",
"valid": true
},
"workspace_build_number": 0,
"workspace_id": {
"uuid": "string",
"valid": true
},
"workspace_name": "string",
"workspace_status": "pending"
}
]
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------|-----------------------------------------|----------|--------------|-------------|
| `count` | integer | false | | |
| `tasks` | array of [codersdk.Task](#codersdktask) | false | | |
## codersdk.TelemetryConfig
```json
@@ -14542,20 +13774,6 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
|---------|-----------------|----------|--------------|-------------|
| `roles` | array of string | false | | |
## codersdk.UpdateTaskInputRequest
```json
{
"input": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `input` | string | false | | |
## codersdk.UpdateTemplateACL
```json
-981
View File
@@ -1,981 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: Tasks
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
## List AI tasks
### Code samples
```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/tasks \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /api/v2/tasks`
### Parameters
| Name | In | Type | Required | Description |
|------|-------|--------|----------|---------------------------------------------------------------------------------------------------------------------------|
| `q` | query | string | false | Search query for filtering tasks. Supports: `owner:<username/uuid/me>`, `organization:<org-name/uuid>`, `status:<status>` |
### Example responses
> 200 Response
```json
{
"count": 0,
"tasks": [
{
"created_at": "2019-08-24T14:15:22Z",
"current_state": {
"message": "string",
"state": "working",
"timestamp": "2019-08-24T14:15:22Z",
"uri": "string"
},
"display_name": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initial_prompt": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"owner_avatar_url": "string",
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
"owner_name": "string",
"status": "pending",
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_agent_health": {
"healthy": false,
"reason": "agent has lost connection"
},
"workspace_agent_id": {
"uuid": "string",
"valid": true
},
"workspace_agent_lifecycle": "created",
"workspace_app_id": {
"uuid": "string",
"valid": true
},
"workspace_build_number": 0,
"workspace_id": {
"uuid": "string",
"valid": true
},
"workspace_name": "string",
"workspace_status": "pending"
}
]
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.TasksListResponse](schemas.md#codersdktaskslistresponse) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Create a new AI task
### Code samples
```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/tasks/{user} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /api/v2/tasks/{user}`
> Body parameter
```json
{
"display_name": "string",
"input": "string",
"name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1"
}
```
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------------------------------------------------------------------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `body` | body | [codersdk.CreateTaskRequest](schemas.md#codersdkcreatetaskrequest) | true | Create task request |
### Example responses
> 201 Response
```json
{
"created_at": "2019-08-24T14:15:22Z",
"current_state": {
"message": "string",
"state": "working",
"timestamp": "2019-08-24T14:15:22Z",
"uri": "string"
},
"display_name": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initial_prompt": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"owner_avatar_url": "string",
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
"owner_name": "string",
"status": "pending",
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_agent_health": {
"healthy": false,
"reason": "agent has lost connection"
},
"workspace_agent_id": {
"uuid": "string",
"valid": true
},
"workspace_agent_lifecycle": "created",
"workspace_app_id": {
"uuid": "string",
"valid": true
},
"workspace_build_number": 0,
"workspace_id": {
"uuid": "string",
"valid": true
},
"workspace_name": "string",
"workspace_status": "pending"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|--------------------------------------------------------------|-------------|------------------------------------------|
| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.Task](schemas.md#codersdktask) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Get AI task by ID or name
### Code samples
```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/tasks/{user}/{task} \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /api/v2/tasks/{user}/{task}`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string | true | Task ID, or task name |
### Example responses
> 200 Response
```json
{
"created_at": "2019-08-24T14:15:22Z",
"current_state": {
"message": "string",
"state": "working",
"timestamp": "2019-08-24T14:15:22Z",
"uri": "string"
},
"display_name": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initial_prompt": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"owner_avatar_url": "string",
"owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
"owner_name": "string",
"status": "pending",
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_agent_health": {
"healthy": false,
"reason": "agent has lost connection"
},
"workspace_agent_id": {
"uuid": "string",
"valid": true
},
"workspace_agent_lifecycle": "created",
"workspace_app_id": {
"uuid": "string",
"valid": true
},
"workspace_build_number": 0,
"workspace_id": {
"uuid": "string",
"valid": true
},
"workspace_name": "string",
"workspace_status": "pending"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.Task](schemas.md#codersdktask) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Delete AI task
### Code samples
```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/tasks/{user}/{task} \
-H 'Coder-Session-Token: API_KEY'
```
`DELETE /api/v2/tasks/{user}/{task}`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string | true | Task ID, or task name |
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------------|-------------|--------|
| 202 | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Accepted | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Update AI task input
### Code samples
```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/tasks/{user}/{task}/input \
-H 'Content-Type: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`PATCH /api/v2/tasks/{user}/{task}/input`
> Body parameter
```json
{
"input": "string"
}
```
### Parameters
| Name | In | Type | Required | Description |
|--------|------|------------------------------------------------------------------------------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string | true | Task ID, or task name |
| `body` | body | [codersdk.UpdateTaskInputRequest](schemas.md#codersdkupdatetaskinputrequest) | true | Update task input request |
### Responses
| Status | Meaning | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204 | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Get AI task logs
### Code samples
```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/tasks/{user}/{task}/logs \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /api/v2/tasks/{user}/{task}/logs`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string | true | Task ID, or task name |
### Example responses
> 200 Response
```json
{
"logs": [
{
"content": "string",
"id": 0,
"time": "2019-08-24T14:15:22Z",
"type": "input"
}
],
"snapshot": true,
"snapshot_at": "string"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.TaskLogsResponse](schemas.md#codersdktasklogsresponse) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Pause task
### Code samples
```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/tasks/{user}/{task}/pause \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /api/v2/tasks/{user}/{task}/pause`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string(uuid) | true | Task ID |
### Example responses
> 202 Response
```json
{
"workspace_build": {
"build_number": 0,
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
"job": {
"available_workers": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"canceled_at": "2019-08-24T14:15:22Z",
"completed_at": "2019-08-24T14:15:22Z",
"created_at": "2019-08-24T14:15:22Z",
"error": "string",
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"input": {
"error": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
},
"logs_overflowed": true,
"metadata": {
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_name": "string",
"workspace_build_transition": "start",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string"
},
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"queue_position": 0,
"queue_size": 0,
"started_at": "2019-08-24T14:15:22Z",
"status": "pending",
"tags": {
"property1": "string",
"property2": "string"
},
"type": "template_version_import",
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
"worker_name": "string"
},
"matched_provisioners": {
"available": 0,
"count": 0,
"most_recently_seen": "2019-08-24T14:15:22Z"
},
"max_deadline": "2019-08-24T14:15:22Z",
"reason": "initiator",
"resources": [
{
"agents": [
{
"api_version": "string",
"apps": [
{
"command": "string",
"display_name": "string",
"external": true,
"group": "string",
"health": "disabled",
"healthcheck": {
"interval": 0,
"threshold": 0,
"url": "string"
},
"hidden": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"open_in": "slim-window",
"sharing_level": "owner",
"slug": "string",
"statuses": [
{
"agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
"app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
"created_at": "2019-08-24T14:15:22Z",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"message": "string",
"needs_user_attention": true,
"state": "working",
"uri": "string",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
],
"subdomain": true,
"subdomain_name": "string",
"tooltip": "string",
"url": "string"
}
],
"architecture": "string",
"connection_timeout_seconds": 0,
"created_at": "2019-08-24T14:15:22Z",
"directory": "string",
"disconnected_at": "2019-08-24T14:15:22Z",
"display_apps": [
"vscode"
],
"environment_variables": {
"property1": "string",
"property2": "string"
},
"expanded_directory": "string",
"first_connected_at": "2019-08-24T14:15:22Z",
"health": {
"healthy": false,
"reason": "agent has lost connection"
},
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"instance_id": "string",
"last_connected_at": "2019-08-24T14:15:22Z",
"latency": {
"property1": {
"latency_ms": 0,
"preferred": true
},
"property2": {
"latency_ms": 0,
"preferred": true
}
},
"lifecycle_state": "created",
"log_sources": [
{
"created_at": "2019-08-24T14:15:22Z",
"display_name": "string",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
],
"logs_length": 0,
"logs_overflowed": true,
"metadata": [
{
"description": {
"display_name": "string",
"interval": 0,
"key": "string",
"script": "string",
"timeout": 0
},
"result": {
"age": 0,
"collected_at": "2019-08-24T14:15:22Z",
"error": "string",
"value": "string"
}
}
],
"name": "string",
"operating_system": "string",
"parent_id": {
"uuid": "string",
"valid": true
},
"ready_at": "2019-08-24T14:15:22Z",
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"scripts": [
{
"cron": "string",
"display_name": "string",
"exit_code": 0,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"log_path": "string",
"log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
"run_on_start": true,
"run_on_stop": true,
"script": "string",
"start_blocks_login": true,
"status": "ok",
"timeout": 0
}
],
"started_at": "2019-08-24T14:15:22Z",
"startup_script_behavior": "blocking",
"status": "connecting",
"subsystems": [
"envbox"
],
"troubleshooting_url": "string",
"updated_at": "2019-08-24T14:15:22Z",
"version": "string"
}
],
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"hide": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
"metadata": [
{
"key": "string",
"sensitive": true,
"value": "string"
}
],
"name": "string",
"type": "string",
"workspace_transition": "start"
}
],
"status": "pending",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"template_version_name": "string",
"template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
"transition": "start",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string",
"workspace_owner_avatar_url": "string",
"workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
"workspace_owner_name": "string"
}
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 202 | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Accepted | [codersdk.PauseTaskResponse](schemas.md#codersdkpausetaskresponse) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Resume task
### Code samples
```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/tasks/{user}/{task}/resume \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /api/v2/tasks/{user}/{task}/resume`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string(uuid) | true | Task ID |
### Example responses
> 202 Response
```json
{
"workspace_build": {
"build_number": 0,
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"deadline": "2019-08-24T14:15:22Z",
"has_ai_task": true,
"has_external_agent": true,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"initiator_name": "string",
"job": {
"available_workers": [
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
],
"canceled_at": "2019-08-24T14:15:22Z",
"completed_at": "2019-08-24T14:15:22Z",
"created_at": "2019-08-24T14:15:22Z",
"error": "string",
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
"input": {
"error": "string",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
},
"logs_overflowed": true,
"metadata": {
"template_display_name": "string",
"template_icon": "string",
"template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
"template_name": "string",
"template_version_name": "string",
"workspace_build_transition": "start",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string"
},
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"queue_position": 0,
"queue_size": 0,
"started_at": "2019-08-24T14:15:22Z",
"status": "pending",
"tags": {
"property1": "string",
"property2": "string"
},
"type": "template_version_import",
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
"worker_name": "string"
},
"matched_provisioners": {
"available": 0,
"count": 0,
"most_recently_seen": "2019-08-24T14:15:22Z"
},
"max_deadline": "2019-08-24T14:15:22Z",
"reason": "initiator",
"resources": [
{
"agents": [
{
"api_version": "string",
"apps": [
{
"command": "string",
"display_name": "string",
"external": true,
"group": "string",
"health": "disabled",
"healthcheck": {
"interval": 0,
"threshold": 0,
"url": "string"
},
"hidden": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"open_in": "slim-window",
"sharing_level": "owner",
"slug": "string",
"statuses": [
{
"agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
"app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
"created_at": "2019-08-24T14:15:22Z",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"message": "string",
"needs_user_attention": true,
"state": "working",
"uri": "string",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
],
"subdomain": true,
"subdomain_name": "string",
"tooltip": "string",
"url": "string"
}
],
"architecture": "string",
"connection_timeout_seconds": 0,
"created_at": "2019-08-24T14:15:22Z",
"directory": "string",
"disconnected_at": "2019-08-24T14:15:22Z",
"display_apps": [
"vscode"
],
"environment_variables": {
"property1": "string",
"property2": "string"
},
"expanded_directory": "string",
"first_connected_at": "2019-08-24T14:15:22Z",
"health": {
"healthy": false,
"reason": "agent has lost connection"
},
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"instance_id": "string",
"last_connected_at": "2019-08-24T14:15:22Z",
"latency": {
"property1": {
"latency_ms": 0,
"preferred": true
},
"property2": {
"latency_ms": 0,
"preferred": true
}
},
"lifecycle_state": "created",
"log_sources": [
{
"created_at": "2019-08-24T14:15:22Z",
"display_name": "string",
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
],
"logs_length": 0,
"logs_overflowed": true,
"metadata": [
{
"description": {
"display_name": "string",
"interval": 0,
"key": "string",
"script": "string",
"timeout": 0
},
"result": {
"age": 0,
"collected_at": "2019-08-24T14:15:22Z",
"error": "string",
"value": "string"
}
}
],
"name": "string",
"operating_system": "string",
"parent_id": {
"uuid": "string",
"valid": true
},
"ready_at": "2019-08-24T14:15:22Z",
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
"scripts": [
{
"cron": "string",
"display_name": "string",
"exit_code": 0,
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"log_path": "string",
"log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
"run_on_start": true,
"run_on_stop": true,
"script": "string",
"start_blocks_login": true,
"status": "ok",
"timeout": 0
}
],
"started_at": "2019-08-24T14:15:22Z",
"startup_script_behavior": "blocking",
"status": "connecting",
"subsystems": [
"envbox"
],
"troubleshooting_url": "string",
"updated_at": "2019-08-24T14:15:22Z",
"version": "string"
}
],
"created_at": "2019-08-24T14:15:22Z",
"daily_cost": 0,
"hide": true,
"icon": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
"metadata": [
{
"key": "string",
"sensitive": true,
"value": "string"
}
],
"name": "string",
"type": "string",
"workspace_transition": "start"
}
],
"status": "pending",
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
"template_version_name": "string",
"template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
"transition": "start",
"updated_at": "2019-08-24T14:15:22Z",
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
"workspace_name": "string",
"workspace_owner_avatar_url": "string",
"workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
"workspace_owner_name": "string"
}
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 202 | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Accepted | [codersdk.ResumeTaskResponse](schemas.md#codersdkresumetaskresponse) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Send input to AI task
### Code samples
```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/tasks/{user}/{task}/send \
-H 'Content-Type: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /api/v2/tasks/{user}/{task}/send`
> Body parameter
```json
{
"input": "string"
}
```
### Parameters
| Name | In | Type | Required | Description |
|--------|------|----------------------------------------------------------------|----------|-------------------------------------------------------|
| `user` | path | string | true | Username, user ID, or 'me' for the authenticated user |
| `task` | path | string | true | Task ID, or task name |
| `body` | body | [codersdk.TaskSendRequest](schemas.md#codersdktasksendrequest) | true | Task input request |
### Responses
| Status | Meaning | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204 | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Upload task log snapshot
### Code samples
```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/me/tasks/{task}/log-snapshot?format=agentapi \
-H 'Content-Type: application/json' \
-H 'Accept: */*' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /api/v2/workspaceagents/me/tasks/{task}/log-snapshot`
> Body parameter
```json
{}
```
### Parameters
| Name | In | Type | Required | Description |
|----------|-------|--------------|----------|--------------------------------------------------------------|
| `task` | path | string(uuid) | true | Task ID |
| `format` | query | string | true | Snapshot format |
| `body` | body | object | true | Raw snapshot payload (structure depends on format parameter) |
#### Enumerated Values
| Parameter | Value(s) |
|-----------|------------|
| `format` | `agentapi` |
### Example responses
> 413 Response
### Responses
| Status | Meaning | Description | Schema |
|--------|-------------------------------------------------------------------------|-----------------------------|--------------------------------------------------|
| 204 | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content | |
| 413 | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 64 KiB | [codersdk.Response](schemas.md#codersdkresponse) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
-1
View File
@@ -44,7 +44,6 @@ Coder — A tool for provisioning self-hosted development environments with Terr
| [<code>reset-password</code>](./reset-password.md) | Directly connect to the database to reset a user's password |
| [<code>secret</code>](./secret.md) | Manage secrets |
| [<code>state</code>](./state.md) | Manually manage Terraform state to fix broken workspaces |
| [<code>task</code>](./task.md) | Manage tasks |
| [<code>templates</code>](./templates.md) | Manage templates |
| [<code>tokens</code>](./tokens.md) | Manage personal access tokens |
| [<code>users</code>](./users.md) | Manage users |
-11
View File
@@ -1738,17 +1738,6 @@ The upper limit of attempts to send a notification.
How often to reconcile workspace prebuilds state.
### --hide-ai-tasks
| | |
|-------------|-----------------------------------|
| Type | <code>bool</code> |
| Environment | <code>$CODER_HIDE_AI_TASKS</code> |
| YAML | <code>client.hideAITasks</code> |
| Default | <code>false</code> |
Hide AI tasks from the dashboard.
### --chat-debug-logging-enabled
| | |
-32
View File
@@ -1,32 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task
description: Manage tasks
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Manage tasks
Aliases:
* tasks
## Usage
```console
coder task
```
## Subcommands
| Name | Purpose |
|-----------------------------------------|----------------------------|
| [<code>create</code>](./task_create.md) | Create a task |
| [<code>delete</code>](./task_delete.md) | Delete tasks |
| [<code>list</code>](./task_list.md) | List tasks |
| [<code>logs</code>](./task_logs.md) | Show a task's logs |
| [<code>pause</code>](./task_pause.md) | Pause a task |
| [<code>resume</code>](./task_resume.md) | Resume a task |
| [<code>send</code>](./task_send.md) | Send input to a task |
| [<code>status</code>](./task_status.md) | Show the status of a task. |
-105
View File
@@ -1,105 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task create
description: Create a task
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Create a task
## Usage
```console
coder task create [flags] [input]
```
## Description
```console
- Create a task with direct input:
$ coder task create "Add authentication to the user service"
- Create a task with stdin input:
$ echo "Add authentication to the user service" | coder task create
- Create a task with a specific name:
$ coder task create --name task1 "Add authentication to the user service"
- Create a task from a specific template / preset:
$ coder task create --template backend-dev --preset "My Preset" "Add authentication to the user service"
- Create a task for another user (requires appropriate permissions):
$ coder task create --owner user@example.com "Add authentication to the user service"
```
## Options
### --name
| | |
|------|---------------------|
| Type | <code>string</code> |
Specify the name of the task. If you do not specify one, a name will be generated for you.
### --owner
| | |
|---------|---------------------|
| Type | <code>string</code> |
| Default | <code>me</code> |
Specify the owner of the task. Defaults to the current user.
### --template
| | |
|-------------|----------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_TASK_TEMPLATE_NAME</code> |
### --template-version
| | |
|-------------|-------------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_TASK_TEMPLATE_VERSION</code> |
### --preset
| | |
|-------------|--------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_TASK_PRESET_NAME</code> |
| Default | <code>none</code> |
### --stdin
| | |
|------|-------------------|
| Type | <code>bool</code> |
Reads from stdin for the task input.
### -q, --quiet
| | |
|------|-------------------|
| Type | <code>bool</code> |
Only display the created task's ID.
### -O, --org
| | |
|-------------|----------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_ORGANIZATION</code> |
Select which organization (uuid or name) to use.
-45
View File
@@ -1,45 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task delete
description: Delete tasks
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Delete tasks
Aliases:
* rm
## Usage
```console
coder task delete [flags] <task> [<task> ...]
```
## Description
```console
- Delete a single task.:
$ $ coder task delete task1
- Delete multiple tasks.:
$ $ coder task delete task1 task2 task3
- Delete a task without confirmation.:
$ $ coder task delete task4 --yes
```
## Options
### -y, --yes
| | |
|------|-------------------|
| Type | <code>bool</code> |
Bypass confirmation prompts.
-97
View File
@@ -1,97 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task list
description: List tasks
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
List tasks
Aliases:
* ls
## Usage
```console
coder task list [flags]
```
## Description
```console
- List tasks for the current user.:
$ coder task list
- List tasks for a specific user.:
$ coder task list --user someone-else
- List all tasks you can view.:
$ coder task list --all
- List all your running tasks.:
$ coder task list --status running
- As above, but only show IDs.:
$ coder task list --status running --quiet
```
## Options
### --status
| | |
|------|--------------------------------------------------------------------|
| Type | <code>pending\|initializing\|active\|paused\|error\|unknown</code> |
Filter by task status.
### -a, --all
| | |
|---------|--------------------|
| Type | <code>bool</code> |
| Default | <code>false</code> |
List tasks for all users you can view.
### --user
| | |
|------|---------------------|
| Type | <code>string</code> |
List tasks for the specified user (username, "me").
### -q, --quiet
| | |
|---------|--------------------|
| Type | <code>bool</code> |
| Default | <code>false</code> |
Only display task IDs.
### -c, --column
| | |
|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type | <code>[id\|organization id\|owner id\|owner name\|owner avatar url\|name\|display name\|template id\|template version id\|template name\|template display name\|template icon\|workspace id\|workspace name\|workspace status\|workspace build number\|workspace agent id\|workspace agent lifecycle\|workspace agent health\|workspace app id\|initial prompt\|status\|state\|message\|created at\|updated at\|state changed]</code> |
| Default | <code>name,status,state,state changed,message</code> |
Columns to display in table output.
### -o, --output
| | |
|---------|--------------------------|
| Type | <code>table\|json</code> |
| Default | <code>table</code> |
Output format.
-43
View File
@@ -1,43 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task logs
description: "Show a task's logs"
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Show a task's logs
## Usage
```console
coder task logs [flags] <task>
```
## Description
```console
- Show logs for a given task.:
$ coder task logs task1
```
## Options
### -c, --column
| | |
|---------|----------------------------------------|
| Type | <code>[id\|content\|type\|time]</code> |
| Default | <code>type,content</code> |
Columns to display in table output.
### -o, --output
| | |
|---------|--------------------------|
| Type | <code>table\|json</code> |
| Default | <code>table</code> |
Output format.
-41
View File
@@ -1,41 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task pause
description: Pause a task
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Pause a task
## Usage
```console
coder task pause [flags] <task>
```
## Description
```console
- Pause a task by name:
$ coder task pause my-task
- Pause another user's task:
$ coder task pause alice/my-task
- Pause a task without confirmation:
$ coder task pause my-task --yes
```
## Options
### -y, --yes
| | |
|------|-------------------|
| Type | <code>bool</code> |
Bypass confirmation prompts.
-49
View File
@@ -1,49 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task resume
description: Resume a task
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Resume a task
## Usage
```console
coder task resume [flags] <task>
```
## Description
```console
- Resume a task by name:
$ coder task resume my-task
- Resume another user's task:
$ coder task resume alice/my-task
- Resume a task without confirmation:
$ coder task resume my-task --yes
```
## Options
### --no-wait
| | |
|------|-------------------|
| Type | <code>bool</code> |
Return immediately after resuming the task.
### -y, --yes
| | |
|------|-------------------|
| Type | <code>bool</code> |
Bypass confirmation prompts.
-38
View File
@@ -1,38 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task send
description: Send input to a task
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Send input to a task
## Usage
```console
coder task send [flags] <task> [<input> | --stdin]
```
## Description
```console
Send input to a task. If the task is paused, it will be automatically resumed before input is sent. If the task is initializing, it will wait for the task to become ready.
- Send direct input to a task:
$ coder task send task1 "Please also add unit tests"
- Send input from stdin to a task:
$ echo "Please also add unit tests" | coder task send task1 --stdin
```
## Options
### --stdin
| | |
|------|-------------------|
| Type | <code>bool</code> |
Reads the input from stdin.
-60
View File
@@ -1,60 +0,0 @@
---
# Code generated by make gen. DO NOT EDIT.
title: task status
description: Show the status of a task.
---
<!-- DO NOT EDIT | GENERATED CONTENT -->
Show the status of a task.
Aliases:
* stat
## Usage
```console
coder task status [flags]
```
## Description
```console
- Show the status of a given task.:
$ coder task status task1
- Watch the status of a given task until it completes (idle or stopped).:
$ coder task status task1 --watch
```
## Options
### --watch
| | |
|---------|--------------------|
| Type | <code>bool</code> |
| Default | <code>false</code> |
Watch the task status output. This will stream updates to the terminal until the underlying workspace is stopped.
### -c, --column
| | |
|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type | <code>[id\|organization id\|owner id\|owner name\|owner avatar url\|name\|display name\|template id\|template version id\|template name\|template display name\|template icon\|workspace id\|workspace name\|workspace status\|workspace build number\|workspace agent id\|workspace agent lifecycle\|workspace agent health\|workspace app id\|initial prompt\|status\|state\|message\|created at\|updated at\|state changed\|healthy]</code> |
| Default | <code>state changed,status,healthy,state,message</code> |
Columns to display in table output.
### -o, --output
| | |
|---------|--------------------------|
| Type | <code>table\|json</code> |
| Default | <code>table</code> |
Output format.
+3 -3
View File
@@ -18,8 +18,8 @@ coder templates init [flags] [directory]
### --id
| | |
|------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type | <code>aws-devcontainer\|aws-linux\|aws-windows\|azure-linux\|digitalocean-linux\|docker\|docker-devcontainer\|docker-envbuilder\|gcp-devcontainer\|gcp-linux\|gcp-vm-container\|gcp-windows\|incus\|kubernetes\|kubernetes-devcontainer\|nomad-docker\|quickstart\|scratch\|tasks-docker</code> |
| | |
|------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type | <code>aws-devcontainer\|aws-linux\|aws-windows\|azure-linux\|digitalocean-linux\|docker\|docker-devcontainer\|docker-envbuilder\|gcp-devcontainer\|gcp-linux\|gcp-vm-container\|gcp-windows\|incus\|kubernetes\|kubernetes-devcontainer\|nomad-docker\|quickstart\|scratch</code> |
Specify a given example template by ID.
-5
View File
@@ -175,11 +175,6 @@ Refer to [Connection logs](../admin/monitoring/connection-logs.md).
The collective term for `coderd`, its provisioners, and its database.
The control plane also runs the agent loop for [Coder Agents](#coder-agents).
### Custom agent
A coding agent you integrate with Coder yourself, beyond the built-in options.
Refer to [Custom agents](../ai-coder/custom-agents.md).
### Custom roles
Deployment-defined roles composed of specific RBAC actions.
+1 -1
View File
@@ -14,7 +14,7 @@ This is helpful in a number of scenarios, including:
- Developers can do ad-hoc debugging or pair programming.
- A workspace can be owned by a group of users for QA, on-call rotations, or shared staging.
- AI workflows where an agent prepares a workspace and a developer takes over to review or finalize the work (ex. with [Coder Tasks](https://coder.com/docs/ai-coder/tasks).)
- AI workflows where an agent prepares a workspace and a developer takes over to review or finalize the work (ex. with [Coder Agents](https://coder.com/docs/ai-coder/agents).)
## Getting Started
+2 -2
View File
@@ -58,8 +58,8 @@ A workspace is considered "active" when Coder detects one or more active session
- **JetBrains IDE sessions**: Using JetBrains Gateway or remote IDE plugins
- **Terminal sessions**: Using the web terminal (including reconnecting to the web terminal)
- **SSH sessions**: Connecting via `coder ssh` or SSH config integration
- **AI agent task status**: When a coding agent reports "working" status via
[Coder Tasks](../ai-coder/tasks.md), the workspace deadline is extended
- **AI agent task status**: When a coding agent reports "working" status, the
workspace deadline is extended
Activity is only detected when there is at least one active session. An open session will keep your workspace marked as active and prevent automatic shutdown.
-3
View File
@@ -291,9 +291,6 @@ Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.
is detected. By default it instructs users to update using 'curl -L
https://coder.com/install.sh | sh'.
--hide-ai-tasks bool, $CODER_HIDE_AI_TASKS (default: false)
Hide AI tasks from the dashboard.
--ssh-config-options string-array, $CODER_SSH_CONFIG_OPTIONS
These SSH config options will override the default SSH config options.
Provide options in "key=value" or "key value" format separated by
@@ -17,7 +17,15 @@ func TestEnterpriseEndpointsDocumented(t *testing.T) {
require.NoError(t, err, "can't parse swagger comments")
require.NotEmpty(t, swaggerComments, "swagger comments must be present")
// Coder Tasks has no swagger annotations because it is withdrawn from the
// product, so verify against a deployment where its routes are not
// registered.
values := coderdtest.DeploymentValues(t)
values.EnableAITasks = false
//nolint: dogsled
_, _, api, _ := coderdenttest.NewWithAPI(t, nil)
_, _, api, _ := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
Options: &coderdtest.Options{DeploymentValues: values},
})
coderdtest.VerifySwaggerDefinitions(t, api.AGPL.APIHandler, swaggerComments, coderdtest.WithSwaggerRoutePrefix("/api/v2"))
}
-14
View File
@@ -230,19 +230,5 @@
"icon": "/emojis/1f4e6.png",
"tags": [],
"markdown": "\n# A minimal Scaffolding for a Coder Template\n\nUse this starter template as a basis to create your own unique template from scratch.\n"
},
{
"id": "tasks-docker",
"url": "",
"name": "Tasks on Docker",
"description": "Run Coder Tasks on Docker with an example application",
"icon": "/icon/tasks.svg",
"tags": [
"docker",
"container",
"ai",
"tasks"
],
"markdown": "\n# Run Coder Tasks on Docker\n\nThis is an example template for running [Coder Tasks](https://coder.com/docs/ai-coder/tasks), Claude Code, along with a [real world application](https://realworld-docs.netlify.app/).\n\n![Tasks](../../.images/tasks-screenshot.png)\n\nThis is a fantastic starting point for working with AI agents with Coder Tasks. Try prompts such as:\n\n- \"Make the background color blue\"\n- \"Add a dark mode\"\n- \"Rewrite the entire backend in Go\"\n\n## Included in this template\n\nThis template is designed to be an example and a reference for building other templates with Coder Tasks. You can always run Coder Tasks on different infrastructure (e.g. as on Kubernetes, VMs) and with your own GitHub repositories, MCP servers, images, etc.\n\nAdditionally, this template uses our [Claude Code](https://registry.coder.com/modules/coder/claude-code) module, but [other agents](https://registry.coder.com/modules?search=tag%3Aagent) or even [custom agents](https://coder.com/docs/ai-coder/custom-agents) can be used in its place.\n\nThis template uses a [Workspace Preset](https://coder.com/docs/admin/templates/extending-templates/parameters#workspace-presets) that pre-defines:\n\n- Universal Container Image (e.g. contains Node.js, Java, Python, Ruby, etc)\n- MCP servers (desktop-commander for long-running logs, playwright for previewing changes)\n- System prompt and [repository](https://github.com/coder-contrib/realworld-django-rest-framework-angular) for the AI agent\n- Startup script to initialize the repository and start the development server\n\n## Add this template to your Coder deployment\n\nYou can also add this template to your Coder deployment and begin tinkering right away!\n\n### Prerequisites\n\n- Coder installed (see [our docs](https://coder.com/docs/install)), ideally a Linux VM with Docker\n- Anthropic API Key (or access to Anthropic models via Bedrock or Vertex, see [Claude Code docs](https://docs.anthropic.com/en/docs/claude-code/third-party-integrations))\n- Access to a Docker socket\n - If on the local VM, ensure the `coder` user is added to the Docker group (docs)\n\n ```sh\n # Add coder user to Docker group\n sudo adduser coder docker\n \n # Restart Coder server\n sudo systemctl restart coder\n \n # Test Docker\n sudo -u coder docker ps\n ```\n\n - If on a remote VM, see the [Docker Terraform provider documentation](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs#remote-hosts) to configure a remote host\n\nTo import this template into Coder, first create a template from \"Scratch\" in the template editor.\n\nVisit this URL for your Coder deployment:\n\n```sh\nhttps://coder.example.com/templates/new?exampleId=scratch\n```\n\nAfter creating the template, paste the contents from [main.tf](https://github.com/coder/registry/blob/main/registry/coder-labs/templates/tasks-docker/main.tf) into the template editor and save.\n\nAlternatively, you can use the Coder CLI to [push the template](https://coder.com/docs/reference/cli/templates_push)\n\n```sh\n# Download the CLI\ncurl -L https://coder.com/install.sh | sh\n\n# Log in to your deployment\ncoder login https://coder.example.com\n\n# Clone the registry\ngit clone https://github.com/coder/registry\ncd registry\n\n# Navigate to this template\ncd registry/coder-labs/templates/tasks-docker\n\n# Push the template\ncoder templates push\n```\n"
}
]
-1
View File
@@ -42,7 +42,6 @@ var (
//go:embed templates/nomad-docker
//go:embed templates/quickstart
//go:embed templates/scratch
//go:embed templates/tasks-docker
files embed.FS
exampleBasePath = "https://github.com/coder/coder/tree/main/examples/templates/"
-87
View File
@@ -1,87 +0,0 @@
---
display_name: Tasks on Docker
description: Run Coder Tasks on Docker with an example application
icon: ../../../site/static/icon/tasks.svg
verified: false
tags: [docker, container, ai, tasks]
maintainer_github: coder
---
# Run Coder Tasks on Docker
This is an example template for running [Coder Tasks](https://coder.com/docs/ai-coder/tasks), Claude Code, along with a [real world application](https://realworld-docs.netlify.app/).
![Tasks](../../.images/tasks-screenshot.png)
This is a fantastic starting point for working with AI agents with Coder Tasks. Try prompts such as:
- "Make the background color blue"
- "Add a dark mode"
- "Rewrite the entire backend in Go"
## Included in this template
This template is designed to be an example and a reference for building other templates with Coder Tasks. You can always run Coder Tasks on different infrastructure (e.g. as on Kubernetes, VMs) and with your own GitHub repositories, MCP servers, images, etc.
Additionally, this template uses our [Claude Code](https://registry.coder.com/modules/coder/claude-code) module, but [other agents](https://registry.coder.com/modules?search=tag%3Aagent) or even [custom agents](https://coder.com/docs/ai-coder/custom-agents) can be used in its place.
This template uses a [Workspace Preset](https://coder.com/docs/admin/templates/extending-templates/parameters#workspace-presets) that pre-defines:
- Universal Container Image (e.g. contains Node.js, Java, Python, Ruby, etc)
- MCP servers (desktop-commander for long-running logs, playwright for previewing changes)
- System prompt and [repository](https://github.com/coder-contrib/realworld-django-rest-framework-angular) for the AI agent
- Startup script to initialize the repository and start the development server
## Add this template to your Coder deployment
You can also add this template to your Coder deployment and begin tinkering right away!
### Prerequisites
- Coder installed (see [our docs](https://coder.com/docs/install)), ideally a Linux VM with Docker
- Anthropic API Key (or access to Anthropic models via Bedrock or Vertex, see [Claude Code docs](https://docs.anthropic.com/en/docs/claude-code/third-party-integrations))
- Access to a Docker socket
- If on the local VM, ensure the `coder` user is added to the Docker group (docs)
```sh
# Add coder user to Docker group
sudo adduser coder docker
# Restart Coder server
sudo systemctl restart coder
# Test Docker
sudo -u coder docker ps
```
- If on a remote VM, see the [Docker Terraform provider documentation](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs#remote-hosts) to configure a remote host
To import this template into Coder, first create a template from "Scratch" in the template editor.
Visit this URL for your Coder deployment:
```sh
https://coder.example.com/templates/new?exampleId=scratch
```
After creating the template, paste the contents from [main.tf](https://github.com/coder/registry/blob/main/registry/coder-labs/templates/tasks-docker/main.tf) into the template editor and save.
Alternatively, you can use the Coder CLI to [push the template](https://coder.com/docs/reference/cli/templates_push)
```sh
# Download the CLI
curl -L https://coder.com/install.sh | sh
# Log in to your deployment
coder login https://coder.example.com
# Clone the registry
git clone https://github.com/coder/registry
cd registry
# Navigate to this template
cd registry/coder-labs/templates/tasks-docker
# Push the template
coder templates push
```
-380
View File
@@ -1,380 +0,0 @@
terraform {
required_providers {
coder = {
source = "coder/coder"
version = ">= 2.13"
}
docker = {
source = "kreuzwerker/docker"
}
}
}
# This template requires a valid Docker socket
# However, you can reference our Kubernetes/VM
# example templates and adapt the Claude Code module
#
# See: https://registry.coder.com/templates
provider "docker" {}
# A `coder_ai_task` resource enables Tasks and associates
# the task with the coder_app that will act as an AI agent.
resource "coder_ai_task" "task" {
count = data.coder_workspace.me.start_count
app_id = module.claude-code[count.index].task_app_id
}
# You can read the task prompt from the `coder_task` data source.
data "coder_task" "me" {}
# The Claude Code module does the automatic task reporting
# Other agent modules: https://registry.coder.com/modules?search=agent
# Or use a custom agent:
module "claude-code" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/claude-code/coder"
version = "4.9.2"
agent_id = coder_agent.main.id
workdir = "/home/coder/projects"
order = 999
claude_api_key = ""
ai_prompt = data.coder_task.me.prompt
system_prompt = data.coder_parameter.system_prompt.value
model = "sonnet"
permission_mode = "plan"
post_install_script = data.coder_parameter.setup_script.value
}
# We are using presets to set the prompts, image, and set up instructions
# See https://coder.com/docs/admin/templates/extending-templates/parameters#workspace-presets
data "coder_workspace_preset" "default" {
name = "Real World App: Angular + Django"
default = true
parameters = {
"system_prompt" = <<-EOT
-- Framing --
You are a helpful assistant that can help with code. You are running inside a Coder Workspace and provide status updates to the user via Coder MCP. Stay on track, feel free to debug, but when the original plan fails, do not choose a different route/architecture without checking the user first.
-- Tool Selection --
- playwright: previewing your changes after you made them
to confirm it worked as expected
- desktop-commander - use only for commands that keep running
(servers, dev watchers, GUI apps).
- Built-in tools - use for everything else:
(file operations, git commands, builds & installs, one-off shell commands)
Remember this decision rule:
- Stays running? → desktop-commander
- Finishes immediately? → built-in tools
-- Context --
There is an existing app and tmux dev server running on port 8000. Be sure to read it's CLAUDE.md (./realworld-django-rest-framework-angular/CLAUDE.md) to learn more about it.
Since this app is for demo purposes and the user is previewing the homepage and subsequent pages, aim to make the first visual change/prototype very quickly so the user can preview it, then focus on backend or logic which can be a more involved, long-running architecture plan.
EOT
"setup_script" = <<-EOT
# Set up projects dir
mkdir -p /home/coder/projects
cd $HOME/projects
# Packages: Install additional packages
sudo apt-get update && sudo apt-get install -y tmux
if ! command -v google-chrome >/dev/null 2>&1; then
yes | npx playwright install chrome
fi
# MCP: Install and configure MCP Servers
npm install -g @wonderwhy-er/desktop-commander
claude mcp add playwright npx -- @playwright/mcp@latest --headless --isolated --no-sandbox
claude mcp add desktop-commander desktop-commander
# Repo: Clone and pull changes from the git repository
if [ ! -d "realworld-django-rest-framework-angular" ]; then
git clone https://github.com/coder-contrib/realworld-django-rest-framework-angular.git
else
cd realworld-django-rest-framework-angular
git fetch
# Check for uncommitted changes
if git diff-index --quiet HEAD -- && \
[ -z "$(git status --porcelain --untracked-files=no)" ] && \
[ -z "$(git log --branches --not --remotes)" ]; then
echo "Repo is clean. Pulling latest changes..."
git pull
else
echo "Repo has uncommitted or unpushed changes. Skipping pull."
fi
cd ..
fi
# Initialize: Start the development server
cd realworld-django-rest-framework-angular && ./start-dev.sh
EOT
"preview_port" = "4200"
"container_image" = "codercom/example-universal:ubuntu"
}
# Pre-builds is a Coder Premium
# feature to speed up workspace creation
#
# see https://coder.com/docs/admin/templates/extending-templates/prebuilt-workspaces
# prebuilds {
# instances = 1
# expiration_policy {
# ttl = 86400 # Time (in seconds) after which unclaimed prebuilds are expired (1 day)
# }
# }
}
# Advanced parameters (these are all set via preset)
data "coder_parameter" "system_prompt" {
name = "system_prompt"
display_name = "System Prompt"
type = "string"
form_type = "textarea"
description = "System prompt for the agent with generalized instructions"
mutable = false
}
data "coder_parameter" "setup_script" {
name = "setup_script"
display_name = "Setup Script"
type = "string"
form_type = "textarea"
description = "Script to run before running the agent"
mutable = false
}
data "coder_parameter" "container_image" {
name = "container_image"
display_name = "Container Image"
type = "string"
default = "codercom/example-universal:ubuntu"
mutable = false
}
data "coder_parameter" "preview_port" {
name = "preview_port"
display_name = "Preview Port"
description = "The port the web app is running to preview in Tasks"
type = "number"
default = "3000"
mutable = false
}
data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
resource "coder_agent" "main" {
arch = data.coder_provisioner.me.arch
os = "linux"
startup_script = <<-EOT
set -e
# Prepare user home with default files on first start.
if [ ! -f ~/.init_done ]; then
cp -rT /etc/skel ~
touch ~/.init_done
fi
EOT
# These environment variables allow you to make Git commits right away after creating a
# workspace. Note that they take precedence over configuration defined in ~/.gitconfig!
# You can remove this block if you'd prefer to configure Git manually or using
# dotfiles. (see docs/dotfiles.md)
env = {
GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}"
GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
}
# The following metadata blocks are optional. They are used to display
# information about your workspace in the dashboard. You can remove them
# if you don't want to display any information.
# For basic resources, you can use the `coder stat` command.
# If you need more control, you can write your own script.
metadata {
display_name = "CPU Usage"
key = "0_cpu_usage"
script = "coder stat cpu"
interval = 10
timeout = 1
}
metadata {
display_name = "RAM Usage"
key = "1_ram_usage"
script = "coder stat mem"
interval = 10
timeout = 1
}
metadata {
display_name = "Home Disk"
key = "3_home_disk"
script = "coder stat disk --path $${HOME}"
interval = 60
timeout = 1
}
metadata {
display_name = "CPU Usage (Host)"
key = "4_cpu_usage_host"
script = "coder stat cpu --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Memory Usage (Host)"
key = "5_mem_usage_host"
script = "coder stat mem --host"
interval = 10
timeout = 1
}
metadata {
display_name = "Load Average (Host)"
key = "6_load_host"
# get load avg scaled by number of cores
script = <<EOT
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
EOT
interval = 60
timeout = 1
}
metadata {
display_name = "Swap Usage (Host)"
key = "7_swap_host"
script = <<EOT
free -b | awk '/^Swap/ { printf("%.1f/%.1f", $3/1024.0/1024.0/1024.0, $2/1024.0/1024.0/1024.0) }'
EOT
interval = 10
timeout = 1
}
}
# See https://registry.coder.com/modules/coder/code-server
module "code-server" {
count = data.coder_workspace.me.start_count
folder = "/home/coder/projects"
source = "registry.coder.com/coder/code-server/coder"
settings = {
"workbench.colorTheme" : "Default Dark Modern"
}
# This ensures that the latest non-breaking version of the module gets downloaded, you can also pin the module version to prevent breaking changes in production.
version = "~> 1.0"
agent_id = coder_agent.main.id
order = 1
}
module "windsurf" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/windsurf/coder"
version = "1.3.1"
agent_id = coder_agent.main.id
}
module "cursor" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/cursor/coder"
version = "1.4.1"
agent_id = coder_agent.main.id
}
module "jetbrains" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/jetbrains/coder"
version = "~> 1.0"
agent_id = coder_agent.main.id
agent_name = "main"
folder = "/home/coder/projects"
}
resource "docker_volume" "home_volume" {
name = "coder-${data.coder_workspace.me.id}-home"
# Protect the volume from being deleted due to changes in attributes.
lifecycle {
ignore_changes = all
}
# Add labels in Docker to keep track of orphan resources.
labels {
label = "coder.owner"
value = data.coder_workspace_owner.me.name
}
labels {
label = "coder.owner_id"
value = data.coder_workspace_owner.me.id
}
labels {
label = "coder.workspace_id"
value = data.coder_workspace.me.id
}
# This field becomes outdated if the workspace is renamed but can
# be useful for debugging or cleaning out dangling volumes.
labels {
label = "coder.workspace_name_at_creation"
value = data.coder_workspace.me.name
}
}
resource "coder_app" "preview" {
agent_id = coder_agent.main.id
slug = "preview"
display_name = "Preview your app"
icon = "${data.coder_workspace.me.access_url}/emojis/1f50e.png"
url = "http://localhost:${data.coder_parameter.preview_port.value}"
share = "authenticated"
subdomain = true
open_in = "tab"
order = 0
healthcheck {
url = "http://localhost:${data.coder_parameter.preview_port.value}/"
interval = 5
threshold = 15
}
}
resource "docker_container" "workspace" {
count = data.coder_workspace.me.start_count
image = data.coder_parameter.container_image.value
# Uses lower() to avoid Docker restriction on container names.
name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
# Hostname makes the shell more user friendly: coder@my-workspace:~$
hostname = data.coder_workspace.me.name
user = "coder"
# Use the docker gateway if the access URL is 127.0.0.1
entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
host {
host = "host.docker.internal"
ip = "host-gateway"
}
volumes {
container_path = "/home/coder"
volume_name = docker_volume.home_volume.name
read_only = false
}
# Add labels in Docker to keep track of orphan resources.
labels {
label = "coder.owner"
value = data.coder_workspace_owner.me.name
}
labels {
label = "coder.owner_id"
value = data.coder_workspace_owner.me.id
}
labels {
label = "coder.workspace_id"
value = data.coder_workspace.me.id
}
labels {
label = "coder.workspace_name"
value = data.coder_workspace.me.name
}
}
+1 -1
View File
@@ -28,7 +28,7 @@
<meta property="regions" content="{{ .Regions }}" />
<meta property="docs-url" content="{{ .DocsURL }}" />
<meta property="logo-url" content="{{ .LogoURL }}" />
<meta property="tasks-tab-visible" content="{{ .TasksTabVisible }}" />
<meta property="ai-tasks-enabled" content="{{ .AITasksEnabled }}" />
<meta property="ai-gateway-enabled" content="{{ .AIGatewayEnabled }}" />
<meta property="permissions" content="{{ .Permissions }}" />
<meta property="organizations" content="{{ .Organizations }}" />
+4 -4
View File
@@ -82,7 +82,7 @@ type Options struct {
Entitlements *entitlements.Set
Telemetry telemetry.Reporter
Logger slog.Logger
HideAITasks bool
AITasksEnabled bool
AIGatewayEnabled bool
}
@@ -267,7 +267,7 @@ type htmlState struct {
Regions string
DocsURL string
TasksTabVisible string
AITasksEnabled string
AIGatewayEnabled string
Permissions string
Organizations string
@@ -517,9 +517,9 @@ func (h *Handler) populateHTMLState(
})
}
wg.Go(func() {
data, err := json.Marshal(!h.opts.HideAITasks)
data, err := json.Marshal(h.opts.AITasksEnabled)
if err == nil {
state.TasksTabVisible = html.EscapeString(string(data))
state.AITasksEnabled = html.EscapeString(string(data))
}
})
wg.Go(func() {
+1 -1
View File
@@ -4789,7 +4789,7 @@ export interface DeploymentValues {
readonly additional_csp_policy?: string;
readonly workspace_hostname_suffix?: string;
readonly workspace_prebuilds?: PrebuildsConfig;
readonly hide_ai_tasks?: boolean;
readonly enable_ai_tasks?: boolean;
readonly ai?: AIConfig;
readonly stats_collection?: StatsCollectionConfig;
readonly template_builder?: TemplateBuilderConfig;
+5 -5
View File
@@ -2,13 +2,13 @@ import { act, renderHook } from "@testing-library/react";
import type { Region, User } from "#/api/typesGenerated";
import {
MockAIGatewayEnabled,
MockAITasksEnabled,
MockAppearanceConfig,
MockBuildInfo,
MockEntitlements,
MockExperiments,
MockOrganization,
MockPermissions,
MockTasksTabVisible,
MockUserAppearanceSettings,
MockUserOwner,
} from "#/testHelpers/entities";
@@ -45,7 +45,7 @@ const mockDataForTags = {
user: MockUserOwner,
userAppearance: MockUserAppearanceSettings,
regions: MockRegions,
"tasks-tab-visible": MockTasksTabVisible,
"ai-tasks-enabled": MockAITasksEnabled,
"ai-gateway-enabled": MockAIGatewayEnabled,
permissions: MockPermissions,
organizations: [MockOrganization],
@@ -80,7 +80,7 @@ const emptyMetadata: RuntimeHtmlMetadata = {
available: false,
value: undefined,
},
"tasks-tab-visible": {
"ai-tasks-enabled": {
available: false,
value: undefined,
},
@@ -127,9 +127,9 @@ const populatedMetadata: RuntimeHtmlMetadata = {
available: true,
value: MockUserAppearanceSettings,
},
"tasks-tab-visible": {
"ai-tasks-enabled": {
available: true,
value: MockTasksTabVisible,
value: MockAITasksEnabled,
},
"ai-gateway-enabled": {
available: true,
+2 -2
View File
@@ -31,7 +31,7 @@ type AvailableMetadata = Readonly<{
entitlements: Entitlements;
regions: readonly Region[];
"build-info": BuildInfoResponse;
"tasks-tab-visible": boolean;
"ai-tasks-enabled": boolean;
"ai-gateway-enabled": boolean;
permissions: Permissions;
organizations: Organization[];
@@ -96,7 +96,7 @@ export class MetadataManager implements MetadataManagerApi {
experiments: this.registerValue<Experiment[]>("experiments"),
"build-info": this.registerValue<BuildInfoResponse>("build-info"),
regions: this.registerRegionValue(),
"tasks-tab-visible": this.registerValue<boolean>("tasks-tab-visible"),
"ai-tasks-enabled": this.registerValue<boolean>("ai-tasks-enabled"),
"ai-gateway-enabled": this.registerValue<boolean>("ai-gateway-enabled"),
permissions: this.registerValue<Permissions>("permissions"),
organizations: this.registerValue<Organization[]>("organizations"),
@@ -12,8 +12,8 @@ import {
TooltipTrigger,
} from "#/components/Tooltip/Tooltip";
import type { ProxyContextValue } from "#/contexts/ProxyContext";
import { useEmbeddedMetadata } from "#/hooks/useEmbeddedMetadata";
import { NotificationsInbox } from "#/modules/notifications/NotificationsInbox/NotificationsInbox";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { getPrereleaseFlag } from "#/utils/buildInfo";
import { cn } from "#/utils/cn";
import {
@@ -206,12 +206,7 @@ type TasksNavItemProps = {
};
const TasksNavItem: FC<TasksNavItemProps> = ({ user }) => {
const { metadata } = useEmbeddedMetadata();
const canSeeTasks = Boolean(
metadata["tasks-tab-visible"].value ||
process.env.NODE_ENV === "development" ||
process.env.STORYBOOK,
);
const canSeeTasks = useAITasksEnabled();
const filter: TypesGen.TasksFilter = {
owner: user.username,
};
+3 -1
View File
@@ -62,6 +62,7 @@ import {
import { useProxy } from "#/contexts/ProxyContext";
import { useClipboard } from "#/hooks/useClipboard";
import { useFeatureVisibility } from "#/modules/dashboard/useFeatureVisibility";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import {
getAgentConnectivityIssues,
getAgentScriptIssues,
@@ -155,6 +156,7 @@ export const AgentRow: FC<AgentRowProps> = ({
initialMetadata,
}) => {
const { browser_only, workspace_external_agent } = useFeatureVisibility();
const aiTasksEnabled = useAITasksEnabled();
const appSections = organizeAgentApps(agent.apps);
const hasAppsToDisplay =
!browser_only || appSections.some((it) => it.apps.length > 0);
@@ -475,7 +477,7 @@ export const AgentRow: FC<AgentRowProps> = ({
</section>
)}
{workspace.task_id && (
{aiTasksEnabled && workspace.task_id && (
<Button asChild size="sm" variant="outline" className="w-fit">
<RouterLink
to={`/tasks/${workspace.owner_name}/${workspace.task_id}`}
@@ -20,7 +20,6 @@ import { Badge } from "#/components/Badge/Badge";
import { Button } from "#/components/Button/Button";
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
import { Kbd, KbdGroup } from "#/components/Kbd/Kbd";
import { Link } from "#/components/Link/Link";
import {
Select,
SelectContent,
@@ -36,7 +35,6 @@ import {
} from "#/components/Tooltip/Tooltip";
import { useAuthenticated } from "#/hooks/useAuthenticated";
import { useExternalAuth } from "#/hooks/useExternalAuth";
import { docs } from "#/utils/docs";
import { getOSKey } from "#/utils/platform";
import { PromptSelectTrigger } from "./PromptSelectTrigger";
import { TemplateVersionSelect } from "./TemplateVersionSelect";
@@ -124,10 +122,7 @@ const TaskPromptEmpty: FC = () => {
No Task templates found
</h3>
<span className="text-content-secondary text-sm">
<Link href={docs("/ai-coder/tasks")} target="_blank" rel="noreferrer">
Learn about Tasks
</Link>{" "}
to get started.
Ask a template administrator to add a Task template to get started.
</span>
</div>
</div>
@@ -40,10 +40,12 @@ import { cn } from "#/utils/cn";
import { TaskDeleteDialog } from "../TaskDeleteDialog/TaskDeleteDialog";
import { taskStatusToStatusIndicatorVariant } from "../TaskStatus/TaskStatus";
import { canPauseTask, canResumeTask, isPauseDisabled } from "../taskActions";
import { useAITasksEnabled } from "../useAITasksEnabled";
import { UserCombobox } from "./UserCombobox";
export const TasksSidebar: FC = () => {
const { user, permissions } = useAuthenticated();
const aiTasksEnabled = useAITasksEnabled();
const ownerParam = useSearchParamsKey({
key: "owner",
defaultValue: user.username,
@@ -51,6 +53,10 @@ export const TasksSidebar: FC = () => {
const [isCollapsed, setIsCollapsed] = useState(false);
if (!aiTasksEnabled) {
return null;
}
return (
<div
className={cn(
@@ -0,0 +1,26 @@
import {
defaultMetadataManager,
useEmbeddedMetadata,
} from "#/hooks/useEmbeddedMetadata";
// The `ai-tasks-enabled` metadata mirrors the CODER_ENABLE_AI_TASKS deployment
// value and is the master switch for every Coder Tasks surface. The Go server
// always embeds it, so a missing value means the frontend is being served by
// Vite, Storybook, or a test runner. Those environments fall back to enabled so
// local development and stories keep rendering Tasks.
function isEnabled(value: boolean | undefined): boolean {
return value ?? true;
}
export function useAITasksEnabled(): boolean {
const { metadata } = useEmbeddedMetadata();
return isEnabled(metadata["ai-tasks-enabled"].value);
}
// Module-scope equivalent of `useAITasksEnabled` for code that runs outside of
// React, such as route registration in `router.tsx`.
export function aiTasksEnabled(): boolean {
return isEnabled(
defaultMetadataManager.getMetadata()["ai-tasks-enabled"].value,
);
}
@@ -9,6 +9,7 @@ import { ConfirmDialog } from "#/components/Dialog/ConfirmDialog/ConfirmDialog";
import { Input } from "#/components/Input/Input";
import { Label } from "#/components/Label/Label";
import { Link } from "#/components/Link/Link";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { docs } from "#/utils/docs";
const warnBoxClassName =
@@ -32,6 +33,7 @@ export const WorkspaceDeleteDialog: FC<WorkspaceDeleteDialogProps> = ({
const confirmId = useId();
const errorId = `${confirmId}-error`;
const orphanId = `${confirmId}-orphan`;
const aiTasksEnabled = useAITasksEnabled();
const [userConfirmationText, setUserConfirmationText] = useState("");
const [orphanWorkspace, setOrphanWorkspace] =
@@ -62,7 +64,7 @@ export const WorkspaceDeleteDialog: FC<WorkspaceDeleteDialogProps> = ({
(workspace.latest_build.status === "failed" ||
workspace.latest_build.status === "canceled");
const hasTask = Boolean(workspace.task_id);
const hasTask = aiTasksEnabled && Boolean(workspace.task_id);
return (
<ConfirmDialog
@@ -10,6 +10,7 @@ import {
CollapsibleTrigger,
} from "#/components/Collapsible/Collapsible";
import { Link } from "#/components/Link/Link";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { cn } from "#/utils/cn";
import { docs } from "#/utils/docs";
@@ -20,6 +21,8 @@ interface ManagedAgentsConsumptionProps {
export const ManagedAgentsConsumption: FC<ManagedAgentsConsumptionProps> = ({
managedAgentFeature,
}) => {
const aiTasksEnabled = useAITasksEnabled();
// If no feature is provided or it's disabled, show disabled state
if (!managedAgentFeature?.enabled) {
return (
@@ -100,15 +103,17 @@ export const ManagedAgentsConsumption: FC<ManagedAgentsConsumptionProps> = ({
<p>
Today,{" "}
<Link
href={docs("/ai-coder/tasks")}
href={docs("/ai-coder/agents")}
target="_blank"
rel="noreferrer"
>
Coder Tasks (via UI, CLI, or API)
Coder Agents (via UI or API)
</Link>{" "}
is the only way to create agentic workspaces, but additional
protocols and APIs may be supported as standards emerge. Learn
more in{" "}
{aiTasksEnabled
? "and Coder Tasks (via UI, CLI, or API) are the only ways"
: "is the only way"}{" "}
to create agentic workspaces, but additional protocols and APIs
may be supported as standards emerge. Learn more in{" "}
<Link
href={docs("/ai-coder/ai-governance")}
target="_blank"
@@ -33,6 +33,7 @@ import {
TableHeader,
TableRow,
} from "#/components/Table/Table";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { getFormHelpers, nameValidator } from "#/utils/formUtils";
const validationSchema = Yup.object({
@@ -197,10 +198,19 @@ const ActionCheckboxes: FC<ActionCheckboxesProps> = ({
}) => {
const [checkedActions, setCheckActions] = useState(permissions);
const [showAllResources, setShowAllResources] = useState(allResources);
const aiTasksEnabled = useAITasksEnabled();
const resourceActions = showAllResources
// `RBACResourceActions` is generated at module scope, so the `task` resource
// is removed here rather than at the constant to keep Tasks roles unsettable
// while Tasks is disabled.
const allActions = showAllResources
? RBACResourceActions
: filteredRBACResourceActions;
const resourceActions = aiTasksEnabled
? allActions
: Object.fromEntries(
Object.entries(allActions).filter(([resource]) => resource !== "task"),
);
const handleActionCheckChange = async (name: string, checked: boolean) => {
const [resource_type, action] = name.split(":");
+1 -10
View File
@@ -11,7 +11,6 @@ import {
} from "#/components/DropdownMenu/DropdownMenu";
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
import { InfoTooltip } from "#/components/InfoTooltip/InfoTooltip";
import { Link } from "#/components/Link/Link";
import { ScrollArea, ScrollBar } from "#/components/ScrollArea/ScrollArea";
import { getTerminalHref } from "#/modules/apps/apps";
import { useAppLink } from "#/modules/apps/useAppLink";
@@ -24,7 +23,6 @@ import {
type WorkspaceAppWithAgent,
} from "#/modules/apps/workspaceApps";
import { cn } from "#/utils/cn";
import { docs } from "#/utils/docs";
type TaskAppsProps = {
task: Task;
@@ -120,14 +118,7 @@ export const TaskApps: FC<TaskAppsProps> = ({ task, workspace }) => {
</h3>
<span className="text-content-secondary text-sm">
<Link
href={docs("/ai-coder/tasks")}
target="_blank"
rel="noreferrer"
>
Learn how to configure apps
</Link>{" "}
for your tasks.
Configure apps on your task template to see them here.
</span>
</div>
)}
@@ -39,10 +39,12 @@ import {
selectDisabledPreferences,
} from "#/modules/notifications/utils";
import type { Permissions } from "#/modules/permissions";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { pageTitle } from "#/utils/page";
const NotificationsPage: FC = () => {
const { user, permissions } = useAuthenticated();
const aiTasksEnabled = useAITasksEnabled();
const [
disabledPreferences,
systemTemplatesByGroup,
@@ -125,7 +127,7 @@ const NotificationsPage: FC = () => {
{ready ? (
<div className="flex flex-col gap-8">
{Object.entries(allTemplatesByGroup).map(([group, templates]) => {
if (!canSeeNotificationGroup(group, permissions)) {
if (!canSeeNotificationGroup(group, permissions, aiTasksEnabled)) {
return null;
}
@@ -275,14 +277,16 @@ export default NotificationsPage;
function canSeeNotificationGroup(
group: string,
permissions: Permissions,
aiTasksEnabled: boolean,
): boolean {
switch (group) {
case "Template Events":
return permissions.createTemplates;
case "User Events":
return permissions.createUser;
case "Workspace Events":
case "Task Events":
return aiTasksEnabled;
case "Workspace Events":
case "Chat Events":
case "Custom Events":
case "AI Cost Control Events":
@@ -8,6 +8,7 @@ import {
PopoverTrigger,
} from "#/components/Popover/Popover";
import { isGroup } from "#/modules/groups";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { AddWorkspaceUserOrGroup } from "#/modules/workspaces/WorkspaceSharingForm/AddWorkspaceUserOrGroup";
import { useWorkspaceSharing } from "#/modules/workspaces/WorkspaceSharingForm/useWorkspaceSharing";
import { WorkspaceSharingForm } from "#/modules/workspaces/WorkspaceSharingForm/WorkspaceSharingForm";
@@ -22,6 +23,7 @@ export const ShareButton: FC<ShareButtonProps> = ({
canUpdatePermissions,
}) => {
const sharing = useWorkspaceSharing(workspace);
const aiTasksEnabled = useAITasksEnabled();
return (
<Popover>
@@ -34,7 +36,7 @@ export const ShareButton: FC<ShareButtonProps> = ({
<PopoverContent align="end" className="w-[580px] p-4">
<div className="flex items-center gap-2 mb-4">
<h3 className="text-lg font-semibold m-0">
{workspace.task_id ? "Task" : "Workspace"} Sharing
{aiTasksEnabled && workspace.task_id ? "Task" : "Workspace"} Sharing
</h3>
</div>
<WorkspaceSharingForm
@@ -74,6 +74,7 @@ import {
import { useAppLink } from "#/modules/apps/useAppLink";
import { findWorkspaceAppWithAgent } from "#/modules/apps/workspaceApps";
import { useDashboard } from "#/modules/dashboard/useDashboard";
import { useAITasksEnabled } from "#/modules/tasks/useAITasksEnabled";
import { abilitiesByWorkspaceStatus } from "#/modules/workspaces/actions";
import { WorkspaceBuildCancelDialog } from "#/modules/workspaces/WorkspaceBuildCancelDialog/WorkspaceBuildCancelDialog";
import { WorkspaceMoreActions } from "#/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions";
@@ -115,6 +116,7 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
chatsByWorkspace,
}) => {
const dashboard = useDashboard();
const aiTasksEnabled = useAITasksEnabled();
const isLoading = !workspaces;
const isEmpty = workspaces && workspaces.length === 0;
const hideHeaders = isLoading || isEmpty;
@@ -223,7 +225,7 @@ export const WorkspacesTable: FC<WorkspacesTableProps> = ({
{workspace.outdated && (
<WorkspaceOutdatedTooltip workspace={workspace} />
)}
{workspace.task_id && (
{aiTasksEnabled && workspace.task_id && (
<Badge size="xs" variant="default">
Task
</Badge>
+5 -2
View File
@@ -13,6 +13,7 @@ import { Loader } from "./components/Loader/Loader";
import { RequireAuth } from "./contexts/auth/RequireAuth";
import { useAuthenticated } from "./hooks/useAuthenticated";
import { DashboardLayout } from "./modules/dashboard/DashboardLayout";
import { aiTasksEnabled } from "./modules/tasks/useAITasksEnabled";
import AuditPage from "./pages/AuditPage/AuditPage";
import ConnectionLogPage from "./pages/ConnectionLogPage/ConnectionLogPage";
import { HealthLayout } from "./pages/HealthPage/HealthLayout";
@@ -599,7 +600,7 @@ export const router = createBrowserRouter(
<Route path="/connectionlog" element={<ConnectionLogPage />} />
<Route path="/tasks" element={<TasksPage />} />
{aiTasksEnabled() && <Route path="/tasks" element={<TasksPage />} />}
<Route path="/organizations" element={<OrganizationSettingsLayout />}>
<Route path="new" element={<CreateOrganizationPage />} />
@@ -828,7 +829,9 @@ export const router = createBrowserRouter(
<Route path="/cli-auth" element={<CliAuthPage />} />
<Route path="/coder-cup" element={<CoderCupPage />} />
<Route path="/icons" element={<IconsPage />} />
<Route path="/tasks/:username/:taskId" element={<TaskPage />} />
{aiTasksEnabled() && (
<Route path="/tasks/:username/:taskId" element={<TaskPage />} />
)}
<Route
path="/agents"
element={
+1 -1
View File
@@ -648,7 +648,7 @@ export const MockImportedUserSecrets: TypesGen.UserSecret[] = [
},
];
export const MockTasksTabVisible: boolean = false;
export const MockAITasksEnabled: boolean = false;
export const MockAIGatewayEnabled: boolean = true;
export const MockOrganizationMember: TypesGen.OrganizationMemberWithUserData = {