# LangChain on AOCore

LangChain's `ChatOpenAI` (from `langchain-openai`) speaks the OpenAI wire format.
Point `openai_api_base` at the AOCore gateway and pass your AOCore-minted
API key — no AOCore-specific library required.

## Install

LangChain's API surface evolves quickly. Pin to a tested minor range to keep
this example runnable:

```bash
pip install "langchain>=0.3,<0.4" "langchain-openai>=0.2,<0.3"
```

These pins reflect the versions this example was developed against; newer
versions usually work but break compatibility on minor bumps from time to time.

## Set the API key

Mint a key in the developer portal (see [quickstart](../../quickstart.md)) and
export it:

```bash
export AOSENTRY_KEY="sk-..."
```

Optionally override the base URL for a self-hosted gateway:

```bash
export AOSENTRY_BASE_URL="https://your-gateway/v1"
```

## Run

```bash
python chat.py
```

You should see a one-sentence greeting printed to stdout.

## What this example does NOT do

LangChain wraps the OpenAI client and does not expose the raw HTTP response by
default — so the six `X-AOCore-*` quota headers (see
[../../rate-limits.md](../../rate-limits.md)) are **not visible** from the
LangChain example. If you need quota observability per call, drop down to the
OpenAI SDK directly:

```bash
python ../python-openai-sdk/chat.py
```

Common pattern: use LangChain for orchestration / chains / agents, and use the
OpenAI SDK directly for observability-heavy endpoints (rate-limit monitoring,
budget alerts, retry loops that need the `X-AOSentry-RateLimit-Reset` header).

## Notes

- `openai_api_base` is the legacy LangChain field name. Recent versions of
  `langchain-openai` accept `base_url` as an alias. Both work.
- `openai_api_key` likewise has the alias `api_key`. Pick whichever your
  LangChain version supports.
- `model=` accepts any model name in your developer allowlist — see
  [../../models.md](../../models.md) for how the allowlist intersection works.
- For streaming responses, use `llm.stream(...)` instead of `llm.invoke(...)`.
  The chunks arrive incrementally over SSE; LangChain handles the iterator
  shape.

## Related

- [chat.py](./chat.py) — the runnable example
- [../python-openai-sdk/](../python-openai-sdk/) — same calls via the OpenAI SDK with quota headers
- [../../quickstart.md](../../quickstart.md) — minting an API key
- [../../rate-limits.md](../../rate-limits.md) — quota headers (visible from the OpenAI SDK example, not this one)
