Documentation•Reference
Migrate from NestJS to HazelJS
Practical mapping for teams moving a NestJS (or Nest-style) TypeScript backend to HazelJS — especially when adding agents, RAG, or Agent OS.
Quick Reference
- Purpose: Map NestJS modules, controllers, providers, pipes, and guards to HazelJS equivalents, then add AI packages without a second framework.
- When to use: You know NestJS and want HazelJS for AI-native backends, or you are piloting a vertical slice (support agent, RAG API).
- Key concepts:
@HazelModule, controllers, DI providers,@AITask,@Agent,@Tool, HCEL,@hazeljs/rag. - Dependencies:
@hazeljs/core, optionally@hazeljs/ai,@hazeljs/agent,@hazeljs/rag. - Related: HazelJS vs NestJS, NestJS + LangChain vs HazelJS, Introduction.
Should you migrate?
Migrate (or start greenfield on HazelJS) when:
- Agents / RAG are core product surfaces
- You want one DI container for HTTP and AI
- You are tired of Nest + LangChain glue
Stay on NestJS when:
- AI is a thin layer (a few LLM calls)
- Nest ecosystem packages are hard requirements
- Political / rewrite cost exceeds glue-code cost
See the honest tradeoffs in HazelJS vs NestJS.
Concept mapping
| NestJS | HazelJS | Notes |
|---|---|---|
@Module() | @HazelModule() | imports, controllers, providers |
@Controller() | @Controller({ path }) | Route prefix on options object |
@Get / @Post / … | Same decorator names from @hazeljs/core | Familiar HTTP verbs |
@Injectable() | @Injectable() | Provider registration |
| Constructor DI | Constructor DI | Same mental model |
| Guards / pipes / interceptors | Guards / pipes / interceptors | See core guides |
| ConfigModule | @hazeljs/config | Env / typed config |
| Passport / custom auth | @hazeljs/auth, @hazeljs/oauth, CASL | Package docs |
| TypeORM / Prisma | @hazeljs/typeorm, @hazeljs/prisma | First-class modules |
| LangChain in a Nest service | @hazeljs/ai HCEL, @hazeljs/agent, @hazeljs/rag | Prefer native over glue |
Step 1 — Install and bootstrap
npm install @hazeljs/core
# Add when you need AI:
npm install @hazeljs/ai @hazeljs/agent @hazeljs/rag
import { HazelApp, HazelModule, Controller, Get } from '@hazeljs/core';
@Controller({ path: '/health' })
class HealthController {
@Get()
check() {
return { ok: true };
}
}
@HazelModule({
controllers: [HealthController],
})
class AppModule {}
async function bootstrap() {
const app = new HazelApp(AppModule);
await app.listen(3000);
}
bootstrap();
Step 2 — Port a Nest controller
Nest-style:
@Controller('tasks')
export class TasksController {
constructor(private readonly tasks: TasksService) {}
@Get()
findAll() {
return this.tasks.findAll();
}
}
HazelJS:
import { Controller, Get } from '@hazeljs/core';
@Controller({ path: '/tasks' })
export class TasksController {
constructor(private readonly tasks: TasksService) {}
@Get()
findAll() {
return this.tasks.findAll();
}
}
Differences are mostly package imports and path on @Controller. Keep service classes as @Injectable() providers and register them on @HazelModule.
Step 3 — Replace LangChain glue with native AI
If a Nest service wrapped LangChain, prefer HCEL or an agent:
import { Injectable } from '@hazeljs/core';
import { AIService } from '@hazeljs/ai';
@Injectable()
export class AssistService {
constructor(private ai: AIService) {}
async answer(question: string) {
return this.ai.hazel
.prompt('Answer using knowledge base: {{input}}')
.rag('product-docs')
.execute(question);
}
}
Or a decorator agent:
import { Agent, Tool } from '@hazeljs/agent';
@Agent({
name: 'support-agent',
systemPrompt: 'Help customers with orders.',
enableMemory: true,
enableRAG: true,
})
export class SupportAgent {
@Tool({
description: 'Get order status',
parameters: [{ name: 'orderId', type: 'string', required: true }],
})
async getOrder(input: { orderId: string }) {
return { orderId: input.orderId, status: 'shipped' };
}
}
Incremental migration strategies
- Greenfield AI service — New HazelJS service for agents/RAG; Nest keeps classic APIs behind a gateway.
- Vertical slice — Move one domain (e.g. support chat) to HazelJS end-to-end.
- Strangler — Route traffic gradually via
@hazeljs/gatewayor your existing edge proxy.
Avoid a big-bang rewrite of unrelated Nest CRUD unless AI is the reason to move.
Checklist
- Core HTTP module boots with
@hazeljs/core - Controllers/providers mapped; smoke-test routes
- Auth/guards ported or temporarily behind edge auth
- Replace LangChain entrypoints with HCEL / Agent / RAG
- Add observability (
@hazeljs/observability/ Inspector) for LLM paths - Read Agent OS if you need loops, policies, and CI tests