Skip to main content

Workspace builders

Workspace mode (DuctapeModule.forWorkspace) enables declarative builder decorators that map HTTP handler bodies to Ductape admin APIs. DuctapeBuilderInterceptor inspects handler metadata and calls the SDK on your behalf.

Metadata decorators

DecoratorPurpose
@AppTag('my-app')App tag for webhook/model/agent builder operations
@WebhookBuilder.Define({ operation, … })Webhook and event CRUD
@ModelBuilder.Define({ operation, product?, tag? })Model CRUD
@AgentBuilder.Define({ operation, product?, tag? })Agent definition CRUD

Apply @AppTag on the controller class (or method) so builder interceptors know which app context to use.

@WebhookBuilder.Define

Maps to ductape.webhooks.* and ductape.webhooks.events.*.

operationSDK area
create, list, fetch, update, deleteWebhook definitions
Event operations (as supported)Webhook events
import { Controller, Post, Body } from '@nestjs/common';
import { AppTag, WebhookBuilder } from '@ductape/nestjs';
import type { IAppWebhook } from '@ductape/sdk';

@AppTag('stripe')
@Controller('admin/webhooks')
export class WebhookAdminController {
@Post()
@WebhookBuilder.Define({ operation: 'create' })
create(body: Partial<IAppWebhook>) {
return body;
}

@Post('list')
@WebhookBuilder.Define({ operation: 'list' })
list(body: Record<string, unknown>) {
return body;
}
}

The method return value (request body) is passed to the SDK; the interceptor replaces it with the API response.

See App webhooks setup.

@ModelBuilder.Define

Maps to models.getService().*.

operationTypical use
createDefine a new model
list, fetch, update, deleteManage models
@Controller('admin/models')
export class ModelAdminController {
@Post()
@ModelBuilder.Define({ operation: 'create', product: 'my-product' })
createModel(body: Record<string, unknown>) {
return body;
}
}

@AgentBuilder.Define

Maps to agents.getService().*.

operationTypical use
defineCreate or update agent definition
fetch, deleteRead or remove definitions
@Controller('admin/agents')
export class AgentAdminController {
@Post()
@AgentBuilder.Define({ operation: 'define', product: 'my-product', tag: 'support' })
defineAgent(body: Record<string, unknown>) {
return body;
}
}

Integration vs workspace

ConcernIntegration modeWorkspace mode
@Webhook.Register / @Webhook.ConsumerProduct integrator URLs
@WebhookBuilder.DefineApp builder webhook CRUD
@Api, @Database, runtime decoratorsYesYes (same accessKey)

Register DuctapeBuilderInterceptor globally in workspace mode (default when using forWorkspace), or apply it per controller: Interceptors.