Contributing

Thank you for your interest in contributing to urimai! This guide covers everything you need to set up a development environment and submit changes.

Development setup

Prerequisites

  • Python 3.11+

  • uv (recommended) or pip

  • Git

Clone and install

git clone https://github.com/shivakharbanda/urimAI.git
cd urimAI
uv sync            # installs all dependencies in a virtual environment

To install in editable mode with pip instead:

python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e .

Project structure

urimai/
├── agents/          # LLM-powered agents (one file per agent)
│   ├── query_agent.py
│   ├── enrichment_agent.py
│   ├── schema_inference_agent.py
│   └── ...
├── core/            # Business logic and orchestration
│   ├── chat_session.py
│   ├── csv_ingestion.py
│   ├── db_manager.py
│   ├── export.py
│   ├── profiling/
│   ├── quality/
│   └── ...
├── storage/         # Persistence layer (SQLite metadata)
│   ├── metadata_store.py
│   └── models.py
├── utils/           # Shared helpers
│   ├── display.py   # Rich console output
│   └── llm.py       # LLM provider abstraction
├── config.py        # Configuration management
├── setup_wizard.py  # First-time setup flow
└── main.py          # Typer CLI entry point

Architecture overview

urimai is built around four layers:

Agents (urimai/agents/)

Stateless functions that call an LLM to perform a single task — classifying a question, selecting relevant tables, generating SQL, analysing results, etc. Each agent is defined with PydanticAI and returns a structured Pydantic model.

Core (urimai/core/)

Orchestration logic that wires agents together. chat_session.py drives the interactive loop; csv_ingestion.py handles CSV-to-SQLite conversion; profiling/ and quality/ produce column-level statistics and data-quality reports.

Storage (urimai/storage/)

A thin persistence layer backed by an internal SQLite database (~/.urimai/metadata.db). Pydantic models define the schema; metadata_store.py provides async CRUD operations.

Utils (urimai/utils/)

Shared utilities — llm.py abstracts provider selection and API-key retrieval; display.py wraps Rich for formatted terminal output.

Code style and conventions

The project uses Ruff for both linting and formatting. Configuration lives in pyproject.toml under [tool.ruff].

# Check for lint issues
ruff check .

# Auto-fix what can be fixed
ruff check --fix .

# Format code
ruff format .

Other conventions:

  • Pydantic models for all structured data (agent inputs/outputs, stored metadata).

  • Typer for CLI commands (urimai/main.py).

  • Async patterns — storage operations use aiosqlite; agents use async PydanticAI calls.

How to add a new agent

  1. Create urimai/agents/my_agent.py.

  2. Define a Pydantic result model describing the agent’s output.

  3. Create the agent using pydantic_ai.Agent(...) with a system prompt and the result type.

  4. Write an async function that calls agent.run(...) and returns the result.

  5. Wire the new agent into the appropriate core module (e.g. chat_session.py).

Look at urimai/agents/query_agent.py for a representative example.

Running docs locally

uv sync --extra docs
python -m sphinx docs docs/_build

Then open docs/_build/index.html in your browser.

Submitting changes

  1. Fork the repository and create a feature branch from main.

  2. Make your changes, ensuring ruff check . and ruff format --check . pass.

  3. Push your branch and open a pull request against main.

  4. Describe what you changed and why in the PR description.