MCPcopy Index your code
hub / github.com/coder/coder / CreateWorkspace

Function CreateWorkspace

coderd/x/chatd/chattool/createworkspace.go:89–348  ·  view source on GitHub ↗

CreateWorkspace returns a tool that creates a new workspace from a template. The tool is idempotent: if the chat already has a workspace that is building or running, it returns the existing workspace instead of creating a new one. A mutex prevents parallel calls from creating duplicate workspaces. d

(db database.Store, organizationID, chatID uuid.UUID, options CreateWorkspaceOptions)

Source from the content-addressed store, hash-verified

87// calls from creating duplicate workspaces.
88// db must not be nil and chatID must not be uuid.Nil.
89func CreateWorkspace(db database.Store, organizationID, chatID uuid.UUID, options CreateWorkspaceOptions) fantasy.AgentTool {
90 return fantasy.NewAgentTool(
91 "create_workspace",
92 "Create a new workspace from a template only when workspace-backed "+
93 "file inspection, command execution, or file editing is required, "+
94 "or when the user explicitly asks for one. Do not use this as a "+
95 "default first step for requests answerable from conversation "+
96 "context, provider tools, or external MCP tools. Requires a "+
97 "template_id (from list_templates). Optionally provide "+
98 "a name and parameter values (from read_template). "+
99 "If no name is given, one will be generated. "+
100 "Provide a preset_id (from read_template) to apply "+
101 "preset parameters and potentially claim a prebuilt "+
102 "workspace for faster startup. "+
103 "This tool is idempotent. If the chat already has a "+
104 "workspace that is building or running, the existing "+
105 "workspace is returned.",
106 func(ctx context.Context, args createWorkspaceArgs, _ fantasy.ToolCall) (fantasy.ToolResponse, error) {
107 if options.CreateFn == nil {
108 return fantasy.NewTextErrorResponse("workspace creator is not configured"), nil
109 }
110
111 templateIDStr := strings.TrimSpace(args.TemplateID)
112 if templateIDStr == "" {
113 return fantasy.NewTextErrorResponse("template_id is required; use list_templates to find one"), nil
114 }
115 templateID, err := uuid.Parse(templateIDStr)
116 if err != nil {
117 return fantasy.NewTextErrorResponse(
118 xerrors.Errorf("invalid template_id: %w", err).Error(),
119 ), nil
120 }
121
122 if !isTemplateAllowed(options.AllowedTemplateIDs, templateID) {
123 return fantasy.NewTextErrorResponse("template not available for chat workspaces; use list_templates to find allowed templates"), nil
124 }
125
126 // Serialize workspace creation to prevent parallel
127 // tool calls from creating duplicate workspaces.
128 if options.WorkspaceMu != nil {
129 options.WorkspaceMu.Lock()
130 defer options.WorkspaceMu.Unlock()
131 }
132
133 ownerID := options.OwnerID
134
135 // Check for an existing workspace on the chat.
136 check := options.checkExistingWorkspace(ctx, db, chatID)
137 if check.BuildErr != nil {
138 return buildFailureToolResponse(
139 ctx,
140 options.Logger,
141 db,
142 ownerID,
143 organizationID,
144 check.BuildAction,
145 check.BuildID,
146 check.BuildErr,

Calls 15

ParseChatWorkspaceTTLFunction · 0.92
NameValidFunction · 0.92
IsResponderFunction · 0.92
FindChatAgentFunction · 0.92
isTemplateAllowedFunction · 0.85
buildFailureToolResponseFunction · 0.85
toolResponseFunction · 0.85
asOwnerFunction · 0.85
templateHasExternalAgentFunction · 0.85
generatedWorkspaceNameFunction · 0.85
responseErrorResultFunction · 0.85
setBuildIDFunction · 0.85