Agentic.LLM.Gateway (agentic v0.2.2)

Copy Markdown

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))

Summary

Types

Provider atom that the gateway knows how to proxy.

Functions

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.

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

Proxy a request to the real provider.

Types

provider_id()

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

Provider atom that the gateway knows how to proxy.

Functions

base_url(provider_id)

@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(env_map, provider_id)

@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(provider_id, path, headers, body)

@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.