Skip to main content
Code contributions are always welcome! Whether you’re fixing bugs, adding features, or improving performance, your contributions help deliver a better developer experience for thousands of developers.

Getting started

Before submitting large new features or refactors, please first open an issue or post to the forum for discussion. This ensures alignment with project goals and prevents duplicate work.

Quick fix: submit a bugfix

For simple bugfixes, you can get started immediately:
1

Reproduce the issue

Before even cloning the repository, ensure you can reliably reproduce the bug. This helps confirm the issue and provides a starting point for your fix. Maintainers and other contributors should be able to reproduce the issue based on your description without additional setup or modifications.
2

Fork the repository

Fork either the LangChain, LangGraph, or Deep Agents repo to your
3

Clone and setup

git clone https://github.com/your-username/name-of-forked-repo.git

# For instance, for LangChain:
git clone https://github.com/parrot123/langchain.git
# Inside your repo, initialize environment and install dependencies
uv venv && source .venv/bin/activate
uv sync --all-groups

# or, to install a specific group only:
uv sync --group test
You will need to install uv if you haven’t previously
4

Create a branch

Create a new branch for your fix. This helps keep your changes organized and makes it easier to submit a pull request later.
git checkout -b your-username/short-bugfix-name
5

Write failing tests

Add unit tests that will fail without your fix. This allows us to verify the bug is resolved and prevents regressions
6

Make your changes

Fix the bug while following our code quality standards. Make the minimal change necessary to resolve the issue. We strongly encourage contributors to comment on the issue before they start coding. For example:
“I’d like to work on this. My intended approach would be to […brief description…]. Does this align with maintainer expectations?”
A 30-second comment often prevents wasted effort if your initial approach is wrong.
7

Verify the fix

Ensure that tests pass and no regressions are introduced. Ensure all tests pass locally before submitting your PR
make format
make lint
make test

# For bugfixes involving integrations, also run:
make integration_tests
# (You may need to set up API testing credentials)
8

Document the change

Update docstrings and/or inline comments if behavior changes
9

Submit a pull request

