DocumentationReference

Migrate a LangChain Agent to HazelJS

Move a LangChain / LangGraph-style agent into HazelJS @Agent + @Tool (and optional RAG/memory) so HTTP, auth, and agents share one TypeScript module system.

Quick Reference

  • Purpose: Side-by-side mapping from LangChain agents to HazelJS Agent Runtime.
  • When to use: You have a working LangChain agent and want a production Nest-style backend without dual paradigms.
  • Key concepts: @Agent, @Tool, requiresApproval, memory, RAG, AgentGraph / Supervisor, HCEL.
  • Dependencies: @hazeljs/core, @hazeljs/agent, optionally @hazeljs/rag, @hazeljs/ai, @hazeljs/memory.
  • Related: vs LangChain, vs LangGraph, NestJS + LangChain, Agent package.

Should you migrate?

Migrate when:

  • The agent must sit behind authenticated APIs, rate limits, and shared config
  • You are tired of wiring LangChain into Nest/Express manually
  • You want Agent OS loops, policies, and describeAgent tests later

Stay on LangChain/LangGraph when:

  • You depend on specific LangChain integrations HazelJS does not mirror
  • Org process is standardized on LangSmith / LangGraph only
  • The agent is a research script, not a product API

Concept mapping

LangChain / LangGraphHazelJS
ChatOpenAI / chat model@hazeljs/ai providers / @AITask
Tools / @tool@Tool on agent methods
AgentExecutor / createReactAgent@Agent + Agent Runtime execute
LangGraph nodes / edgesAgentGraph, SupervisorAgent, @Delegate
CheckpointersAgent state + @hazeljs/flow for durable business WAIT/resume
Retrievers@hazeljs/rag / .rag() in HCEL
Memory modulesenableMemory + @hazeljs/memory
Mount on Express/NestNative @Controller in the same app

Before (LangChain-shaped)

// Illustrative — model + tools + executor, then mounted on Express/Nest elsewhere
const tools = [lookupOrderTool, refundTool];
const agent = createReactAgent({ llm, tools });
const result = await agent.invoke({ messages: [/* ... */] });

After (HazelJS agent)

import { Agent, Tool } from '@hazeljs/agent';

@Agent({
  name: 'support-agent',
  description: 'Customer support agent',
  systemPrompt: 'You help with orders and refunds. Be concise.',
  enableMemory: true,
  enableRAG: true,
})
export class SupportAgent {
  @Tool({
    description: 'Look up an order by ID',
    parameters: [{ name: 'orderId', type: 'string', required: true }],
  })
  async lookupOrder(input: { orderId: string }) {
    return { orderId: input.orderId, status: 'shipped' };
  }

  @Tool({
    description: 'Process a refund',
    requiresApproval: true,
    parameters: [
      { name: 'orderId', type: 'string', required: true },
      { name: 'amount', type: 'number', required: true },
    ],
  })
  async processRefund(input: { orderId: string; amount: number }) {
    return { success: true, ...input };
  }
}

Register the agent class as a provider in @HazelModule, then execute via Agent Runtime (see Agent package docs for runtime.execute patterns).

Expose over HTTP

import { Controller, Post, Body, HazelModule } from '@hazeljs/core';
import { SupportAgent } from './support.agent';

@Controller({ path: '/support' })
export class SupportController {
  @Post('chat')
  async chat(@Body() body: { message: string }) {
    // Wire to Agent Runtime — see docs/examples/support-agent
    return { message: body.message };
  }
}

@HazelModule({
  controllers: [SupportController],
  providers: [SupportAgent],
})
export class SupportModule {}

Full walkthrough: Support agent example.

Multi-agent and graphs

NeedHazelJS approach
Delegate to peer agents@Delegate({ agent: 'ResearchAgent', ... })
DAG / conditional pipelinesAgentGraph
LLM router / supervisorSupervisorAgent
Long-running business WAIT@hazeljs/flow (not only agent loops)

Details: vs LangGraph, Agent OS.

Incremental migration

  1. Keep LangChain, put a thin HazelJS (or Nest) façade in front — temporary.
  2. Reimplement tools as @Tool methods; parity-test prompts.
  3. Cut over traffic for one vertical (e.g. support) to HazelJS Agent Runtime.
  4. Delete LangChain executor once evals pass (@hazeljs/eval / @hazeljs/testing).

Checklist

  • Tools mapped 1:1 with clear JSON schemas
  • System prompt + memory/RAG flags set on @Agent
  • Sensitive tools use requiresApproval: true
  • HTTP auth matches previous gateway behavior
  • Eval set for golden questions before cutover
  • Read HazelJS vs LangChain

Next steps