AGENTS.md Repository Guidelines Documentation For Developers - Langchain-ai, Langgraph
This document provides guidelines and conventions for developers contributing to this repository. It covers general rules, repository structure, dependency management, and testing procedures to ensure consistency and maintainability across the project.
<general_rules>
General Rules for Developers
When contributing to this repository, it's essential to adhere to certain general rules and best practices to maintain code quality and project consistency. This section outlines these crucial guidelines, focusing on aspects such as code organization, dependency management, and code style.
First and foremost, this repository follows a monorepo structure. Therefore, before introducing new functionalities, it is imperative to conduct a thorough search within the relevant directories to determine if a similar function or module already exists. This practice prevents redundancy and ensures that the codebase remains streamlined. If the required functionality is indeed new, create it in the appropriate directory, either in an existing file or a new one, adhering to the existing directory structure.
Code formatting and linting are critical for maintaining a consistent code style. Before submitting any pull requests (PRs), it is mandatory to run the formatting, linting, and testing scripts. These scripts are typically executed using make format
, make lint
, and make test
commands. These commands ensure that the code adheres to the project's coding standards and that all tests pass, safeguarding against regressions and stylistic inconsistencies.
The project utilizes uv as its primary package manager. This choice reflects a commitment to modern tooling and efficient dependency resolution. When adding or updating dependencies, it is essential to use uv
to ensure compatibility and manage the project's dependencies effectively. Using a consistent package manager across the project helps in avoiding dependency conflicts and streamlines the build process.
When working within the repository, understanding the root Makefile is essential. The Makefile contains various commands for building, testing, and managing the project. Familiarizing yourself with these commands can significantly streamline your development workflow. The Makefile provides a central point for executing common tasks, making it easier to contribute and maintain the project. Pay particular attention to commands related to formatting, linting, testing, and installation, as these are frequently used in the development process.
Consistent code style is paramount for readability and maintainability. This repository uses tools such as ruff
for linting and formatting and mypy
for static type checking. Adhering to the guidelines enforced by these tools ensures that the code is clean, readable, and maintainable. Code style consistency reduces cognitive load when reviewing code and helps to maintain a unified codebase.
For finding existing functionalities, start by navigating the primary directories corresponding to your area of work. This monorepo is structured to make it easier to locate existing components. For instance, when working on features related to LangGraph, the langgraph/
directory is the first place to explore. A systematic approach to searching for existing code can save time and effort, and it promotes code reuse and avoids unnecessary duplication.
In summary, these general rules are designed to ensure that contributions to the repository are consistent, maintainable, and of high quality. By following these guidelines, developers can contribute effectively and help maintain the overall health of the project.
</general_rules>
<repository_structure>
Repository Structure Overview
Understanding the repository structure is crucial for effective navigation and contribution. This section provides a high-level overview of how the repository is organized, focusing on key directories, libraries, and their relationships. The goal is to provide new developers with a clear mental model of the project's architecture, enabling them to quickly locate relevant code and understand the codebase's organization.
This repository adopts a monorepo structure, with the primary source code located under the libs/
directory. The libs/
directory houses several key libraries, each serving a specific purpose within the larger project. Understanding the purpose and dependencies of these libraries is essential for contributing effectively.
Within the libs/
directory, there are eight main libraries: checkpoint, langgraph, prebuilt, checkpoint-postgres, checkpoint-sqlite, cli, sdk-py, and sdk-js. Each of these libraries plays a distinct role, and it's important to understand their individual functionalities and interdependencies. For example, the langgraph
library might depend on the checkpoint
library for certain functionalities, and the sdk-py
and sdk-js
libraries provide interfaces for Python and JavaScript, respectively.
- checkpoint: This library likely handles the management and persistence of checkpoints, which are crucial for maintaining the state and progress of long-running processes.
- langgraph: This is a core library, possibly related to graph-based computations or representations within the project.
- prebuilt: This may contain pre-built components or modules that can be readily used in various parts of the project.
- checkpoint-postgres and checkpoint-sqlite: These libraries probably provide checkpointing functionalities specifically tailored for PostgreSQL and SQLite databases, respectively.
- cli: This library likely implements the command-line interface (CLI) for the project, allowing users to interact with the system through commands.
- sdk-py and sdk-js: These are software development kits (SDKs) for Python and JavaScript, respectively, providing tools and interfaces for developers to integrate the project's functionalities into their applications.
Understanding the dependency hierarchy among these libraries is essential. Some libraries may depend on others, creating a network of relationships that influence how changes in one library might affect others. Analyzing these dependencies helps in planning and executing changes safely and effectively. It also informs the testing strategy, ensuring that changes in a foundational library do not inadvertently break dependent libraries.
Across these libraries, there is a consistent directory structure pattern. This consistency aids in navigation and understanding the codebase. For instance, you might find similar directories for tests, examples, or documentation within each library. This uniformity makes it easier to locate specific types of files or modules across different libraries.
For local development, the repository utilizes an editable install configuration. This setup allows developers to make changes to libraries and immediately see those changes reflected in other parts of the project. This is a significant advantage for rapid development and testing, as it reduces the overhead of rebuilding and reinstalling libraries every time a change is made. The editable install configuration is usually managed through tools like uv.sources
or similar mechanisms, allowing for seamless local development workflows.
In summary, this repository structure is designed to facilitate modular development and maintainability. The monorepo approach, with its clearly defined libraries and consistent directory structure, promotes code reuse and simplifies dependency management. Understanding this structure is key to contributing effectively and navigating the codebase efficiently.
</repository_structure>
<dependencies_and_installation>
Dependencies and Installation Guide
This section provides a concise guide on how to manage dependencies and set up the development environment for this repository. Effective dependency management is crucial for ensuring that the project builds and runs correctly across different environments. This guide focuses on the tools and practices used in this repository to streamline the installation and dependency resolution process.
The primary package manager used in this repository is uv. This choice indicates a commitment to modern tooling and efficient dependency management. uv is designed to be fast and reliable, making it an ideal choice for managing the project's dependencies. It is essential for developers to use uv when adding, updating, or removing dependencies to maintain consistency and avoid conflicts.
To set up the development environment, the recommended approach is to use the make install
command in the root directory. This command automates the installation of all necessary dependencies, configuring the environment for development. The make install
command typically handles tasks such as creating virtual environments, installing packages, and setting up any required environment variables.
The pyproject.toml
file plays a central role in managing dependencies. Each library within the repository typically has its own pyproject.toml
file, which specifies the dependencies required for that library. This configuration pattern allows for clear separation of dependencies and ensures that each library has the necessary packages to function correctly. The pyproject.toml
file also often includes metadata about the library, such as its name, version, and maintainers.
Within the pyproject.toml
files, you'll find patterns that define the project's dependencies, including both direct dependencies and development dependencies. Development dependencies are packages that are required for development tasks such as testing, linting, and formatting. These dependencies are typically separated from the runtime dependencies to keep the production environment as lean as possible.
For common development dependencies, you can expect to see tools like pytest
for testing, ruff
for linting and formatting, and mypy
for static type checking. These tools are essential for maintaining code quality and ensuring that the project adheres to coding standards. By including these dependencies in the pyproject.toml
file, the project ensures that all developers have access to the necessary tools for contributing effectively.
The editable installs, often managed via uv.sources
, allow developers to work on the libraries locally and see the changes reflected immediately without needing to reinstall the packages. This feature greatly speeds up the development process and facilitates rapid iteration. Editable installs create symbolic links to the source code, so changes made in the source files are directly reflected in the installed environment.
In summary, the dependencies and installation process in this repository is designed to be straightforward and efficient. Using uv as the primary package manager, leveraging the make install
command, and understanding the role of pyproject.toml
files are key to setting up the development environment. These practices ensure that all developers have a consistent and reliable environment for contributing to the project.
</dependencies_and_installation>
<testing_instructions>
Testing Instructions
This section provides a comprehensive guide to testing within this repository. Effective testing is crucial for ensuring the reliability and correctness of the code. This guide covers the testing frameworks used, the types of modules that should be tested, how to run tests, and other important considerations for writing and running tests in this project.
The primary testing framework used in this repository is pytest. pytest is a powerful and flexible testing framework for Python, known for its simplicity and extensive plugin ecosystem. It is essential for developers to use pytest when writing and running tests in this project. pytest supports a wide range of testing styles, including unit tests, integration tests, and functional tests.
pytest's support for asyncio is particularly relevant in this repository. asyncio is a Python library for writing concurrent code, and its integration with pytest allows for effective testing of asynchronous code. Many parts of the project likely rely on asynchronous operations, making pytest's asyncio support essential for thorough testing. Tests involving asynchronous code should leverage pytest's asyncio capabilities to ensure proper execution and validation.
To run tests, you can use the make test
command. This command is configured to execute the test suite for the entire project. It provides a convenient way to run all tests and verify that the codebase is functioning correctly. The make test
command typically discovers and runs all tests in the project, providing a summary of the results.
For running tests in a specific library, you can navigate to the library's directory and use the make test
command there. This allows you to focus on testing a specific part of the project, which can be useful when making changes to a particular library. Running tests in isolation can help to quickly identify issues and verify that changes have not introduced regressions.
You can also run specific test files by using the TEST
variable with the make test
command. For example, make test TEST=path/to/test_file.py
will run only the tests in the specified file. This is particularly useful when you are working on a specific feature or bug fix and want to quickly verify your changes without running the entire test suite.
For tests that depend on PostgreSQL, you may need to set up a Docker Compose environment. Docker Compose allows you to define and manage multi-container Docker applications, making it easy to set up a PostgreSQL database for testing purposes. The repository likely includes a docker-compose.yml
file that defines the necessary services for testing with PostgreSQL. To run these tests, you would typically use the docker-compose up
command to start the containers and then run the tests as described above.
The NO_DOCKER
environment variable can be used to skip tests that require Docker. This is useful in environments where Docker is not available or when you want to run tests that do not have external dependencies. Setting NO_DOCKER=1
will typically disable tests that rely on Docker, allowing you to run the remaining tests without encountering errors.
In terms of test structure, each library typically includes a tests/
directory containing the test files. These files follow a consistent naming convention, often using the test_*.py
pattern. This consistency helps in organizing and discovering tests within the project. Within the test files, tests are typically organized into functions or classes, using pytest's conventions for test discovery.
It is important to ensure that all new modules and functionalities are thoroughly tested. Writing comprehensive tests helps to catch bugs early, prevent regressions, and ensure that the codebase remains stable and reliable. Tests should cover a variety of scenarios, including normal cases, edge cases, and error conditions.
In summary, testing in this repository is centered around pytest, with a strong emphasis on testing asynchronous code and PostgreSQL-dependent functionalities. Understanding how to run tests, use Docker Compose for database dependencies, and structure test files is essential for contributing effectively to the project. These practices help to maintain a high level of code quality and ensure the reliability of the software.
</testing_instructions>