# `Agentic.LLM.Gateway`

Transparent LLM API proxy that sits between external coding agents
(Claude Code, OpenCode, Codex, Kimi, etc.) and the actual LLM providers.

Provides functions that can be called from a web layer (e.g. a Phoenix
controller or Plug) to forward Anthropic/OpenAI-format requests,
capture full traffic details, and emit `:agentic` telemetry events
that flow into Worth's X-Ray panel.

## Usage (from web controller)

    {status, headers, body} = Agentic.LLM.Gateway.proxy(
      :anthropic,
      "POST",
      "/v1/messages",
      req_headers,
      req_body
    )

## Environment injection for coding agents

The gateway exposes `base_url/1` so coding-agent protocols can inject
the proxy endpoint into spawned CLI processes:

    config
    |> put_in([:env, "ANTHROPIC_BASE_URL"], Agentic.LLM.Gateway.base_url(:anthropic))

# `provider_id`

```elixir
@type provider_id() :: :anthropic | :openai | atom()
```

Provider atom that the gateway knows how to proxy.

# `base_url`

```elixir
@spec base_url(provider_id()) :: String.t() | nil
```

Returns the local gateway base URL for a provider shape.
The host application (Worth) is expected to mount the gateway
routes and tell us the public port/path.

# `inject_env`

```elixir
@spec inject_env(map(), provider_id()) :: map()
```

Injects gateway environment variables into a coding agent's env map.

Only injects when (1) a gateway base URL is configured and (2) credentials
are actually resolvable for the provider. Without credentials the gateway
would 401 every request, so we leave the CLI to use its own auth (e.g.
Claude Code's OAuth session) by talking to the real provider directly.

# `proxy`

```elixir
@spec proxy(provider_id(), String.t(), [{String.t(), String.t()}], map() | binary()) ::
  {integer(), [{String.t(), String.t()}], Enumerable.t() | binary()}
```

Proxy a request to the real provider.

Returns `{status_code, response_headers, response_body}` where
`response_body` is an *enumerable* of chunks for streaming responses
or a plain string/binary for non-streaming ones.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
