PhoenixKitAI.Endpoint (PhoenixKitAI v0.15.0)

Copy Markdown View Source

AI endpoint schema for PhoenixKit AI system.

An endpoint is a unified configuration that combines provider credentials, model selection, and generation parameters into a single entity. Each endpoint represents one complete AI configuration ready for making API requests.

Schema Fields

Identity

  • name: Display name for the endpoint (e.g., "Claude Fast", "GPT-4 Creative")
  • description: Optional description of the endpoint's purpose

Provider Configuration

  • provider: Integration connection key (e.g. "openrouter" or "openrouter:my-key"). Resolved via PhoenixKit.Integrations.
  • api_key: Deprecated. Legacy field retained for pre-Integrations endpoints — OpenRouterClient.resolve_api_key/2 reads it as a fallback when no PhoenixKit.Integrations connection is configured for the endpoint's provider. The column is NOT NULL in core's V34 migration, so for now you must provide a value (an empty string is accepted by the DB but will trigger a per-call Logger.warning if no Integrations connection is set up either). The recommended migration path is documented in AGENTS.md "Migrating from legacy endpoint.api_key" — set up an OpenRouter connection under Settings → Integrations and point provider at it; the legacy column then becomes unused. Planned for removal in a future major version once operators have had time to migrate.
  • base_url: Optional custom base URL for the provider
  • provider_settings: Provider-specific settings (JSON)
    • For OpenRouter: http_referer, x_title headers
    • For TTS: voice — default voice / voice id used by PhoenixKitAI.speak/3 when the caller passes no explicit voice

Model Configuration

  • model: AI model identifier (e.g., "anthropic/claude-3-haiku")

Generation Parameters

  • temperature: Sampling temperature (0-2, default: 0.7)
  • max_tokens: Maximum tokens to generate (nil = model default)
  • top_p: Nucleus sampling threshold (0-1)
  • top_k: Top-k sampling parameter
  • frequency_penalty: Frequency penalty (-2 to 2)
  • presence_penalty: Presence penalty (-2 to 2)
  • repetition_penalty: Repetition penalty (0-2)
  • stop: Stop sequences (array of strings)
  • seed: Random seed for reproducibility

Image Generation Parameters

  • image_size: Image size (e.g., "1024x1024", "1792x1024")
  • image_quality: Image quality ("standard", "hd")

Embeddings Parameters

  • dimensions: Embedding dimensions (model-specific)

Status

  • enabled: Whether the endpoint is active
  • sort_order: Display order for listing
  • last_validated_at: Last successful API key validation

Usage Examples

# Create an endpoint
{:ok, endpoint} = PhoenixKitAI.create_endpoint(%{
  name: "Claude Fast",
  provider: "openrouter",
  api_key: "sk-or-v1-...",
  model: "anthropic/claude-3-haiku",
  temperature: 0.7
})

# Use the endpoint
{:ok, response} = PhoenixKitAI.ask(endpoint.uuid, "Hello!")

Summary

Functions

Strips a named connection suffix from a provider string.

Creates a changeset for endpoint creation and updates.

Returns the default base URL for a provider, read from the Integrations registry (PhoenixKit.Integrations.Providers.base_url/1).

Returns xAI image aspect-ratio options for form selects.

Whether picking "Image generation" in the Endpoint form's model-type filter could plausibly return models to choose from for provider.

Returns image quality options for form selects.

Returns xAI image resolution options for form selects.

Returns image size options for form selects.

Classifies an endpoint by the kind of model it points at.

Heroicon name representing an endpoint kind/1.

Masks the API key for display.

