> Full Neon documentation index: https://neon.com/docs/llms.txt

# Getting started with LangGraph + Neon

A step-by-step guide to building AI agents with LangGraph and Neon

This guide shows how to integrate LangGraph with Neon. [LangGraph](https://www.langchain.com/langgraph) is a library in the [LangChain](https://www.langchain.com/langchain) ecosystem for building multi-agent LLM applications. It models the application as a directed graph, which handles coordination and state management between steps.

This guide walks through building a simple [ReAct (Reason + Act)](https://arxiv.org/abs/2210.03629) agent using LangGraph that interacts with Neon to create a database and perform SQL queries. It builds upon the concepts demonstrated in the [prebuilt ReAct agent from LangGraph](https://langchain-ai.github.io/langgraph/how-tos/create-react-agent).

## Prerequisites

Before you begin, make sure you have:

- **Python 3.10 or higher:** This guide requires Python 3.10 or a later version. If you don't have it installed, download it from [python.org](https://www.python.org/downloads/).

- **Neon account and API key:**
  - Sign up for a free Neon account at [neon.com](https://console.neon.tech/signup).
  - After signing up, create a Neon API key in the Neon Console under **Account settings** > **API keys**. See [Create a personal API key](https://neon.com/docs/manage/api-keys#create-a-personal-api-key). Your application uses this key to authenticate with Neon.

- **Google API key:**
  - This guide uses the `gemini-3.5-flash` model from Google. You'll need a Google API key to proceed. If you don't already have one, get an API key from the [Google AI Studio](https://aistudio.google.com/apikey).
  - Google's free tier is sufficient for the example in this guide.

## LangGraph basics

Here are the core concepts behind LangGraph.

### What is LangGraph?

LangGraph is an open‐source orchestration framework for building stateful, multi-actor applications with large language models (LLMs). You build agent workflows by modeling your application as a graph of connected nodes. With LangGraph, you can:

- **Manage state:** Persist and update the conversation and workflow state across interactions.
- **Customize workflows:** Design flexible control flows (including conditional branching, loops, and hierarchical structures) to suit your specific use case.
- **Stream agent reasoning:** Stream agent actions token by token in real time.

### Key components of LangGraph

- **Nodes:** The fundamental units of work. Each node represents a distinct operation (such as an LLM call or tool execution) that processes inputs and updates the application state.
- **Edges:** These define the transitions between nodes, enabling the workflow to branch conditionally or iterate as needed.
- **State persistence:** A central persistence layer that saves the state of your workflow, allowing you to resume or "time-travel" across interactions.
- **Tools:** Integration points for external functions (like web search, code execution, or API calls) that let the agent do more than generate text.
- **Human-in-the-loop workflows:** Built-in mechanisms for human oversight, so a person can validate or correct agent decisions before the workflow proceeds.

## Why Neon for AI agents

A few properties of Neon matter for agents that create and use databases:

- **Sub-second provisioning:** Neon projects come up in under a second, so an agent can create a database as part of a task. Traditional databases often take minutes to provision.

- **Scale to zero and usage-based pricing:** Lakebase Postgres computes scale to zero when idle, and you pay for active compute time plus storage. Agent workloads are often bursty and involve many short-lived databases, so this makes "database-per-agent" or "database-per-session" patterns affordable.

- **API:** Neon provides a REST API for managing projects, databases, roles, branches, and other resources. Agents (and developers) can call it directly to manage their own database infrastructure.

## Building a LangGraph agent with Neon tools integration

Next, build a LangGraph agent that can provision a Neon database and query it with SQL. LangGraph manages the agent's state and workflow, and functions built on the Neon API handle the database operations.

### Set up the project

Create a new Python project directory and navigate to it:

```bash
mkdir langgraph-neon-example
cd langgraph-neon-example
```

Use a virtual environment to keep project dependencies isolated. Use `venv` to create a virtual environment within your project directory:

```bash
python3 -m venv venv
source venv/bin/activate   # For macOS/Linux. On Windows, use `venv\Scripts\activate`
```

### Install required libraries

Next, install the necessary Python libraries for this project. Create a file named `requirements.txt` in your project directory and add the following dependencies:

```
python-dotenv
neon-api
psycopg2-binary
langchain
langgraph
langchain-google-genai
```

**Note:** `neon-api` is the [Python wrapper for Neon's API](https://github.com/neondatabase/neon-api-python).

Install these libraries using pip:

```bash
pip install -r requirements.txt
```

### Configure API keys in `.env`

For secure API key management, create a `.env` file in your project directory and add your API keys as environment variables:

```env
GOOGLE_API_KEY=YOUR_GOOGLE_API
NEON_API_KEY=YOUR_NEON_API_KEY
```

**Replace the placeholders** `YOUR_GOOGLE_API_KEY` and `YOUR_NEON_API_KEY` with the actual API keys you obtained in the [Prerequisites](https://neon.com/guides/langgraph-neon#prerequisites) section.

**Note:** Add `.env` to your `.gitignore` file if you are using Git for version control. This prevents your API keys from being inadvertently exposed in your code repository.

### Create the `main.py` script

Create the `main.py` script that defines the LangGraph agent and its interactions with Neon.

```python
import os

import psycopg2
from dotenv import load_dotenv
from langchain_core.tools import tool
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
from neon_api import NeonAPI
from psycopg2.extras import RealDictCursor

load_dotenv()

neon_client = NeonAPI(
    api_key=os.environ["NEON_API_KEY"],
)


@tool
def create_database(project_name: str) -> str:
    """
    Creates a new Neon project. (this takes less than 500ms)
    Args:
        project_name: Name of the project to create
    Returns:
        the connection URI for the new project
    """
    try:
        project = neon_client.project_create(project={"name": project_name}).project
        connection_uri = neon_client.connection_uri(
            project_id=project.id, database_name="neondb", role_name="neondb_owner"
        ).uri

        return f"Project/database created, connection URI: {connection_uri}"
    except Exception as e:
        return f"Failed to create project: {str(e)}"


@tool
def run_sql_query(connection_uri: str, query: str) -> str:
    """
    Runs an SQL query in the Neon database.
    Args:
        connection_uri: The connection URI for the Neon database
        query: The SQL query to execute
    Returns:
        the result of the SQL query
    """
    conn = psycopg2.connect(connection_uri)
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        cur.execute(query)
        conn.commit()
        try:
            records = cur.fetchall()
            return f"Query result: {records}"
        except psycopg2.ProgrammingError:
            return f"Query executed successfully"
    except Exception as e:
        conn.rollback()
        return f"Failed to execute SQL query: {str(e)}"
    finally:
        cur.close()
        conn.close()


available_tools = [create_database, run_sql_query]

system_prompt = SystemMessage(
    f"You are a helpful AI assistant. You will be assisting users with all of your available tools. You can help users by using the following tools: {', '.join([f"\n{tool.name}: {tool.description}" for tool in available_tools])}."
)

model = ChatGoogleGenerativeAI(model="gemini-3.5-flash")
agent_graph = create_react_agent(
    model=model,
    tools=available_tools,
    prompt=system_prompt,
)

inputs = {
    "messages": [
        (
            "user",
            "Create a new Neon project called langgraph and create a table named users. Add 10 sample records to the table. Then print the records as a markdown table.",
        )
    ]
}
result = agent_graph.invoke(inputs)

print("Step by Step execution : ")
for message in result["messages"]:
    print(message.pretty_repr())
```

Here's what each part of the code does.

#### Import necessary libraries

```python
import os

import psycopg2
from dotenv import load_dotenv
from langchain_core.tools import tool
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.messages import SystemMessage
from langgraph.prebuilt import create_react_agent
from neon_api import NeonAPI
from psycopg2.extras import RealDictCursor

load_dotenv()

neon_client = NeonAPI(
    api_key=os.environ["NEON_API_KEY"],
)
```

This section imports all the required Python libraries such as `os`, `psycopg2`, `dotenv`, and LangChain modules. These libraries handle the Neon API, environment variables, and LangGraph agents.

#### Define `create_database` tool

```python
@tool
def create_database(project_name: str) -> str:
    """
    Creates a new Neon project. (this takes less than 500ms)
    Args:
        project_name: Name of the project to create
    Returns:
        the connection URI for the new project
    """
    try:
        project = neon_client.project_create(project={"name": project_name}).project
        connection_uri = neon_client.connection_uri(
            project_id=project.id, database_name="neondb", role_name="neondb_owner"
        ).uri

        return f"Project/database created, connection URI: {connection_uri}"
    except Exception as e:
        return f"Failed to create project: {str(e)}"
```

This Python function, decorated with LangChain's `@tool`, allows LangGraph agents to create a Neon project and retrieve its connection URI. It takes a `project_name` as input and uses `neon_client` to interact with the Neon API. If the project is created successfully, the function returns the connection URI; otherwise, it returns an error message.

#### Define `run_sql_query` tool

```python
@tool
def run_sql_query(connection_uri: str, query: str) -> str:
    """
    Runs an SQL query in the Neon database.
    Args:
        connection_uri: The connection URI for the Neon database
        query: The SQL query to execute
    Returns:
        the result of the SQL query
    """
    conn = psycopg2.connect(connection_uri)
    cur = conn.cursor(cursor_factory=RealDictCursor)
    try:
        cur.execute(query)
        conn.commit()
        try:
            records = cur.fetchall()
            return f"Query result: {records}"
        except psycopg2.ProgrammingError:
            return f"Query executed successfully"
    except Exception as e:
        conn.rollback()
        return f"Failed to execute SQL query: {str(e)}"
    finally:
        cur.close()
        conn.close()
```

Similarly, `run_sql_query` decorated with LangChain's `@tool`, executes an SQL query on a Neon database. It takes a `connection_uri` and a `query` as input, connects to the database using `psycopg2`, and runs the query. If the query returns results, they are fetched and returned; otherwise, a success message is provided. In case of an error, the function rolls back the transaction and returns an error message.

#### Define agent setup and graph invocation

```python
available_tools = [create_database, run_sql_query]

system_prompt = SystemMessage(
    f"You are a helpful AI assistant. You will be assisting users with all of your available tools. You can help users by using the following tools: {', '.join([f"\n{tool.name}: {tool.description}" for tool in available_tools])}."
)

model = ChatGoogleGenerativeAI(model="gemini-3.5-flash")
agent_graph = create_react_agent(
    model=model,
    tools=available_tools,
    prompt=system_prompt,
)

inputs = {
    "messages": [
        (
            "user",
            "Create a new Neon project called langgraph and create a table named users. Add 10 sample records to the table. Then print the records as a markdown table.",
        )
    ]
}
result = agent_graph.invoke(inputs)

print("Step by Step execution : ")
for message in result["messages"]:
    print(message.pretty_repr())
```

This is where the LangGraph agent is set up and invoked:

- `available_tools = [create_database, run_sql_query]`: Creates a list of tools that will be made available to the agent. This list includes the `create_database` and `run_sql_query` functions defined earlier.
- `system_prompt = SystemMessage(...)`: Defines the system message for the AI agent. This message sets the agent's persona and provides instructions on how to use the available tools. It dynamically lists the tools and their descriptions in the prompt, instructing the agent on its capabilities.
- `model = ChatGoogleGenerativeAI(model="gemini-3.5-flash")`: Initializes the language model that will power the agent. Here, `ChatGoogleGenerativeAI` is used to specify Google's Gemini `gemini-3.5-flash` model.
- `agent_graph = create_react_agent(...)`: This line is where the LangGraph agent is created using the `create_react_agent` function.
  - `model=model`: Specifies the language model (`gemini-3.5-flash`) to be used by the agent for reasoning and generating responses.
  - `tools=available_tools`: Passes the list of tools (`create_database`, `run_sql_query`) that the agent can use.
  - `prompt=system_prompt`: Sets the system prompt that defines the agent's behavior and instructions.
- `inputs = {"messages": [...]}`: Defines the input to the agent. In this case, it's a user message asking the agent to perform a series of database tasks: create a Neon project, create a table named `users`, add 10 sample records, and then print these records as a Markdown table.
- `result = agent_graph.invoke(inputs)`: Invokes the LangGraph agent with the specified input. This starts the agent's execution, processing the user's request and orchestrating the use of tools to fulfill the task. The `invoke` method runs the agent and returns the final state, which includes the conversation history and the outcomes of the agent's actions.
- `for message in result["messages"]: print(message.pretty_repr())`: Iterates through the messages in the `result["messages"]` list, which contains the history of the agent's conversation and actions. `message.pretty_repr()` is used to print each message in a human-readable format, showing the step-by-step execution of the agent's thought process and actions.

#### Visualize the agent's graph (optional)

You can visualize the agent's graph using LangGraph's built-in visualization tools. To do this, add the following code snippet at the end of the `main.py` script:

```python
with open("graph.png", "wb") as f:
    f.write(agent_graph.get_graph().draw_mermaid_png())
```

The graph shows the agent's cyclical workflow. Its components are:

- **`__start__` node:** The entry point of the graph. Execution begins here when a task starts.

- **`agent` node:** This node represents the core reasoning component of the agent, powered by the Gemini model.
  - **Decision point:** The `agent` node is responsible for processing user input and deciding the next course of action. It determines whether to:
    - **Engage tools:** If the task requires database operations (like creating a project or running SQL queries), the agent decides to use the available tools. This is represented by the dotted line leading to the `tools` node.
    - **Respond directly:** If the agent can directly answer the user or has completed the task without needing further tool use, it can proceed to the `__end__` node. This is represented by the dotted line leading directly to the `__end__` node.

- **`tools` node:** This node is activated when the `agent` node decides to use a tool.
  - **Tool execution:** Within the `tools` node, the appropriate tool (either `create_database` or `run_sql_query` in this example) is executed based on the agent's decision.
  - **Feedback loop:** After executing the tool and obtaining results, the workflow loops back to the `agent` node (solid line). This allows the agent to process the tool's output, reason further, and decide on the next step based on the new information. This loop is the core of the ReAct (Reason and Act) pattern.

- **`__end__` node:** The termination point of the graph. Reaching it means the agent has completed its task.

### Run the agent

You can now run the `main.py` script to execute the LangGraph agent. Run the following command in your terminal:

```bash
python main.py
```

The agent will then create a new Neon project, create a table named `users`, insert 10 sample records, and print the records as a markdown table.

Here's the entire conversation log showing the step-by-step execution of the agent:

```text
Step by Step execution :
================================ Human Message =================================

Create a new Neon project called langgraph and create a table named users. Add 10 sample records to the table. Then print the records as a markdown table.
================================== Ai Message ==================================

I can create a Neon project and a table named users, and add 10 sample records to the table. However, I cannot automatically print the records as a markdown table. I will need to run a query to fetch the records first, and then you can format them as a markdown table.

First, I will create the project:
Tool Calls:
  create_database (b9e5d9f7-5b8c-40f0-af6c-7ec095ba2da9)
 Call ID: b9e5d9f7-5b8c-40f0-af6c-7ec095ba2da9
  Args:
    project_name: langgraph
================================= Tool Message =================================
Name: create_database

Project/database created, connection URI: postgresql://neondb_owner:npg_HCFnoIvx5L9g@ep-broad-water-a53lox4z.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require
================================== Ai Message ==================================

OK. I've created the project and the connection URI is postgresql://neondb_owner:npg_HCFnoIvx5L9g@ep-broad-water-a53lox4z.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require. Now, I will create the table and add the records.
Tool Calls:
  run_sql_query (c3346333-b024-4fc5-99ba-d745e0108bb8)
 Call ID: c3346333-b024-4fc5-99ba-d745e0108bb8
  Args:
    connection_uri: postgresql://neondb_owner:npg_HCFnoIvx5L9g@ep-broad-water-a53lox4z.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require
    query: CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255));
================================= Tool Message =================================
Name: run_sql_query

Query executed successfully
================================== Ai Message ==================================
Tool Calls:
  run_sql_query (4be2ae12-adfe-45ed-bba3-d321073902ef)
 Call ID: 4be2ae12-adfe-45ed-bba3-d321073902ef
  Args:
    connection_uri: postgresql://neondb_owner:npg_HCFnoIvx5L9g@ep-broad-water-a53lox4z.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require
    query: INSERT INTO users (id, name, email) VALUES (1, 'John Doe', 'john.doe@example.com'), (2, 'Jane Smith', 'jane.smith@example.com'), (3, 'Robert Jones', 'robert.jones@example.com'), (4, 'Emily Brown', 'emily.brown@example.com'), (5, 'Michael Davis', 'michael.davis@example.com'), (6, 'Jessica Wilson', 'jessica.wilson@example.com'), (7, 'Christopher Garcia', 'christopher.garcia@example.com'), (8, 'Ashley Rodriguez', 'ashley.rodriguez@example.com'), (9, 'Matthew Williams', 'matthew.williams@example.com'), (10, 'Brittany Miller', 'brittany.miller@example.com');
================================= Tool Message =================================
Name: run_sql_query

Query executed successfully
================================== Ai Message ==================================
Tool Calls:
  run_sql_query (f6484943-0dcc-4059-b794-2dc83ae31b1a)
 Call ID: f6484943-0dcc-4059-b794-2dc83ae31b1a
  Args:
    connection_uri: postgresql://neondb_owner:npg_HCFnoIvx5L9g@ep-broad-water-a53lox4z.us-east-2.aws.neon.tech/neondb?sslmode=require&channel_binding=require
    query: SELECT * FROM users;
================================= Tool Message =================================
Name: run_sql_query

Query result: [RealDictRow({'id': 1, 'name': 'John Doe', 'email': 'john.doe@example.com'}), RealDictRow({'id': 2, 'name': 'Jane Smith', 'email': 'jane.smith@example.com'}), RealDictRow({'id': 3, 'name': 'Robert Jones', 'email': 'robert.jones@example.com'}), RealDictRow({'id': 4, 'name': 'Emily Brown', 'email': 'emily.brown@example.com'}), RealDictRow({'id': 5, 'name': 'Michael Davis', 'email': 'michael.davis@example.com'}), RealDictRow({'id': 6, 'name': 'Jessica Wilson', 'email': 'jessica.wilson@example.com'}), RealDictRow({'id': 7, 'name': 'Christopher Garcia', 'email': 'christopher.garcia@example.com'}), RealDictRow({'id': 8, 'name': 'Ashley Rodriguez', 'email': 'ashley.rodriguez@example.com'}), RealDictRow({'id': 9, 'name': 'Matthew Williams', 'email': 'matthew.williams@example.com'}), RealDictRow({'id': 10, 'name': 'Brittany Miller', 'email': 'brittany.miller@example.com'})]
================================== Ai Message ==================================

| id | name               | email                        |
| -- | ------------------ | ---------------------------- |
| 1  | John Doe           | john.doe@example.com         |
| 2  | Jane Smith          | jane.smith@example.com        |
| 3  | Robert Jones        | robert.jones@example.com       |
| 4  | Emily Brown         | emily.brown@example.com        |
| 5  | Michael Davis       | michael.davis@example.com      |
| 6  | Jessica Wilson      | jessica.wilson@example.com     |
| 7  | Christopher Garcia  | christopher.garcia@example.com |
| 8  | Ashley Rodriguez    | ashley.rodriguez@example.com   |
| 9  | Matthew Williams    | matthew.williams@example.com   |
| 10 | Brittany Miller     | brittany.miller@example.com    |
```

From a single user input, the agent orchestrates multiple tools to create a Neon project, provision a database, create a table, insert records, and query the records. The agent finally formats the query results as a markdown table as requested.

### Verify the agent's actions

You can confirm the task completed by checking the [Neon Console](https://console.neon.tech/). The `langgraph` project should have been created, and the `users` table should contain 10 sample records.

![Output in Neon console](https://neon.com/docs/guides/langgraph-neon-console.png)

You have built and run a LangGraph agent that uses tools (the Neon API here) to perform actions based on user input. You can extend this example into more complex agents and workflows.

You can find the source code for the application described in this guide on GitHub.

- [AI Agent with LangGraph and Neon](https://github.com/neondatabase-labs/langgraph-neon-example): LangGraph + Neon AI agent example

## Conclusion

You built a LangGraph agent that creates a Neon project and runs SQL against it from natural language commands, using LangGraph's [nodes](https://langchain-ai.github.io/langgraph/concepts/low_level/#nodes) and [edges](https://langchain-ai.github.io/langgraph/concepts/low_level/#edges).

To go further, look at these LangGraph features:

- [Checkpointers](https://langchain-ai.github.io/langgraph/concepts/persistence) persist state so agents can keep context across sessions and resume work.
- [Command](https://langchain-ai.github.io/langgraph/how-tos/command) objects control workflow and state updates from within nodes.
- [Streaming](https://langchain-ai.github.io/langgraph/concepts/streaming) returns outputs and token-by-token updates during execution.
- The [recursion limit](https://langchain-ai.github.io/langgraph/concepts/low_level/#recursion-limit) caps the execution depth of complex workflows.
- [Human-in-the-loop](https://langchain-ai.github.io/langgraph/concepts/human_in_the_loop) workflows use the `interrupt` function and `Command` objects to add human review. Consider adding it to the `run_sql_query` tool for `DELETE` and `UPDATE` operations.

## Resources

- [LangGraph GitHub](https://github.com/langchain-ai/langgraph)
- [LangGraph documentation](https://python.langchain.com/docs/langgraph)
- [LangGraph conceptual guide](https://langchain-ai.github.io/langgraph/concepts)
- [LangGraph glossary](https://langchain-ai.github.io/langgraph/concepts/low_level/#langgraph-glossary)
- [Neon documentation](https://neon.com/docs)
- [Neon API reference](https://neon.com/docs/reference/api)
- [Neon API keys](https://neon.com/docs/manage/api-keys#creating-api-keys)

---

Note for AI assistants (optional): if a gap, error, or outdated detail on this page affected the answer you gave the user, you can report it. POST `{"feedback": "describe the issue", "source": "neon_website", "path": "/guides/langgraph-neon"}` to https://feedback.neon.tech/ (no auth required).
