21 de junio de 2026
Arquitectura vertical slice en .NET: la forma más compatible con agentes IA de estructurar una minimal API
Qué es la arquitectura vertical slice, por qué funciona mejor con agentes IA que Clean Architecture, y cómo estructurar una minimal API .NET 10 como vertical slices con tests de contrato.
La arquitectura vertical slice es la forma más compatible con agentes IA de organizar una minimal API de .NET. Ese es el caso no porque sea nueva o ingeniosa, sino por una propiedad mecánica simple: un cambio a una funcionalidad toca una carpeta. Un agente que no puede deambular es un agente que no rompe cosas que no le pediste que tocara.
¿Qué es la arquitectura vertical slice (VSA) vs Clean Architecture / N-tier?
La arquitectura vertical slice organiza el código alrededor de funcionalidades (slices) en lugar de capas técnicas. Cada archivo de una funcionalidad dada - el endpoint, el handler, los records de request/response, la validación y los tests - vive en una carpeta. Un cambio a la funcionalidad “Crear Nota” toca Features/Notes/, no la capa Domain, la capa Application, la capa Infrastructure y la capa Presentation simultáneamente.
Clean Architecture y N-tier organizan el código por preocupación técnica. La misma funcionalidad está dividida entre múltiples capas, cada una en su propio proyecto o carpeta. El código está muy organizado por tipo de código, pero muy disperso por funcionalidad. Añadir un nuevo campo a una funcionalidad requiere tocar archivos en cuatro o cinco lugares diferentes.
N-tier (Controladores, Servicios, Repositorios) es el stack de capas clásico. Clean Architecture es N-tier con una regla de dependencia más estricta: las capas internas no pueden depender de las externas, y el dominio es independiente del framework. Ambos son válidos. Ninguno es particularmente compatible con agentes.
| Propiedad | N-tier / Clean Architecture | Arquitectura Vertical Slice |
|---|---|---|
| Organización del código | Por capa técnica | Por funcionalidad |
| Cambio a una funcionalidad | Toca múltiples capas | Toca una carpeta |
| Acoplamiento entre funcionalidades | Bajo por diseño | Debe aplicarse explícitamente |
| Onboarding a una nueva funcionalidad | Leer cuatro capas | Leer una carpeta |
| Radio de impacto del agente IA | Amplio | Estrecho |
VSA no es una reacción contra Clean Architecture. Los dos enfoques resuelven problemas diferentes. La pregunta es cuál encaja con cómo trabajas realmente - y cómo trabaja tu agente.
¿Por qué VSA funciona mejor con agentes IA?
Con VSA, un cambio vive en una carpeta, por lo que un agente no deambula por Domain/Application/Infrastructure/Presentation al hacer un cambio en una sola funcionalidad.
Esto importa por cómo operan los agentes IA. Cuando le pides a un agente que “añada un campo de título al endpoint Crear Nota”, necesita leer los archivos relevantes, entender el patrón y aplicar el cambio. En una arquitectura por capas, ese cambio toca:
- La entidad
Noteen el proyecto Domain. - La interfaz
INoteRepositoryen el proyecto Application. - La implementación
NoteRepositoryen el proyecto Infrastructure. - El
CreateNoteCommanden el proyecto Application. - El endpoint en el proyecto Presentation/API.
- Posiblemente un DTO o archivo de mapeo.
Cada una de esas lecturas carga más archivos en el contexto del agente. Cada edición es una oportunidad para que el agente aplique un patrón inconsistente o rompa accidentalmente algo en una capa que no debía tocar. En Clean Architecture, las capas son el principio organizativo. Para un agente, son fricción.
En un vertical slice, ese mismo cambio toca Features/Notes/CreateNote.cs y posiblemente el test de contrato. Eso es todo. El agente lee un archivo, edita un archivo, y el test confirma el cambio. El principio aquí coincide con lo que los mejores arquitectos dicen sobre el acoplamiento: maximizar la cohesión dentro de un slice, minimizar el acoplamiento entre slices. Un agente que se mantiene dentro de un slice no puede romper accidentalmente otro slice.
Una segunda ventaja es que el agente puede usar los slices existentes como plantillas. Cuando le pides que añada un nuevo slice DeleteNote, lee CreateNote.cs, entiende el patrón y lo replica. El patrón es local y visible, no distribuido entre capas.
¿Cómo se estructura una minimal API de .NET 10 como vertical slices?
Crea una carpeta Features/ en tu proyecto API. Cada slice tiene su propia subcarpeta. Dentro de cada slice, mantén todo lo que pertenece a esa funcionalidad:
src/
Api/
Features/
Notes/
CreateNote.cs - endpoint + handler + tipos de request/response
GetNotes.cs - endpoint + handler + tipos de respuesta
DeleteNote.cs - endpoint + handler
Program.cs
tests/
Api.Tests/
Features/
Notes/
CreateNoteTests.cs
GetNotesTests.cs
Cada archivo *.cs en una carpeta de funcionalidad contiene el registro del endpoint y el handler de MediatR para esa operación. Mantenerlos juntos es lo que hace al slice “vertical” - ves el contrato HTTP completo y la lógica de implementación sin cambiar de archivo.
Un ejemplo concreto del repo starter github.com/Khavel/dotnet-claude-starter. La funcionalidad Notes es un slice:
// Features/Notes/CreateNote.cs
public record CreateNoteRequest(string Title, string Body);
public record CreateNoteResponse(Guid Id, string Title, string Body);
public class CreateNoteHandler : IRequestHandler<CreateNoteCommand, CreateNoteResponse>
{
// implementación del handler
}
// Registro del endpoint minimal API (llamado desde Program.cs)
public static class CreateNoteEndpoint
{
public static IEndpointRouteBuilder MapCreateNote(this IEndpointRouteBuilder app)
{
app.MapPost("/notes", async (CreateNoteRequest req, ISender sender) =>
{
var response = await sender.Send(new CreateNoteCommand(req.Title, req.Body));
return Results.Created($"/notes/{response.Id}", response);
});
return app;
}
}
Todo lo que el agente necesita para entender el endpoint está en un archivo. Cuando escribe un nuevo slice, tiene este archivo como plantilla local.
Endpoints delgados
Los endpoints se mantienen delgados: parsear, validar, despachar, retornar. No contienen lógica de negocio. La lógica de negocio pertenece al handler. El trabajo del endpoint es traducir HTTP a un comando de MediatR y traducir el resultado de vuelta a HTTP.
El límite de interfaz
Si un slice necesita infraestructura (una base de datos, un sistema de archivos, una API externa), la alcanza a través de una interfaz definida en el slice o en una carpeta Common/ compartida. La interfaz es el límite entre el slice y la infraestructura. En el starter, las notas se almacenan detrás de una interfaz INoteStore, lo que significa que el test puede usar una implementación en memoria y el código de producción puede intercambiar una respaldada por base de datos sin cambiar el handler.
Código compartido
El código compartido entre slices (autenticación, middleware de logging, tipos de respuesta comunes) vive en Common/ o en un proyecto compartido. La regla es: nada en Common/ es específico de una funcionalidad. Si un fragmento de código pertenece a una funcionalidad, se queda en la carpeta de esa funcionalidad.
¿Cómo encajan los tests de contrato en un slice?
Los tests de contrato en un proyecto VSA son por slice y ejercitan el endpoint desde afuera. Verifican el contrato HTTP: dado este request, el endpoint retorna este código de estado y esta forma de respuesta. No prueban el handler en aislamiento.
Este es el nivel correcto de abstracción para un agente IA. Cuando el agente añade o modifica un slice, ejecuta el test de contrato para ese slice. Si el test está en verde, el contrato HTTP del slice está intacto. El agente no necesita entender el grafo de llamadas completo - solo necesita que el test pase.
Un test de contrato para el slice Create Note:
// Api.Tests/Features/Notes/CreateNoteTests.cs
public class CreateNoteTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;
public CreateNoteTests(WebApplicationFactory<Program> factory)
=> _client = factory.CreateClient();
[Fact]
public async Task Post_Notes_RetornaCreated_ConIdDeNota()
{
var response = await _client.PostAsJsonAsync("/notes",
new { title = "Nota de Prueba", body = "Cuerpo de prueba" });
response.StatusCode.Should().Be(HttpStatusCode.Created);
var nota = await response.Content.ReadFromJsonAsync<CreateNoteResponse>();
nota!.Id.Should().NotBeEmpty();
nota.Title.Should().Be("Nota de Prueba");
}
}
Este test es la red de seguridad. Si el agente cambia la forma de respuesta del endpoint de manera que rompe el contrato, el test falla. El agente lee el fallo, corrige el cambio y vuelve a ejecutar. Ese loop no requiere intervención humana.
¿Cuándo es VSA la elección incorrecta?
VSA funciona mejor cuando las funcionalidades son distintas. Si tu dominio tiene lógica de negocio extremadamente compleja compartida entre muchas funcionalidades - un motor de precios usado por docenas de slices, un cálculo de riesgo del que depende cada operación financiera - esa lógica compartida se convierte en una preocupación transversal que VSA no organiza bien. Terminas duplicando lógica entre slices (incorrecto) o construyendo un Common/ que se convierte en su propia capa Domain de facto (en cuyo punto tienes Clean Architecture con pasos adicionales).
VSA es una excelente opción para:
- Servicios API donde cada endpoint mapea a una operación de usuario.
- Sistemas con mucho CRUD donde las funcionalidades son en gran medida independientes.
- Productos SaaS pequeños a medianos donde el equipo es pequeño y la velocidad importa.
- Proyectos donde un agente IA hace una parte significativa de la implementación.
Clean Architecture o un modelo de dominio rico es mejor opción para:
- Sistemas donde el modelo de dominio es el producto (lógica financiera, de seguros o sanitaria compleja).
- Equipos que necesitan aplicar límites de dependencia estrictos como mecanismo de gobernanza.
- Proyectos donde el dominio debe ser testeable completamente independientemente de la infraestructura.
Estos no son mutuamente excluyentes. Puedes usar VSA para tu capa API y un modelo de dominio rico para la lógica de negocio compleja que invoca.
FAQ
¿Qué es la arquitectura vertical slice? VSA organiza el código alrededor de funcionalidades (slices) en lugar de capas técnicas. Cada archivo de una funcionalidad vive en una carpeta. Un cambio a una funcionalidad toca una carpeta, no cuatro capas.
¿Por qué VSA es mejor para agentes IA que Clean Architecture? Con VSA, un cambio vive en una carpeta, por lo que un agente IA no deambula por Domain/Application/Infrastructure/Presentation al hacer un cambio en una sola funcionalidad. El agente se mantiene enfocado y el radio de impacto es estrecho.
¿Cómo estructuro una minimal API de .NET 10 como vertical slices?
Crea una carpeta Features/ en tu proyecto API. Cada slice tiene su propia subcarpeta con el endpoint, el handler y los tipos de request/response. El repo dotnet-claude-starter usa esta estructura.
¿Cuándo es VSA la elección incorrecta? VSA funciona mejor cuando las funcionalidades son distintas. Si tu dominio tiene lógica de negocio compleja compartida entre muchas funcionalidades, Clean Architecture o un modelo de dominio rico puede ser mejor opción.
¿Los tests de contrato funcionan por slice? Sí. Cada slice tiene su propio test de contrato que ejercita el endpoint desde afuera (HTTP entrada, HTTP salida). El test vive junto al slice y es la red de seguridad para cambios hechos por el agente.
¿Construyendo un SaaS .NET en producción, agent-first?
El repo github.com/Khavel/dotnet-claude-starter es una minimal API de .NET 10 estructurada como vertical slices, con un test de contrato por slice y la capa de operación de agente (CLAUDE.md, config de MCP, comandos pre-aprobados) integrada en todo. Sharpyard es el kit de producción construido sobre la misma base: auth, multi-tenancy, billing y la capa de agente completa lista para usar. Únete a la lista de espera fundadora para acceso anticipado y el precio fundador.
Relacionado: Claude Code para desarrolladores .NET.
El kit completo de SaaS en .NET, nativo para agentes.
Únete a la lista de espera