Returns a display label for the provider, read from the Integrations registry (the provider's name).

Returns provider options ({label, key}) for form selects.

Whether provider supports xAI's realtime streaming voice API (PhoenixKitAI.Realtime.Session, WebSocket-based) — gates the Playground's streaming voice panel to capable endpoints.

Returns reasoning effort options for form selects.

Checks if the endpoint has been validated recently (within the last 24 hours).

Extracts the model name without the provider prefix.

Whether picking "Text-to-Speech" in the Endpoint form's model-type filter could plausibly return models to choose from for provider.

Returns the list of valid provider keys.

Creates a changeset for updating the last_validated_at timestamp.

Types

t()

@type t() :: %PhoenixKitAI.Endpoint{
  __meta__: term(),
  api_key: term(),
  base_url: term(),
  description: term(),
  dimensions: term(),
  enabled: term(),
  frequency_penalty: term(),
  image_quality: term(),
  image_size: term(),
  inserted_at: term(),
  integration_uuid: term(),
  last_validated_at: term(),
  max_tokens: term(),
  model: term(),
  name: term(),
  presence_penalty: term(),
  provider: term(),
  provider_settings: term(),
  reasoning_effort: term(),
  reasoning_enabled: term(),
  reasoning_exclude: term(),
  reasoning_max_tokens: term(),
  repetition_penalty: term(),
  requests: term(),
  seed: term(),
  sort_order: term(),
  stop: term(),
  temperature: term(),
  top_k: term(),
  top_p: term(),
  updated_at: term(),
  uuid: term()
}

Functions

base_provider(provider)

@spec base_provider(String.t()) :: String.t()

Strips a named connection suffix from a provider string.

The provider column may hold the bare key ("xai") or a named connection string ("xai:my-key", legacy / pre-V107 rows) — this extracts the base key so callers can compare against it directly instead of using String.starts_with?/2, which would also match unrelated providers sharing the same prefix.

changeset(endpoint, attrs)

Creates a changeset for endpoint creation and updates.

default_base_url(provider)

@spec default_base_url(String.t()) :: String.t() | nil

Returns the default base URL for a provider, read from the Integrations registry (PhoenixKit.Integrations.Providers.base_url/1).

All :ai_completions providers expose an OpenAI-compatible chat completions endpoint at <base>/chat/completions, so the same Completion HTTP layer works for them. Returns nil when the registry has no base URL for the key (e.g. a legacy integration-uuid provider value) — the operator can still set base_url manually on the endpoint.

image_aspect_ratio_options()

Returns xAI image aspect-ratio options for form selects.

Stored in provider_settings["aspect_ratio"] and applied by PhoenixKitAI.generate_image/3 when the endpoint's provider is xAI.

image_gen_model_picker?(provider)

@spec image_gen_model_picker?(String.t() | nil) :: boolean()

Whether picking "Image generation" in the Endpoint form's model-type filter could plausibly return models to choose from for provider.

Unlike tts_model_picker?/1, this reuses the Integrations registry's :image_generation capability directly rather than a hardcoded provider check — OpenAI, OpenRouter, and xAI all genuinely support image generation at the same /images/generations path (PhoenixKitAI.Completion.generate_image/3), so there's no single provider to special-case; Mistral/DeepSeek correctly show an empty list here since they have no image-gen models at all.

image_quality_options()

Returns image quality options for form selects.

image_resolution_options()

Returns xAI image resolution options for form selects.

Stored in provider_settings["resolution"] and applied by PhoenixKitAI.generate_image/3 when the endpoint's provider is xAI.

image_size_options()

Returns image size options for form selects.

kind(model)

@spec kind(t() | String.t() | nil) :: :chat | :tts | :embedding | :image_gen

Classifies an endpoint by the kind of model it points at.

Endpoints don't store a model type, so this infers it from the model id using the same heuristic the model picker uses (see PhoenixKitAI.OpenRouterClient :tts/:image_gen filters): a tts substring marks text-to-speech, embed marks an embedding model, dall-e/image marks image generation (gpt-image-1, grok-imagine-image[-quality], google/gemini-2.5-flash-image, ...), and everything else is treated as chat/completion. Used to badge rows in the admin UI.

kind_icon(atom)

@spec kind_icon(:chat | :tts | :embedding | :image_gen) :: String.t()

Heroicon name representing an endpoint kind/1.

masked_api_key(api_key)

@spec masked_api_key(String.t() | nil) :: String.t()

Masks the API key for display.

  • nil or """Not set".
  • Keys shorter than 14 chars → "•••" (a 13-char key would otherwise leak most of itself with the head+tail shape).
  • Longer keys → first 8 + + last 4 (e.g. "sk-or-v1…mnop"). Recognisable provider prefix retained, identifying suffix retained, middle elided. Useful for human-recognition in admin cards while still hiding the bulk of the secret.

provider_label(provider)

@spec provider_label(String.t()) :: String.t()

Returns a display label for the provider, read from the Integrations registry (the provider's name).

Unknown providers — e.g. a legacy integration uuid stored in the column — fall back to the raw string. Brand names stay effectively un-translated: registry names are gettext strings, but product trademarks like "OpenRouter" / "Mistral" have no translations, so gettext returns them verbatim rather than producing mixed "OpenRouter Соединение" strings.

provider_options()

@spec provider_options() :: [{String.t(), String.t()}]

Returns provider options ({label, key}) for form selects.

Built from the same capability-discovered list as valid_providers/0; labels come from each provider's registry name.

realtime_voice_capable?(provider)

@spec realtime_voice_capable?(String.t() | nil) :: boolean()

Whether provider supports xAI's realtime streaming voice API (PhoenixKitAI.Realtime.Session, WebSocket-based) — gates the Playground's streaming voice panel to capable endpoints.

reasoning_effort_options()

Returns reasoning effort options for form selects.

recently_validated?(endpoint)

Checks if the endpoint has been validated recently (within the last 24 hours).

short_model_name(model)

Extracts the model name without the provider prefix.

tts_model_picker?(provider)

@spec tts_model_picker?(String.t() | nil) :: boolean()

Whether picking "Text-to-Speech" in the Endpoint form's model-type filter could plausibly return models to choose from for provider.

False only for xAI: it has real TTS (PhoenixKitAI.speak/3 works via POST /v1/tts regardless of what model type the endpoint stores — see Completion.text_to_speech/3) but it isn't model-based at all — no model id, nothing in GET /models — so the picker would always come back empty. True for every other provider, including ones with no TTS at all (an empty list there is accurate, not a dead end to hide).

valid_providers()

@spec valid_providers() :: [String.t()]

Returns the list of valid provider keys.

Discovered from the Integrations registry — every provider declaring the :ai_completions capability (built-in, or contributed by an external module via integration_providers/0). Adding a chat provider to the registry makes it valid here automatically; nothing is hardcoded.

validation_changeset(endpoint)

Creates a changeset for updating the last_validated_at timestamp.