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

# Getting started with AutoGen + Neon

A step-by-step guide to building AI agents using AutoGen and Neon

This guide shows how to integrate AutoGen with Neon. [AutoGen](https://microsoft.github.io/autogen/stable) is an open-source framework developed by Microsoft for building AI agents that can converse, plan, and interact with tools (APIs). With AutoGen and Neon, AI agents can create databases, run SQL queries, and automate data tasks.

In this guide, we'll walk through building an AI agent with a practical example: creating a system that retrieves recent machine learning papers from arXiv and stores them in a Neon database. Following this example, you will learn how to:

- Create an AutoGen agent with Neon API integration.
- Implement database operations (like project creation and SQL queries) as agent tools.
- Set up a workflow where multiple agents work together to accomplish research tasks.

## Prerequisites

Before you begin, make sure you have the following:

- **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 Neon account on the Free plan at [neon.com](https://console.neon.tech/signup).
  - After signing up, create a Neon API key in the [Neon Console](https://console.neon.tech/app/settings/profile) under **Account settings** > **API keys**. Your application uses this key to authenticate with the Neon API.

- **OpenAI account and API key:**
  - This guide uses the `gpt-4o` model from OpenAI to power the AI agent. If you don't have an OpenAI account, sign up at [platform.openai.com](https://platform.openai.com/).
  - Generate a new API key from the [OpenAI Platform API keys section](https://platform.openai.com/api-keys). This key allows AutoGen to interact with OpenAI's models.

With these prerequisites in place, you are ready to build your AI agent.

## AutoGen basics

Before we start building your AI agent, let's understand some fundamental concepts of AutoGen.

### What is AutoGen?

AutoGen is a framework for building applications with LLMs. You build AI workflows from **conversational agents** that are capable of:

- **Conversation:** Engaging in multi-agent dialogues to solve tasks collaboratively.
- **Planning:** Developing and executing strategic plans to achieve goals.
- **Tool use:** Integrating with external tools and APIs to extend their capabilities beyond simple text generation, enabling real-world interactions.

### Key components of AutoGen

- **Agents:** The foundational building blocks in AutoGen. Agents are autonomous entities that can:
  - **Receive and process messages:** Accept and understand messages from users or other agents.
  - **Act autonomously:** Perform tasks, use tools, or generate responses based on their programmed logic and received messages.
  - **Agent types:** AutoGen offers various agent types, including:
    - **`AssistantAgent`:** A general-purpose agent powered by an LLM that can use tools and follow instructions. Use it for general tasks and multi-step reasoning.
    - **`CodeExecutorAgent`:** A specialized agent designed to execute code snippets. Useful for tasks requiring script execution or interacting with system commands.
    - **`UserProxyAgent`:** An agent that serves as an interface for human users. It can relay communications between the user and other agents and can be configured to request human input at specific workflow stages.

- **Teams (Group chat):** AutoGen lets you group agents into teams that work on a problem together. Key team configurations include:
  - **`RoundRobinGroupChat`:** A straightforward team setup where agents communicate in turns, following a round-robin approach to ensure balanced contribution from each member.
  - **`SelectorGroupChat`:** A team configuration with more control over agent selection, including LLM-driven speaker selection for dynamic conversation flow.

- **Tools:** AutoGen agents can use tools to interact with external environments or perform specialized functions. Tools can be:
  - **Python functions:** Custom Python functions that agents can call to execute specific actions or computations.
  - **External APIs:** Integrations with external services, such as web search.

- **Code execution:** AutoGen agents can execute code, so they can handle computation, data manipulation, or system interactions.

- **Termination conditions:** AutoGen lets you define criteria for ending a conversation or task. Examples include:
  - **`TextMentionTermination`:** Ends the conversation when a predefined text or phrase is detected in the dialogue (e.g., "TERMINATE").
  - **`MaxMessageTermination`:** Automatically stops the conversation after a set number of messages have been exchanged, preventing infinite loops.

With these components, you can build anything from a simple chatbot to a multi-agent system.

## Why Neon for AI agents

A few properties of Neon matter for AI agent development:

- **One-second provisioning:** Neon databases can be provisioned in about a second, so agents that create databases on the fly don't wait. Traditional databases often take minutes to provision.

- **Scale to zero and usage-based pricing:** Lakebase Postgres computes scale to zero when idle, so you don't pay for compute while they're suspended (storage still bills). This keeps costs down for agent workflows with unpredictable load and many short-lived databases, and makes "database-per-agent" or "database-per-session" patterns affordable.

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

## Building the AI agent

Let's start building your AI agent. First, create a new directory for your project. For example, you can name it `autogen-neon-example`. Open this new folder in your preferred code editor.

### Setting up a virtual environment

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

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

### Installing 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:

```
autogen-agentchat[openai]
autogen-ext[openai]
python-dotenv
neon-api
psycopg2-binary
```

**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
```

### Configuring 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
OPENAI_API_KEY=YOUR_OPENAI_API_KEY
NEON_API_KEY=YOUR_NEON_API_KEY
```

**Replace the placeholders** `YOUR_OPENAI_API_KEY` and `YOUR_NEON_API_KEY` with the actual API keys you obtained in the [Prerequisites](https://neon.com/guides/autogen-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.

### Creating the `main.py` file

Create a Python file named `main.py` in your project's root directory and copy the following code into it:

```python
import asyncio
import os

import psycopg2
from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_ext.models.openai import OpenAIChatCompletionClient
from dotenv import load_dotenv
from neon_api import NeonAPI
from psycopg2.extras import RealDictCursor

load_dotenv()

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


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)}"


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 to fetch results (for SELECT queries)
        try:
            records = cur.fetchall()
            return f"Query result: {records}"
        except psycopg2.ProgrammingError:
            # For INSERT/UPDATE/DELETE operations
            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()


async def main() -> None:
    model_client = OpenAIChatCompletionClient(model="gpt-4o", temperature=0.6)

    assistant = AssistantAgent(
        name="assistant",
        system_message="""You are a helpful AI assistant.
Solve tasks using your coding and language skills.
You are working with two other agents:
1. 'code_executor': Use this agent for non-database coding tasks such as general-purpose scripts, file manipulation, and system commands.
2. 'db_admin': Use this agent for all database-related tasks.
Do NOT generate or suggest any SQL or database connection code yourself. Clearly mention what needs to be done and send the request to 'db_admin'.

In the following cases, suggest python code (in a python coding block) or shell script (in a sh coding block) for the user to execute.
1. When you need to collect info, use the code to output the info you need, for example, browse or search the web, download/read a file, print the content of a webpage or a file, get the current date/time, check the operating system. After sufficient info is printed and the task is ready to be solved based on your language skill, you can solve the task by yourself.
2. When you need to perform some task with code, use the code to perform the task and output the result. Finish the task smartly.

Solve the task step by step if you need to. If a plan is not provided, explain your plan first. Be clear which step uses code, and which step uses your language skill.
When using code, you must indicate the script type in the code block. The user cannot provide any other feedback or perform any other action beyond executing the code you suggest. The user can't modify your code. So do not suggest incomplete code which requires users to modify. Don't use a code block if it's not intended to be executed by the user.
If you want the user to save the code in a file before executing it, put # filename: <filename> inside the code block as the first line. Don't include multiple code blocks in one response. Do not ask users to copy and paste the result. Instead, use 'print' function for the output when relevant, try to add print statements while sharing code with the user so it will be used for debugging. Check the execution result returned by the user.
If the result indicates there is an error, fix the error and output the code again. Suggest the full code instead of partial code or code changes. If the error can't be fixed or if the task is not solved even after the code is executed successfully, analyze the problem, revisit your assumption, collect additional info you need, and think of a different approach to try.
When you find an answer, verify the answer carefully. Include verifiable evidence in your response if possible.
Reply 'TERMINATE' in the end when the task is completed by everyone.
""",
        model_client=model_client,
    )

    code_executor = CodeExecutorAgent(
        name="code_executor",
        code_executor=LocalCommandLineCodeExecutor(work_dir="coding"),
        sources=["assistant"],
    )

    db_admin = AssistantAgent(
        name="db_admin",
        system_message="""You are a helpful database admin assistant with access to the following tools:
1.  **Project Creation:** Create a new Neon project by providing a project name and receive the connection URI.
2.  **SQL Execution:** Run SQL queries within a Neon database.
Use these tools to fulfill user requests.  For each step, clearly describe the action taken and its result.  Include the tool output directly in the chat.  When multiple SQL queries are required, combine them into a single grouped query.  Present the output of each individual query within the grouped query's response.
""",
        model_client=model_client,
        tools=[create_database, run_sql_query],
    )

    # The termination condition is a combination of text termination and max message termination, either of which will cause the chat to terminate.
    termination = TextMentionTermination("TERMINATE") | MaxMessageTermination(20)

    # The group chat will alternate between the assistant and the code executor.
    group_chat = RoundRobinGroupChat(
        [assistant, code_executor, db_admin], termination_condition=termination
    )

    # `run_stream` returns an async generator to stream the intermediate messages.
    stream = group_chat.run_stream(
        task="Get the 10 most recent Machine Learning papers from arXiv. Print the titles and links to the papers in the chat. Save them in a database named 'arxiv_papers'",
    )
    await Console(stream)


if __name__ == "__main__":
    asyncio.run(main())
```

The following sections walk through the code.

### Import necessary libraries

```python
import asyncio
import os

import psycopg2
from autogen_agentchat.agents import AssistantAgent, CodeExecutorAgent
from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.ui import Console
from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
from autogen_ext.models.openai import OpenAIChatCompletionClient
from dotenv import load_dotenv
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 Python libraries required for the script. These include libraries for AutoGen agents, Neon API interaction, SQL execution, environment variable management, and asynchronous operations. It also initializes the Neon API client using your API key loaded from the `.env` file.

### Define the tools for agent interaction

To enable agents to interact with the Neon database, we define specific tools. In this example, we create two primary tools: `create_database` and `run_sql_query`.

#### Define `create_database` tool

```python
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 defines a tool that allows agents to create new Neon projects programmatically using the `neon_api_client`.

- It accepts `project_name: str` as an argument, which specifies the name for the new Neon project.
- It uses `neon_client.project_create()` to send a request to the Neon API to create a new project.
- Upon successful project creation, it retrieves the connection URI for the newly created Neon database using `neon_client.connection_uri()`.
- It returns a formatted string that confirms the project and database creation and includes the connection URI.
- If project creation fails, it catches the exception and returns an error message.

#### Define `run_sql_query` tool

```python
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 to fetch results (for SELECT queries)
        try:
            records = cur.fetchall()
            return f"Query result: {records}"
        except psycopg2.ProgrammingError:
            # For INSERT/UPDATE/DELETE operations
            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()
```

This Python function is defined as a tool for agents to execute SQL queries directly against a Neon database.

- It takes two arguments: `connection_uri: str`, which is the URI string required to establish a database connection, and `query: str`, the SQL query intended for execution.
- It connects to the Neon database using `psycopg2.connect(connection_uri)`.
- It creates a cursor object using `conn.cursor(cursor_factory=RealDictCursor)`. The `RealDictCursor` is specified to fetch query results as dictionaries, which is often more convenient for data manipulation in Python.
- It executes the provided SQL query using `cur.execute(query)`.
- It includes error handling for SQL query execution. If any exception occurs, it rolls back the transaction using `conn.rollback()` and returns an error message.

### Define `main` asynchronous function

```python
async def main() -> None:
    model_client = OpenAIChatCompletionClient(model="gpt-4o", temperature=0.6)

    assistant = AssistantAgent(
        name="assistant",
        system_message="""... (system message content)""",
        model_client=model_client,
    )

    code_executor = CodeExecutorAgent(
        name="code_executor",
        code_executor=LocalCommandLineCodeExecutor(work_dir="coding"),
        sources=["assistant"],
    )

    db_admin = AssistantAgent(
        name="db_admin",
        system_message="""... (system message content)""",
        model_client=model_client,
        tools=[create_database, run_sql_query],
    )

    termination = TextMentionTermination("TERMINATE") | MaxMessageTermination(20)

    group_chat = RoundRobinGroupChat(
        [assistant, code_executor, db_admin], termination_condition=termination
    )

    stream = group_chat.run_stream(
        task="Get the 10 most recent Machine Learning papers from arXiv. Print the titles and links to the papers in the chat. Save them in a database named 'arxiv_papers'",
    )
    await Console(stream)
```

The `async def main() -> None:` function sets up and runs the AutoGen agents. Here's what happens inside:

- **Initialize model client:**

  ```python
  model_client = OpenAIChatCompletionClient(model="gpt-4o", temperature=0.6)
  ```

  This line initializes the OpenAI model client, specifying `gpt-4o` as the LLM to be used. `OpenAIChatCompletionClient` is configured to interact with OpenAI's API, using the API key you've set up.

- **Create `assistant` agent:**

  ```python
  assistant = AssistantAgent(
      name="assistant",
      system_message="""... (system message)""",
      model_client=model_client,
  )
  ```

  Here, we instantiate the primary agent, `assistant`, using `AssistantAgent`. This agent is the main problem solver. The `system_message` is the most important part of its configuration. It defines its role, capabilities, and instructions on how to interact with other agents and tools. It emphasizes task planning, delegation, and using the specialized `code_executor` and `db_admin` agents for specific sub-tasks.

- **Create `code_executor` agent:**

  ```python
  code_executor = CodeExecutorAgent(
      name="code_executor",
      code_executor=LocalCommandLineCodeExecutor(work_dir="coding"),
      sources=["assistant"],
  )
  ```

  We then create a `CodeExecutorAgent` named `code_executor`. This agent is specialized in executing code and is equipped with `LocalCommandLineCodeExecutor` to run code locally. The `sources=["assistant"]` configuration indicates that this agent is intended to execute code suggested by the `assistant` agent.

- **Create `db_admin` agent:**

  ```python
  db_admin = AssistantAgent(
      name="db_admin",
      system_message="""... (system message content)""",
      model_client=model_client,
      tools=[create_database, run_sql_query],
  )
  ```

  Next, you create another `AssistantAgent`, `db_admin`, which is specifically designed for database administration tasks. We give this agent the `tools=[create_database, run_sql_query]` defined earlier. The `system_message` for `db_admin` instructs it on its role as a database admin assistant and how to use the provided tools.

- **Define termination conditions:**

  ```python
  termination = TextMentionTermination("TERMINATE") | MaxMessageTermination(20)
  ```

  This sets up termination conditions for your group chat. The conversation will end if either the phrase "TERMINATE" is mentioned by any agent (`TextMentionTermination`) or if the conversation reaches 20 messages (`MaxMessageTermination(20)`), whichever comes first. This keeps conversations from running indefinitely.

- **Create `group_chat`:**

  ```python
  group_chat = RoundRobinGroupChat(
      [assistant, code_executor, db_admin], termination_condition=termination
  )
  ```

  We then assemble your agents into a team using `RoundRobinGroupChat`. This configuration ensures that the agents (`assistant`, `code_executor`, `db_admin`) will take turns speaking in a round-robin fashion. The `termination_condition=termination` applies the termination conditions we defined earlier to this chat.

- **Run the chat:**

  ```python
  stream = group_chat.run_stream(
      task="Get the 10 most recent Machine Learning papers from arXiv. Print the titles and links to the papers in the chat. Save them in a database named 'arxiv_papers'",
  )
  await Console(stream)
  ```

  Finally, we initiate and run the group chat using `group_chat.run_stream()`. We provide the initial `task` for the agents: to retrieve the 10 most recent Machine Learning papers from arXiv, display their titles and links, and then store this information in a database named `arxiv_papers`. `Console(stream)` is used to provide a real-time, streaming output of the conversation to the console, making it easy for you to follow along with the agent's interactions.

  **Warning:** This guide uses `LocalCommandLineCodeExecutor` for simplicity, which allows AI agents to execute commands directly on your local machine. **This setup is insecure and not recommended for production environments.** Agents could perform harmful actions on your system.

  For production deployments, use `DockerCommandLineCodeExecutor`. This executor runs code within isolated Docker containers, which limits the agent's access to your system.

  Setting up `DockerCommandLineCodeExecutor` involves additional configuration steps, including Docker setup and image management, which are beyond the scope of this guide. See the [AutoGen documentation](https://microsoft.github.io/autogen/stable/reference/python/autogen_ext.code_executors.docker.html#autogen_ext.code_executors.docker.DockerCommandLineCodeExecutor) for detailed instructions on how to configure and use `DockerCommandLineCodeExecutor` securely.

### Running the example

With your project set up and the `main.py` code in place, you are ready to execute the example.

Open your terminal and run the script using:

```bash
python main.py
```

Executing this command will:

- Launch the `main.py` script, initiating the AutoGen agent team.
- Start the collaborative process as the agents begin to interact to achieve the defined task.
- Display a real-time, step-by-step conversation between the agents directly in your console.
- Show the `assistant` agent planning and delegating sub-tasks to the `code_executor` (for coding needs) and `db_admin` (for database operations).
- Retrieve recent ML papers from arXiv and store them in a Neon database named `arxiv_papers`.

### Expected output

When you run `python main.py`, you'll see a turn-based conversation between your agents in your console.

![Autogen-Neon example output 1](https://neon.com/docs/guides/autogen-neon-output-1.png)
![Autogen-Neon example output 2](https://neon.com/docs/guides/autogen-neon-output-2.png)
![Autogen-Neon example output 3](https://neon.com/docs/guides/autogen-neon-output-3.png)

You can verify the successful completion of the task by checking the [Neon Console](https://console.neon.tech/). The `arxiv_papers` project should have been created, and the recent ML papers from arXiv should be stored in the database.

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

You've built an AutoGen agent team that creates a Neon project and stores data in it. From here, you can add more tools, such as branch creation, or swap in `DockerCommandLineCodeExecutor` for safer code execution.

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

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

## Resources

- [AutoGen documentation](https://microsoft.github.io/autogen/stable/)
- [Neon documentation](https://neon.com/docs)
- [neon_api: Python API wrapper for the Neon API](https://github.com/neondatabase/neon-api-python)
- [Neon API Reference](https://neon.com/docs/reference/api)
- [Neon API keys](https://neon.com/docs/manage/api-keys#creating-api-keys)
- [Postgres for AI agents](https://neon.com/use-cases/ai-agents)

---

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/autogen-neon"}` to https://feedback.neon.tech/ (no auth required).
