Contributing to Upsonic
February 5, 2026 · View on GitHub
Upsonic is an open-source AI Agent Framework. We welcome contributions that align with our standards.
Development Setup
- Clone the repository
- Install
uvif not already installed:pip install uv - Create and activate a virtual environment:
uv venv source .venv/bin/activate # Unix # or .venv\Scripts\activate # Windows - Install the package in editable mode with dev dependencies:
uv pip install -e ".[dev]"
For specific feature development, install the relevant optional dependencies:
uv pip install -e ".[vectordb,storage,models,embeddings,tools]"
Running Tests
Unit Tests
uv run --all-extras pytest tests/unit_tests -v
Smoke Tests (requires Docker)
make smoke_tests
This will automatically start the required Docker services (Redis, PostgreSQL, MongoDB) before running tests.
Running Specific Tests
uv run --all-extras pytest tests/unit_tests/tools/test_common_tools_duckduckgo.py -v
uv run --all-extras pytest tests/smoke_tests/memory -v
Code Standards
Sync/Async Pattern
Every function/method MUST have both synchronous and asynchronous versions:
def process(data: str) -> Result:
"""Synchronous version."""
...
async def aprocess(data: str) -> Result:
"""Asynchronous version - prefix with 'a'."""
...
Type Annotations
All code MUST have proper type annotations. No Any types unless absolutely necessary:
def calculate_score(
items: list[dict[str, float]],
threshold: float = 0.5
) -> tuple[float, list[str]]:
...
Standalone Functions
Functions must be self-contained and receive all dependencies as parameters:
# ✅ Correct
def process_data(client: HttpClient, config: Config, data: str) -> Result:
...
# ❌ Wrong - relies on external state
def process_data(data: str) -> Result:
client = get_global_client() # Don't do this
...
Extension Points
Adding a VectorDB Provider
-
Create a new file in
src/upsonic/vectordb/providers/:src/upsonic/vectordb/providers/your_provider.py -
Implement the
VectorDBProviderinterface fromsrc/upsonic/vectordb/base.py -
Add dependencies to
pyproject.tomlunder a new optional group:[project.optional-dependencies] your-provider = [ "your-client-lib>=x.x.x", ] -
Update the
vectordbgroup to include your vector database -
Add tests in
tests/smoke_tests/vectordb/
Reference: src/upsonic/vectordb/providers/chroma.py
Adding a Model Provider
-
Create a new file in
src/upsonic/models/:src/upsonic/models/your_provider.py -
Implement the required interface pattern (see existing providers)
-
Register in
src/upsonic/models/model_registry.py -
Add dependencies to
pyproject.tomlunder a new optional group:[project.optional-dependencies] your-provider = [ "your-client-lib>=x.x.x", ] -
Update the
modelsgroup to include your model provider -
Add tests in
tests/unit_tests/ortests/smoke_tests/
Reference: src/upsonic/models/openai.py, src/upsonic/models/anthropic.py
Adding a Storage Provider
-
Create a new directory in
src/upsonic/storage/:src/upsonic/storage/your_storage/ ├── __init__.py ├── your_storage.py # Sync implementation ├── async_your_storage.py # Async implementation ├── schemas.py └── utils.py -
Implement the
BaseStorageinterface fromsrc/upsonic/storage/base.py -
Provide BOTH sync and async implementations
-
Add dependencies to
pyproject.toml:[project.optional-dependencies] your-storage = [ "your-client>=x.x.x", ] -
Update the
storagegroup to include your storage -
Add tests in
tests/smoke_tests/memory/
Reference: src/upsonic/storage/postgres/, src/upsonic/storage/redis/
Adding a Tool
-
For common tools, add to
src/upsonic/tools/common_tools/:src/upsonic/tools/common_tools/your_tool.py -
For custom/integration tools, add to
src/upsonic/tools/custom_tools/:src/upsonic/tools/custom_tools/your_tool.py -
Follow the base tool pattern from
src/upsonic/tools/base.py -
Export in the appropriate
__init__.py -
Add tests in
tests/unit_tests/tools/ -
Update the
toolsgroup to include your tool
Reference: src/upsonic/tools/common_tools/duckduckgo.py
Pull Request Guidelines
- Keep PRs focused: One feature or fix per PR
- Include tests: All new code must have test coverage
- Follow type conventions: Proper annotations
- Both sync/async: Implement both versions for any new function
- Run tests locally: Ensure all tests pass before submitting
License
This project is licensed under the MIT License.