# Overview

OpenResponses is a production-grade Elixir implementation of the [Open Responses specification](https://openresponses.dev) — a provider-agnostic API for interacting with large language models.

## What it does

At its simplest: you send a request, you get a response. Behind the scenes, OpenResponses manages the agentic loop, routes to the right provider, streams events back to your client, dispatches tool calls, and tracks conversation history — all without you writing any of that infrastructure.

```
POST /v1/responses
{
  "model": "gpt-4o",
  "input": [{"role": "user", "content": "What's the weather in London?"}],
  "tools": [{"type": "function", "name": "get_weather", "parameters": {...}}]
}
```

Your client receives a stream of Server-Sent Events, or a single JSON response — your choice.

## Why Elixir?

The Open Responses spec describes a system that maps directly onto what the BEAM was built for:

| Spec requirement | BEAM advantage |
|---|---|
| Agentic loop with tool dispatch | One GenServer per request — crash isolation, OTP supervision |
| Semantic SSE streaming | Phoenix handles chunked HTTP natively; PubSub fans out to multiple consumers |
| Multi-provider concurrency | Thousands of simultaneous loops on a single node without threads |
| State machine on responses | AshStateMachine enforces valid transitions at compile time |
| Extensible provider routing | Pattern-match on model names in config — no code changes |

## Supported providers

| Provider | Model pattern | Notes |
|---|---|---|
| OpenAI | `gpt-*` | Near pass-through |
| Anthropic | `claude-*` | Full event translation |
| Google Gemini | `gemini-*` | `contents`/`parts` format |
| Ollama | `llama*`, `mistral*`, `phi*`, `qwen*` | Local models, no API key |
| z.ai | Any | Use Anthropic adapter with custom `base_url` |
| Custom | Anything | Implement `OpenResponses.Adapter` |

## Architecture in one diagram

```
Client
  │
  ▼
POST /v1/responses
  │
  ▼
ResponseController
  │  creates Response (Ash / ETS)
  ▼
LoopSupervisor.start_loop/1
  │
  ▼
Loop (GenServer, one per request)
  │  resolves adapter from model name
  │  applies middleware before_sample
  │  calls adapter.stream/2
  │  processes events
  │  dispatches tool calls
  │  applies middleware after_sample
  │  transitions state machine
  │  caches completed response
  │
  ├──── broadcasts events via PubSub ────► SSE chunks to client
  │
  └──── stores in ResponseCache ────► available for previous_response_id
```

## Next steps

- [Installation](installation.html) — add OpenResponses to your Phoenix app
- [Getting Started](getting_started.html) — make your first request
- [Providers](providers.html) — configure API keys and routing
