# LLM Providers

Orxaq integrates with multiple LLM providers for AI-powered features like
edge proposals in the DAG editor, scenario analysis, and natural language queries.

## Supported Providers

| Provider | Type | Endpoint | Auth |
|----------|------|----------|------|
| **vLLM** | Local GPU | `http://localhost:8000/v1` | None |
| **Anthropic** | Cloud | `api.anthropic.com` | `ANTHROPIC_API_KEY` |
| **OpenAI** | Cloud | `api.openai.com` | `OPENAI_API_KEY` |

## Configuration

### Environment Variables

```bash
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
```

### vLLM Local Server

Start a local vLLM server (requires a GPU):

```bash
python -m vllm.entrypoints.openai.api_server \
    --model mistralai/Mistral-7B-Instruct-v0.2 \
    --port 8000
```

Orxaq connects to vLLM via its OpenAI-compatible API at
`http://localhost:8000/v1` by default.

## CLI Commands

### Check Provider Health

```bash
orxaq providers check
```

Shows connectivity status for all configured providers.

### List Available Models

```bash
orxaq providers list
```

Shows models available across all providers.

## Intelligent Routing

The `ProviderRouter` automatically selects the best provider based on:

- **Task type**: Fast tasks prefer local vLLM; reasoning tasks prefer Claude.
- **Availability**: Unhealthy providers are skipped.
- **Fallback chain**: If vLLM is down, requests fall through to cloud providers.

### Task Type Mapping

| Task Type | Preferred Providers |
|-----------|-------------------|
| `fast` | vLLM |
| `reasoning` | Anthropic, OpenAI |
| `coding` | Anthropic, OpenAI |
| `creative` | OpenAI, Anthropic |
| `general` | vLLM, Anthropic, OpenAI |

## Graceful Degradation

If no providers are available, all AI features degrade to non-AI mode with
clear messages. Core causal discovery and credit risk features work without
any LLM provider.

## Python API

```python
from orxaq.orchestration import ProviderRegistry, ProviderRouter

# Auto-configure from environment
registry = ProviderRegistry.default()
router = ProviderRouter(registry)

# Route a request (automatic provider selection)
response = router.route("Explain GDP impact on default rates", task_type="reasoning")
print(response.text)

# Check health
health = router.health_check()
for name, info in health.items():
    print(f"{name}: {'OK' if info['healthy'] else 'FAIL'}")
```
