# Agent Guidelines for langchain-litellm

This file provides instructions for agentic coding agents working in the langchain-litellm repository.

## Build/Lint/Test Commands

### Running Tests

- Run all unit tests: `make test` or `make tests`
- Run specific test file: `make test TEST_FILE=tests/unit_tests/test_litellm.py`
- Run integration tests: `make integration_test` or `make integration_tests`
- Run specific integration test: `make integration_test TEST_FILE=tests/integration_tests/test_standard.py`
- Run tests with watcher: `make test_watch`

### Linting and Formatting

- Run linter: `make lint`
- Run formatter: `make format`
- Check imports: `make check_imports`
- Spell check: `make spell_check`
- Fix spelling: `make spell_fix`

### Dependency Management

- Install dependencies: `uv sync`
- Install dev dependencies: `uv sync --group dev`
- Install test dependencies: `uv sync --group test`
- Install lint dependencies: `uv sync --group lint`
- Install typing dependencies: `uv sync --group typing`

### Single Test Execution

To run a single test function:
```bash
uv run --group test pytest tests/unit_tests/test_litellm.py::test_litellm_model -v
```

## Code Style Guidelines

### Imports

1. Standard library imports first
2. Third-party imports second
3. Local application imports last
4. Use absolute imports from project root
5. Group imports logically with blank lines between groups
6. Use `from __future__ import annotations` at the top of files
7. Import specific items rather than using wildcards when possible

Example:
```python
from __future__ import annotations

import json
import logging
from typing import Any, Dict, List, Optional

from langchain_core.callbacks import (
    AsyncCallbackManagerForLLMRun,
    CallbackManagerForLLMRun,
)
from langchain_core.language_models.chat_models import BaseChatModel
```

### Formatting

1. Line length: 88 characters (default for Ruff/formatter)
2. Use 4 spaces for indentation (no tabs)
3. Trailing commas in multi-line tuples, lists, and dictionaries
4. Blank lines:
   - Two blank lines between top-level function and class definitions
   - One blank line between method definitions in a class
   - One blank line before return statements (unless it's the only statement)
5. Use Ruff formatter (configured via pyproject.toml)

### Types and Type Hints

1. Use type hints for all function parameters and return values
2. Use `Optional[T]` for potentially None values
3. Use `List[T]`, `Dict[K, V]`, `Tuple[T1, T2]` for collections
4. Use `Any` only when necessary and with justification
5. Use `Literal` for specific string/int values
6. Use `Union` when a parameter can be multiple types
7. Use `Type[SomeClass]` for class objects
8. Use `Protocol` for structural typing when appropriate
9. Enable strict type checking with MyPy (via `make lint`)

### Naming Conventions

1. Classes: `PascalCase`
2. Functions and methods: `snake_case`
3. Constants: `UPPER_SNAKE_CASE`
4. Variables and parameters: `snake_case`
5. Instance attributes: `snake_case`
6. Private attributes/methods: `_snake_case` (leading underscore)
7. Protected attributes/methods: `_snake_case` (single leading underscore)
8. Special methods (dunder): `__snake_case__`

### Error Handling

1. Use specific exception types rather than bare `except:`
2. Raise appropriate built-in exceptions (`ValueError`, `TypeError`, etc.) for invalid inputs
3. Create custom exceptions when needed (inherit from `Exception`)
4. Handle exceptions at the appropriate level - don't catch and ignore unless there's a good reason
5. Use logging for unexpected errors rather than printing
6. Validate inputs early in functions (fail fast)
7. Use `get_from_dict_or_env` utility for getting configuration from dict or environment
8. Include meaningful error messages that help with debugging

### Docstrings

1. Use Google-style docstrings for all public classes, functions, and methods
2. Include a brief summary on the first line
3. Follow with a blank line and detailed description if needed
4. Document all parameters with `:param parameter_name:` and `:type parameter_type:`
5. Document return values with `:returns:` and `:rtype:`
6. Document raised exceptions with `:raises ExceptionType:`
7. Include examples in doctest format when appropriate
8. Keep docstrings updated when modifying code

### Specific Patterns in This Codebase

1. Use `@pre_init` decorator for environment validation in model classes
2. Use `_create_retry_decorator` helper for consistent retry logic
3. Use `get_from_dict_or_env` for configuration resolution
4. Use `_convert_message_to_dict` and `_convert_dict_to_message` for message conversion
5. Follow the pattern of separating concerns with private helper methods (prefixed with `_`)
6. Use proper typing with `BaseModel` for configuration classes
7. Implement both sync and async versions of methods when appropriate
8. Use `__future__` annotations to avoid import circularities

### Testing Guidelines

1. Place unit tests in `tests/unit_tests/` directory
2. Place integration tests in `tests/integration_tests/` directory
3. Name test files as `test_*.py`
4. Name test functions as `test_*_description`
5. Use pytest fixtures for common setup/teardown
6. Mock external dependencies in unit tests
7. Integration tests may require actual API keys (use test credentials)
8. Use descriptive test names that explain what is being tested
9. Follow Arrange-Act-Assert pattern in tests
10. Test both positive and negative cases
11. Test edge cases and boundary conditions
12. Use parametrized tests for similar test cases with different inputs

### Version Control

1. Write clear, descriptive commit messages
2. Keep commits focused on a single change
3. Reference issues in commit messages when applicable
4. Don't commit generated files or dependencies
5. Follow conventional commits format when possible:
   - `feat: add new feature`
   - `fix: fix bug in component`
   - `docs: update documentation`
   - `style: formatting changes`
   - `refactor: refactor code`
   - `test: add/update tests`
   - `chore: update build process`

## Additional Resources

- See [README.md](README.md) for project overview and usage examples
- See [Makefile](Makefile) for all available commands
- See [pyproject.toml](pyproject.toml) for dependency and tool configuration
- Refer to LangChain documentation for integration patterns
- Refer to LiteLLM documentation for provider-specific details