<div align="center">

[![CI](https://img.shields.io/github/actions/workflow/status/agenticraft/agenticraft-types/ci.yml?style=flat-square&label=CI)](https://github.com/agenticraft/agenticraft-types/actions/workflows/ci.yml)
[![coverage](https://img.shields.io/codecov/c/github/agenticraft/agenticraft-types/main?style=flat-square)](https://codecov.io/gh/agenticraft/agenticraft-types)
[![python](https://img.shields.io/badge/python-3.10%2B-blue?style=flat-square)](https://www.python.org/downloads/)
[![license](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](LICENSE)

**Shared type definitions, protocols, and error hierarchy for AgentiCraft packages.**

The type foundation behind [AgentiCraft](https://agenticraft.ai) -- an enterprise-grade platform for building production-ready AI agents and multi-agent systems.

Pydantic v2 models &middot; Protocol classes &middot; Exception hierarchy &middot; Configuration schemas &middot; Zero business logic

</div>

---

## Install

With [uv](https://docs.astral.sh/uv/) (recommended):

```bash
uv add agenticraft-types
```

Or with pip:

```bash
pip install agenticraft-types
```

## Quick Start

```python
from agenticraft_types import (
    CompletionRequest,
    CompletionResponse,
    ProviderName,
    ProviderError,
    RateLimitError,
    RetryConfig,
)

# Build a typed request
request = CompletionRequest(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=100,
)

# Use enums for provider selection
provider = ProviderName.OPENAI

# Catch typed exceptions
try:
    response = await some_provider.complete(request)
except RateLimitError as e:
    print(f"Rate limited by {e.provider}, retry after {e.retry_after}s")
except ProviderError as e:
    print(f"Provider {e.provider} failed: {e}")
```

### Protocol-Based Typing

```python
from agenticraft_types import Provider, Router, CircuitBreakerLike

# Structural typing -- implement the protocol, no inheritance needed
class MyProvider:
    async def complete(self, messages, **kwargs) -> CompletionResponse: ...
    async def stream(self, messages, **kwargs): ...

def route(provider: Provider) -> None:
    # Type-safe without coupling to a base class
    ...
```

## What's Inside

- **`models`** -- Pydantic v2 request/response models (`CompletionRequest`, `CompletionResponse`, `StreamChunk`, `Usage`, `Message`)
- **`enums`** -- Shared enumerations (`ProviderName`, `FailureType`, `RoutingStrategy`, `MessageRole`, `CircuitBreakerState`)
- **`errors`** -- Exception hierarchy (`AgentiCraftError`, `ProviderError`, `RateLimitError`, `AuthenticationError`, etc.)
- **`protocols`** -- `typing.Protocol` classes for structural typing (`Provider`, `Router`, `CircuitBreakerLike`, `KeyPoolLike`)
- **`config`** -- Configuration schemas (`RetryConfig`, `CircuitBreakerConfig`, `RateLimitConfig`)

## Design Rules

- Under 1,000 LOC total
- Zero business logic
- Only dependency: `pydantic>=2.0`
- Apache 2.0 license

## Development

```bash
# Install dev dependencies
uv sync --group dev

# Run tests
uv run pytest tests/ -v

# Run with coverage
uv run pytest tests/ --cov=agenticraft_types --cov-report=html

# Lint
uv run ruff check src/ tests/

# Format
uv run ruff format src/ tests/

# Type check
uv run pyright src/

# Pre-commit hooks
uv run pre-commit install
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.

## License

Apache 2.0

Part of the [AgentiCraft](https://agenticraft.ai) platform.