Follow the PR template provided. If applicable, reference the issue you’re fixing using a closing keyword (e.g. Fixes #ISSUE_NUMBER) so that the issue is automatically closed when your PR is merged.

Full development setup

For ongoing development or larger contributions:
  1. Review our contribution guidelines for features, bugfixes, and integrations
  2. Set up your environment following our setup guide below
  3. Understand the repository structure and package organization
  4. Learn our development workflow including testing and linting

Contribution guidelines

Before you start contributing to LangChain projects, take a moment to think about why you want to. If your only goal is to add a “first contribution” to your resume (or if you’re just looking for a quick win) you might be better off doing a boot-camp or an online tutorial. Contributing to open source projects takes time and effort, but it can also help you become a better developer and learn new skills. However, it’s important to know that it might be harder and slower than following a training course. That said, contributing to open source is worth it if you’re willing to take the time to do things well!

Backwards compatibility

Breaking changes to public APIs are not allowed except for critical security fixes.See our versioning policy for details on major version releases.
Maintain compatibility via:
Always preserve:
  • Function signatures and parameter names
  • Class interfaces and method names
  • Return value structure and types
  • Import paths for public APIs
Acceptable modifications:
  • Adding new optional parameters
  • Adding new methods to classes
  • Improving performance without changing behavior
  • Adding new modules or functions
  • Would this break existing user code?
  • Check if your target is public
  • If needed, is it exported in __init__.py?
  • Are there existing usage patterns in tests?

New features

We aim to keep the bar high for new features. We generally don’t accept new core abstractions from outside contributors without an existing issue that demonstrates an acute need for them. This also applies to changes to infrastructure and dependencies. In general, feature contribution requirements include:
1

Design discussion

Open an issue describing:
  • The problem you’re solving
  • Proposed API design
  • Expected usage patterns
2

Implementation

  • Follow existing code patterns
  • Include comprehensive tests and documentation
  • Consider security implications
3

Integration considerations

  • How does this interact with existing features?
  • Are there performance implications?
  • Does this introduce new dependencies?
We will reject features that are likely to lead to security vulnerabilities or reports.

Security guidelines

Security is paramount. Never introduce vulnerabilities or unsafe patterns.
Security checklist:
  • Validate and sanitize all user inputs
  • Properly escape data in templates and queries
  • Never use eval(), exec(), or pickle on user data, as this can lead to arbitrary code execution vulnerabilities
  • Use specific exception types
  • Don’t expose sensitive information in error messages
  • Implement proper resource cleanup
  • Avoid adding hard dependencies
  • Keep optional dependencies minimal
  • Review third-party packages for security issues

Development environment

Our Python projects use uv for dependency management. Make sure you have the latest version installed.
We strive to keep setup consistent across all Python packages. From the package directory, run:
uv sync --all-groups
make test  # Verify unit tests pass before starting development
Once you’ve reviewed the contribution guidelines, find the package directory for the component you’re working on in the repository structure section below.

Repository structure

LangChain is organized as a monorepo with multiple packages:

Core packages

  • langchain (located in libs/langchain/): Main package with chains, agents, and retrieval logic
  • langchain-core (located in libs/core/): Base interfaces and core abstractions
Located in libs/partners/, these are independently versioned packages for specific integrations. For example:Many partner packages are in external repositories. Please check the list of integrations for details.

Development workflow

Running tests

Directories are relative to the package you’re working in.
We favor unit tests over integration tests when possible. Unit tests run on every pull request, so they should be fast and reliable. Integration tests run on a schedule and require more setup, so they should be reserved for confirming interface points with external services.

Unit tests

Location: tests/unit_tests/ Unit tests cover modular logic that does not require calls to outside APIs. If you add new logic, you should add a unit test. In unit tests, check pre/post processing and mock external dependencies. Requirements:
  • No network calls allowed
  • Test all code paths including edge cases
  • Use mocks for external dependencies
To run unit tests:
make test

# Or directly:
uv run --group test pytest tests/unit_tests

# To run a specific test:
TEST_FILE=tests/unit_tests/test_imports.py make test

Integration tests

Location: tests/integration_tests/ Integration tests cover logic that requires making calls to outside APIs (often integration with other services). Integration tests require access to external services/provider APIs (which can cost money) and therefore are not run by default. Not every code change will require an integration test, but keep in mind that we’ll require/run integration tests separately as part of our review process. Requirements:
  • Test real integrations with external services
  • Use environment variables for API keys
  • Skip gracefully if credentials unavailable
To run integration tests:
make integration_tests

# Or directly:
uv run --group test --group test_integration pytest --retries 3 --retry-delay 1 tests/integration_tests

# To run a specific test:
TEST_FILE=tests/integration_tests/test_openai.py make integration_tests

Code quality standards

Contributions must adhere to the following quality requirements:
Required: Complete type annotations for all functions
def process_documents(
    docs: list[Document],
    processor: DocumentProcessor,
    *,
    batch_size: int = 100
) -> ProcessingResult:
    """Process documents in batches.

    Args:
        docs: List of documents to process.
        processor: Document processing instance.
        batch_size: Number of documents per batch.

    Returns:
        Processing results with success/failure counts.
    """

Dependencies

LangChain packages distinguish between hard dependencies and optional dependencies to keep packages lightweight and minimize installation overhead for users.
Almost all new dependencies should be optional. Use optional dependencies when:
  • The dependency is only needed for specific integrations or features
  • Users can meaningfully use the package without this dependency
  • The dependency is large or has many transitive dependencies
Requirements:
  • Users without the dependency installed must be able to import your code without any side effects (no warnings, no errors, no exceptions)
  • pyproject.toml and uv.lock are not modified
To add an optional dependency:
  1. Add the dependency to the appropriate testing dependencies file (e.g., extended_testing_deps.txt)
  2. Add a unit test that at minimum attempts to import the new code. Ideally, the unit test uses lightweight fixtures to test the logic of the code.
  3. Use the @pytest.mark.requires("package_name") decorator for any unit tests that require the dependency.

Test writing guidelines

In order to write effective tests, there’s a few good practices to follow:
  • Use natural language to describe the test in docstrings
  • Use descriptive variable names
  • Be exhaustive with assertions
def test_document_processor_handles_empty_input():
    """Test processor gracefully handles empty document list."""
    processor = DocumentProcessor()

    result = processor.process([])

    assert result.success
    assert result.processed_count == 0
    assert len(result.errors) == 0

Submitting your PR

Once your tests pass and code meets quality standards:
  1. Push your branch and open a pull request
  2. Follow the provided PR template
  3. Reference related issues using a closing keyword (e.g., Fixes #123)
  4. Wait for CI checks to complete
Address CI failures promptly. Maintainers may close PRs that do not pass CI within a reasonable timeframe.

Getting help

Our goal is to have the most accessible developer setup possible. Should you experience any difficulty getting setup, please ask in the community slack or open a forum post.
You’re now ready to contribute high-quality code to LangChain!

Connect these docs to Claude, VSCode, and more via MCP for real-time answers.