api-thin-controllers
**Impact: HIGH**
$ npx -y skills add calcom/cal.com --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
**Impact: HIGH**
Agent definition
api-thin-controllers.mdpaths:
- "apps/api/**/*.controller.ts"
title: Keep Controllers Thin - HTTP Concerns Only
impact: HIGH
impactDescription: Enables technology-agnostic business logic
tags: api, controllers, http, separation-of-concerns
Keep Controllers Thin - HTTP Concerns Only
**Impact: HIGH**
Controllers are thin layers that handle only HTTP concerns. They take requests, process them, and map data to DTOs that are passed to core application logic. No application or core logic should be seen in API routes or tRPC handlers.
**Controller responsibilities (and ONLY these):**
- Receive and validate incoming requests
- Extract data from request parameters, body, headers
- Transform request data into DTOs
- Call appropriate application services with those DTOs
- Transform application service responses into response DTOs
- Return HTTP responses with proper status codes
**Controllers should NOT:**
- Contain business logic or domain rules
- Directly access databases or external services
- Perform complex data transformations or calculations
- Make decisions about what the application should do
- Know about implementation details of the domain
**Incorrect (business logic in controller):**
export async function POST(request: Request) {
const body = await request.json();
// Business logic in controller - BAD
const user = await prisma.user.findFirst({ where: { id: body.userId } });
if (!user.canBook) {
return Response.json({ error: "Cannot book" }, { status: 403 });
}
const booking = await prisma.booking.create({
data: {
title: body.title,
startTime: new Date(body.startTime),
// Complex logic here...
}
});
return Response.json(booking);
}**Correct (thin controller):**
export async function POST(request: Request) {
const body = await request.json();
// Validate input
const input = CreateBookingSchema.parse(body);
// Delegate to service
const result = await bookingService.createBooking(input);
// Transform and return
return Response.json(BookingResponseSchema.parse(result));
}**The principle:** We must detach HTTP technology from our application. The way we transfer data between client and server (whether REST, tRPC, etc.) should not influence how our core application works. HTTP is a delivery mechanism, not an architectural driver.
Reference: [Cal.diy Engineering Blog](https://cal.com/blog/engineering-in-2026-and-beyond)
Read more
paths: - "apps/api/**/*.controller.ts" title: Keep Controllers Thin - HTTP Concerns Only impact: HIGH impactDescription: Enables technology-agnostic business logic tags: api, controllers, http, separation-of-concerns
Keep Controllers Thin - HTTP Concerns Only
**Impact: HIGH**
Controllers are thin layers that handle only HTTP concerns. They take requests, process them, and map data to DTOs that are passed to core application logic. No application or core logic should be seen in API routes or tRPC handlers.
**Controller responsibilities (and ONLY these):**
- Receive and validate incoming requests
- Extract data from request parameters, body, headers
- Transform request data into DTOs
- Call appropriate application services with those DTOs
- Transform application service responses into response DTOs
- Return HTTP responses with proper status codes
**Controllers should NOT:**
- Contain business logic or domain rules
- Directly access databases or external services
- Perform complex data transformations or calculations
- Make decisions about what the application should do
- Know about implementation details of the domain
**Incorrect (business logic in controller):**
export async function POST(request: Request) {
const body = await request.json();
// Business logic in controller - BAD
const user = await prisma.user.findFirst({ where: { id: body.userId } });
if (!user.canBook) {
return Response.json({ error: "Cannot book" }, { status: 403 });
}
const booking = await prisma.booking.create({
data: {
title: body.title,
startTime: new Date(body.startTime),
// Complex logic here...
}
});
return Response.json(booking);
}**Correct (thin controller):**
export async function POST(request: Request) {
const body = await request.json();
// Validate input
const input = CreateBookingSchema.parse(body);
// Delegate to service
const result = await bookingService.createBooking(input);
// Transform and return
return Response.json(BookingResponseSchema.parse(result));
}**The principle:** We must detach HTTP technology from our application. The way we transfer data between client and server (whether REST, tRPC, etc.) should not influence how our core application works. HTTP is a delivery mechanism, not an architectural driver.
Reference: [Cal.diy Engineering Blog](https://cal.com/blog/engineering-in-2026-and-beyond)
Repo: calcom/cal.com
Other agents on caldiy.
- knowledge-base
This file contains domain knowledge about the Cal.diy product and codebase. For coding guidelines and rules, see [`rules/`](rules/).
Open agent - api-no-breaking-changes
**Impact: CRITICAL**
Open agent - architecture-circular-dependencies
**Impact: CRITICAL**
Open agent - architecture-feature-boundaries
**Impact: CRITICAL**
Open agent - architecture-features-modules
The `packages/features` package should contain only framework-agnostic code: - Repositories (data access layer) - Services (business logic) - Core utilities and helpers - Types and interfaces
Open agent - architecture-page-level-auth
**Impact: CRITICAL (Prevents unauthorized access to sensitive data)**
Open agent

