Metadata-Version: 2.4
Name: kortex-ai
Version: 0.1.0
Summary: Agent coordination runtime for multi-agent AI systems
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: aiosqlite>=0.19
Requires-Dist: httpx>=0.25
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: redis>=5.0
Requires-Dist: structlog>=23.1
Provides-Extra: dev
Requires-Dist: mkdocs-material>=9.4; extra == 'dev'
Requires-Dist: pyright>=1.1; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)
![License](https://img.shields.io/badge/license-Apache--2.0-green)
![Tests](https://img.shields.io/badge/tests-passing-brightgreen)

# Kortex

**The coordination runtime for multi-agent AI systems.**

Multi-agent systems break in production. Context gets lost between agent handoffs. There's no cost control — a simple summarization task hits GPT-4 when GPT-4o-mini would do. Failures cascade silently because no one's watching the execution graph.

Kortex fixes this. It sits between your agent framework and your LLM providers to handle **intelligent task routing** (cost/latency/capability-aware model selection), **stateful handoffs** (context preservation with checkpoint chains for rollback), and **failure detection** (structured event streams with automatic recovery).

## Quick Start

```python
import asyncio
from kortex.core.router import ProviderModel, Router
from kortex.core.runtime import AgentDescriptor, KortexRuntime
from kortex.core.state import StateManager
from kortex.core.types import TaskSpec

router = Router()
router.register_model(ProviderModel(
    provider="anthropic", model="claude-sonnet-4-20250514",
    cost_per_1k_input_tokens=0.003, cost_per_1k_output_tokens=0.015,
    avg_latency_ms=800, capabilities=["reasoning", "writing"], tier="balanced",
))

runtime = KortexRuntime(router=router, state_manager=StateManager())
runtime.register_agent(AgentDescriptor("researcher", "Researcher", "Gathers info"))
runtime.register_agent(AgentDescriptor("writer", "Writer", "Drafts content"))

task = TaskSpec(content="Write about AI coordination", complexity_hint="moderate")
result = asyncio.run(runtime.coordinate(task, ["researcher", "writer"]))
print(runtime.get_coordination_summary(result))
```

## Works With Any Model

**Local models** (Ollama, vLLM, llama.cpp, LM Studio):
```python
from kortex.providers.base import GenericOpenAIConnector

ollama = GenericOpenAIConnector(
    base_url="http://localhost:11434/v1",
    name="ollama",
    models=[ProviderModel(provider="ollama", model="llama3", tier="fast",
        cost_per_1k_input_tokens=0, cost_per_1k_output_tokens=0, avg_latency_ms=100)],
)
```

**Cloud APIs** (OpenAI, Anthropic, OpenRouter):
```python
from kortex.providers.registry import ProviderRegistry

registry = ProviderRegistry()
registry.auto_discover()  # reads OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.
```

**Custom endpoints**:
```python
registry.register_openai_compatible(
    name="corporate-llm",
    base_url="https://llm.internal.corp/v1",
    api_key="sk-corp-key",
    extra_headers={"X-Team": "platform"},
    models=[your_model_definitions],
)
```

## Framework Adapters

**LangGraph**:
```python
from kortex.adapters.langgraph import KortexLangGraphAdapter

adapter = KortexLangGraphAdapter(runtime)
wrapped = adapter.wrap_graph(graph, {"node_a": "researcher", "node_b": "writer"})
output, coordination = await wrapped("Analyze this data")
```

**CrewAI**:
```python
from kortex.adapters.crewai import KortexCrewAIAdapter

adapter = KortexCrewAIAdapter(runtime)
descriptors = adapter.create_agents_from_crew(crew)  # auto-infers capabilities
wrapped = adapter.wrap_crew(crew, {"Research Analyst": "researcher"})
output, coordination = await wrapped("Research AI trends")
```

## CLI

```bash
$ kortex status
Kortex Status
Providers (2): openai: OK, anthropic: OK
Models (4): fast: 1, balanced: 2, powerful: 1
Agents: 3

$ kortex models
PROVIDER   MODEL                     TIER      INPUT/1K  OUTPUT/1K  LATENCY
anthropic  claude-sonnet-4-20250514  balanced  $0.0030   $0.01      800ms
openai     gpt-4o-mini               fast      $0.0001   $0.0006    200ms

$ kortex dry-run --task "Analyze data" --complexity complex --pipeline researcher,writer
Routing Decisions:
  Step 1: anthropic/claude-opus-4-20250514 (est. $0.05, 2.0s)
  Step 2: anthropic/claude-sonnet-4-20250514 (est. $0.01, 800ms)
Cost Summary: Total estimated: $0.07
```

Works with no API keys — shows demo models automatically.

## Why Kortex?

- **Framework-agnostic** — wraps LangGraph, CrewAI, or any custom agent system. Never replaces your framework.
- **Fail-open** — if Kortex is unavailable, agents fall back to direct execution. Zero-downtime integration.
- **Any provider** — OpenAI, Anthropic, Ollama, vLLM, or any OpenAI-compatible endpoint. Mix local and cloud in one pipeline.
- **Logs everything** — every routing decision and handoff is captured as a structured event. This data trains the learned router.

## Installation

```bash
pip install kortex-ai
```

```bash
uv add kortex-ai
```

## Examples

| Example | Description |
|---------|-------------|
| [`langgraph_example.py`](examples/langgraph_example.py) | 3-agent pipeline with dry-run and live execution modes |
| [`crewai_example.py`](examples/crewai_example.py) | CrewAI crew wrapping with auto-generated agent descriptors |
| [`custom_provider_example.py`](examples/custom_provider_example.py) | Mixing local Ollama, corporate API, and cloud providers |

All examples run without API keys.

## Documentation

Full docs: [kortex.github.io/kortex](https://kortex.github.io/kortex) *(coming soon)*

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

[Apache-2.0](LICENSE)
