DEV Community

Cover image for Building AI Agent with LangGraph and NestJS
Daniel Malek
Daniel Malek

Posted on • Edited on

Building AI Agent with LangGraph and NestJS

github link - https://github.com/Dan1618/nest-langgraph

What we are building and why

This project shows how to build a workflow of an AI agent that helps with data processing. In following application there is provided an example of a stock market portfolio that we want to edit with help of agent, then include human in the loop to verify each of the stock and eventually let the agent write a nice overview of the portfolio.

The main goal of this article is to show capabilities and a demo of LangGraph - opensource library for building complex AI agents.

The UI and workflow

  1. User sees a portfolio that will be reviewed. (this example consists of three items, but could be added more)

  2. After start the agent automatically assigns investment risk property.

  3. Each of stock items are presented to the reviewer so he can approve, reject or edit each stock (human in the loop).

  4. After all items are reviewed by human, the agent generates a nice overview of picked stocks.

So the flow goes like this:

TechStack

Backend framework - NestJS
Templating / UI - Handlebars
LLM orchestration - LangGraph
Chat model - OpenAI API

What is LangGraph?
LangGraph is a specialized framework designed for building complex, stateful AI applications. Instead of running a simple linear sequence, it allows you to structure AI behaviors as graphs—complete with nodes (actions) and edges (decisions)—which makes it the industry standard for creating robust, cyclical AI agent workflows. Major features:
a) Advanced Workflows
Traditional AI structures only go in one direction (Step 1 → Step 2 → Step 3). LangGraph allows for cyclical workflows (loops). This means an AI can try a task, evaluate the result, and loop back to fix its own mistakes if it fails.

  • It also manages a centralized "State," ensuring that every step of the workflow has access to the history of what happened before.

b) Multi-Agent Systems
LangGraph excels at orchestration, allowing you to deploy multiple independent AI agents within the same system.

  • You can break a massive, complex problem down into smaller parts.
  • Each agent can be a specialist (e.g., one Researcher agent, one Writer agent, and one Editor agent).
  • They can collaborate, pass tasks to one another, and transfer control dynamically based on the graph's rules.

c) Native Observability via LangSmith
Debugging autonomous agents can be incredibly difficult because they make decisions on the fly. LangGraph integrates natively with LangSmith to solve this.
With LangSmith connected, you get full visibility into the system:

  • Traceability: See exactly which agent was called, what prompt was sent, and what the response was at every single node.
  • Cost & Latency Tracking: Monitor token usage and execution time for each step of your advanced workflow.
  • Time Travel: Pause the execution, look at the state, and even modify it to test how your agents react to different inputs.

Technical implementation

Setup — NestJS + Handlebars

NestJS gives us a structured, modular backend with dependency injection out of the box. Handlebars is wired in as the view engine so it can serve a lightweight UI without pulling in a full frontend framework.

If you are planning to run this code yourself, please remember to add your OPENAI_API_KEY to .env file.

codebase reviewing

Basically the codebase consists of controller which handles endpoints and service which handles code related to the agent.

The agent's graph is built in constructor of graph.service.ts:

    const workflow = new StateGraph(StateAnnotation)
      .addNode("scoreCompanies", scoreCompanies)
      .addNode("humanReview", humanReview)
      .addNode("generateOverview", generateOverview)
      .addEdge(START, "scoreCompanies")
      .addEdge("scoreCompanies", "humanReview")
      .addEdge("humanReview", "generateOverview")
      .addEdge("generateOverview", END);
Enter fullscreen mode Exit fullscreen mode

The graph has start, end, nodes and edges. Moreover it can be coded with different type of nodes (like ToolNode for MCP-like tools, or RouterNode for returning edges conditionally). You can see in code above that each addEdge function holds a pointer to two nodes.

Visualising the graph with Mermaid

Mermaid is a tool to go from text to a living diagram.
The graph can be visualised with this piece of code:

const graph = await this.appGraph.getGraph();
console.log(graph.drawMermaid());
Enter fullscreen mode Exit fullscreen mode

It will return a diagram code which if you pass to editor (like this https://mermaid.live/) will display as following:

Although this workflow looks very simple here is an example how more advanced LangGraph workflow could look like with more features:

Running the workflow

The workflow starts when user clicks 'Start' in UI and endpint @Post('start') is run. Data from json file is being taken and passed to first node (the data could come from any data source like database).

The First node that is being invoked is scoreCompanies which for each stock element provided from data source asks OpenAI to generate the risk scoring and passes state to next node.

The next node is humanReview which interrupts the graph to wait for response from user. It is important here to notice that for the user's review there is a separate endpoint @Post('review') which resumes the interrupted graph when user clicks approve or reject on the UI. That endpoint provides logic to process all stock items and when that is done it countinues to generateOverview node, which yet again connects to LLM for a text review of provided stock portfolio.

Summary

LangGraph provides a lot of tooling for creating flexible, robust and advanced agent workflows, moreover it works very well with observability libraries for LLM apps like LangSmith. In this post I presented an example workflow with several features, the codebase and ideas how it can be extended.

Top comments (2)

Collapse
 
nick_chebotar_3c18937e136 profile image
Nick Chebotar

Nice write-up, Daniel!
The "human-in-the-loop" pattern in LangGraph is often overlooked but super valuable in real-world agent design - especially for sensitive domains like portfolio reviews. NestJS + LangGraph is a solid combo for structured backend integration.

Did you run into any gotchas with state persistence across the interrupt points in the graph? Would love to see a follow-up on scaling this beyond a demo (e.g., handling concurrent user sessions)

Collapse
 
dan1618 profile image
Daniel Malek • Edited

Hi Nick, that is interesting question. I didn't have to implement the graph for concurrent users, but for sure you can store the state in database to use it from the code level. I will have it in mind to check if it is possible for multiple users to interrupt the graph and will get back to you when figure out.