MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / handleCreateAgent

Method handleCreateAgent

internal/httpapi/agents_write.go:183–253  ·  view source on GitHub ↗
(ctx context.Context, in *createAgentInput)

Source from the content-addressed store, hash-verified

181}
182
183func (s *Server) handleCreateAgent(ctx context.Context, in *createAgentInput) (*createAgentOutput, error) {
184 user, err := s.requireAccountUser(ctx)
185 if err != nil {
186 return nil, err
187 }
188 req := in.Body
189 email := identity.NormalizeEmail(req.Email)
190
191 if email == "" {
192 return nil, NewError(http.StatusBadRequest, "invalid_request", "email is required")
193 }
194
195 // Resolve the DNS domain from the email itself (AG-1/AG-2): there is one
196 // create path. An email on the deployment's shared domain is a shared-domain
197 // registration (its local-part is validated as a slug, no ownership check);
198 // any other domain is a custom-domain agent gated by ownership below.
199 parts := strings.SplitN(email, "@", 2)
200 if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
201 return nil, NewError(http.StatusBadRequest, "invalid_request", "invalid email address")
202 }
203 domain := parts[1]
204 isShared := s.deps.SharedDomain != "" && strings.EqualFold(domain, s.deps.SharedDomain)
205 if isShared {
206 domain = s.deps.SharedDomain // normalize to the configured casing
207 if err := validateSlug(parts[0]); err != nil {
208 return nil, NewError(http.StatusBadRequest, "invalid_slug", err.Error())
209 }
210 }
211
212 // Custom-domain ownership guard (decision 1): the domain must be
213 // registered to this user AND verified. This is the load-bearing
214 // authorization that an agent can only be created on a domain the
215 // caller controls.
216 if !isShared {
217 if s.deps.LookupDomain == nil {
218 return nil, NewError(http.StatusInternalServerError, "internal_error", "domain lookup unavailable")
219 }
220 dom, err := s.deps.LookupDomain(ctx, domain, user.ID)
221 if err != nil {
222 return nil, NewError(http.StatusBadRequest, "domain_not_registered", "register and verify your domain first")
223 }
224 if !dom.Verified {
225 return nil, NewError(http.StatusBadRequest, "domain_not_verified", "verify your domain first")
226 }
227 }
228
229 // Per-user agent cap (after auth + domain checks, so a 402 means
230 // "valid request, out of capacity" — never masks a 400/401).
231 if s.deps.EnforceAgentCreate != nil {
232 if err := s.deps.EnforceAgentCreate(ctx, user.ID); err != nil {
233 if env, ok := limitEnvelope(err); ok {
234 return nil, env
235 }
236 return nil, NewError(http.StatusInternalServerError, "internal_error", "limits check failed")
237 }
238 }
239
240 if s.deps.CreateAgent == nil {

Callers

nothing calls this directly

Calls 9

requireAccountUserMethod · 0.95
NormalizeEmailFunction · 0.92
NewErrorFunction · 0.85
limitEnvelopeFunction · 0.85
agentViewFromIdentityFunction · 0.85
LookupDomainMethod · 0.80
CreateAgentMethod · 0.80
validateSlugFunction · 0.70
ErrorMethod · 0.45

Tested by

no test coverage detected