Docs

AI API reference

The AI API is how your code calls models through a linked AI resource: an SDK client, the binding it reads, and the gateway endpoints underneath. A binding is the connection details Alien injects into each workload linked to the resource, which the SDK client reads.

In TypeScript, ai(name) from @alienplatform/sdk returns a client. In Python, ai(name).connection() from alienplatform returns an endpoint for any OpenAI- or Anthropic-compatible client.

There is no Rust client. Rust and other languages call the endpoints directly.

The binding

Linking an AI resource injects ALIEN_<NAME>_BINDING: the resource id uppercased, with hyphens replaced by underscores. A resource named llm becomes ALIEN_LLM_BINDING.

The value is a JSON object tagged by service:

servicePlatformFields
bedrockAWSregion
vertexGCPproject, location
foundryAzureendpoint, account
external-aiKubernetes, Machines, Local, or any external bindingprovider, apiKey

The cloud variants carry no credential: the workload's own identity authorizes each call. external-ai carries a provider key, and the SDK calls that provider directly. provider is openai or anthropic.

TypeScript

ai

function ai(name: string): Ai

Returns a client for the AI resource name. The binding is resolved, and on a cloud binding the gateway is started, on the first call. A failed start isn't cached, so the next call retries.

chat.completions.create

create(
  params: ChatCompletionCreateParams & { stream?: false },
): Promise<ChatCompletion>

create(
  params: ChatCompletionCreateParams & { stream: true },
): Promise<AsyncIterable<ChatCompletionChunk>>

Sends an OpenAI Chat Completions request. Works for every model. Models that don't speak Chat Completions natively, Claude and the GPT-5 family, are reached through protocol translation.

const llm = ai("llm")

const completion = await llm.chat.completions.create({
  model: "gpt-oss-120b",
  messages: [{ role: "user", content: "Summarize this order." }],
})

const stream = await llm.chat.completions.create({
  model: "gpt-oss-120b",
  messages: [{ role: "user", content: "Summarize this order." }],
  stream: true,
})
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "")
}
ParameterTypeRequiredNotes
modelstringYesAn id from getAvailableModels(), with or without the byo/ prefix.
messagesArray<{ role: string; content: string | object }>Yescontent takes a string or content parts.
streambooleanNotrue returns an async iterable of chunks.

Any other field is passed through. On a model's native protocol it reaches the provider unchanged.

responses.create

create(params: ResponseCreateParams & { stream?: false }): Promise<Response>
create(params: ResponseCreateParams & { stream: true }): Promise<AsyncIterable<ResponseStreamEvent>>

Sends an OpenAI Responses request. Native on AWS for the GPT-5 family, gpt-oss-20b, and gpt-oss-120b. Other models are reached through translation.

const response = await ai("llm").responses.create({
  model: "gpt-5.5",
  input: "Summarize this order.",
})
ParameterTypeRequiredNotes
modelstringYesA model id.
inputstring | Array<{ role: string; content: string }>YesThe prompt.
streambooleanNotrue returns an async iterable of events.

Throws AI_RESPONSES_API_UNSUPPORTED on an external binding whose provider is anthropic, since Anthropic's API has no Responses endpoint.

getAvailableModels

getAvailableModels(): Promise<AiModel[]>

Lists the models for this deployment.

const models = await ai("llm").getAvailableModels()
// [{ id: "byo/gpt-oss-20b", provider: "openai", displayName: "GPT-OSS 20B" }, …]

On a cloud binding this is Alien's model list for that cloud, with ids in the byo/ namespace. It doesn't call the provider.

On an external binding it's a fixed list per provider: gpt-4o-mini and gpt-4o for openai, and claude-opus-4-8, claude-sonnet-5, and claude-haiku-4-5 for anthropic. See Model availability.

getAiConnection

function getAiConnection(name: string): Promise<AiConnection>

Resolves a binding to an endpoint for another client library. On a cloud binding it waits for the gateway to start, so the URL is live when the promise resolves.

import { createOpenAICompatible } from "@ai-sdk/openai-compatible"
import { getAiConnection } from "@alienplatform/sdk"

const connection = await getAiConnection("llm")
const model = createOpenAICompatible({
  name: "alien",
  ...connection,
  apiKey: connection.apiKey ?? "",
})("gpt-oss-120b")

Pass apiKey: "" on a cloud binding instead of leaving it unset. Most clients fall back to a provider key in the environment when the field is missing.

Types

interface AiConnection {
  baseURL: string   // ends in /v1
  apiKey?: string   // external bindings only; undefined on the clouds
}

interface AiModel {
  id: string          // pass as `model`
  provider: string    // "openai", "anthropic", "google", "mistral", …
  displayName: string // label for a model picker
}

interface ChatCompletionCreateParams {
  model: string
  messages: Array<{ role: string; content: string | object }>
  stream?: boolean
  [key: string]: unknown
}

interface ResponseCreateParams {
  model: string
  input: string | Array<{ role: string; content: string }>
  stream?: boolean
  [key: string]: unknown
}

ChatCompletion, ChatCompletionChunk, Response, and ResponseStreamEvent come from the openai package, an optional peer dependency. Install it for the types. It isn't needed at runtime.

Python

from alienplatform import ai

conn = await ai("llm").connection()

connection() returns an AiConnection:

FieldTypeNotes
base_urlstrThe gateway or provider root, without /v1.
openai_base_urlstrbase_url with /v1 appended, for OpenAI-compatible clients.
api_keystr | NoneExternal bindings only. None on the clouds.
providerstr | NoneExternal bindings only.

On a cloud binding, the gateway runs inside your Python process for as long as the connection object is alive. The repr of a connection redacts the key.

Endpoints

The gateway serves these paths under the connection's base URL. getAiConnection() returns a baseURL that already ends in /v1.

PathMethodProtocol
/chat/completionsPOSTOpenAI Chat Completions
/messagesPOSTAnthropic Messages
/responsesPOSTOpenAI Responses
/modelsGETThe model list, as { object: "list", data: [...] }

Every inference path accepts every model. The model field in the body picks the model, and the gateway translates when the path isn't the model's native protocol.

const { baseURL } = await getAiConnection("llm")

await fetch(`${baseURL}/chat/completions`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    model: "gpt-oss-120b",
    messages: [{ role: "user", content: "hi" }],
  }),
})

On a cloud binding, send no credentials. The gateway listens only on the loopback interface inside your workload and signs every provider request with the workload's identity.

On an external binding the base URL is the provider's own (https://api.openai.com/v1 or https://api.anthropic.com/v1), and you send the key as a bearer token.

Don't hardcode the gateway port. It's assigned when the gateway starts. When ALIEN_AI_GATEWAY_URL is set, append /<name>/v1, where <name> is the resource id lowercased with underscores replaced by hyphens.

Errors

SDK errors

CodeMeaningRetryable
AI_UPSTREAM_ERRORThe gateway or provider returned a non-2xx status, which the error carries.On 429, 502, 503, 504
AI_TRANSPORT_ERRORThe request didn't complete, or the body wasn't valid JSON.Yes
AI_RESPONSES_API_UNSUPPORTEDresponses.create on an external anthropic binding.No
AI_UNSUPPORTED_PROVIDERAn external binding names a provider other than openai or anthropic, and ALIEN_AI_LOCAL_BASE_URL isn't set.No
AI_GATEWAY_START_FAILEDThe gateway process didn't report ready.Yes
AI_GATEWAY_UNSUPPORTED_PLATFORMNo prebuilt gateway binary for this OS and architecture.No
AI_GATEWAY_BINARY_UNAVAILABLEThe gateway binary couldn't be found or extracted.No
BINDING_NOT_FOUNDALIEN_<NAME>_BINDING isn't set. The resource isn't linked to this workload.No
INVALID_BINDING_CONFIGThe binding JSON is malformed.No

Match on error.code. AiUpstreamError and AiTransportError are exported from @alienplatform/sdk.

Gateway responses

When the provider rejects a request, the gateway returns a stable JSON error instead of the provider's body:

{
  "type": "error",
  "error": { "type": "provider_rate_limited", "code": "provider_rate_limited", "message": "The customer model provider rate limit was reached" },
  "retryable": true
}
Provider statusGateway statuscodeRetryable
401, 403, 404503provider_access_unavailableNo
429429provider_rate_limitedYes. Retry-After is passed through.
408, 504504provider_timeoutYes
Other 5xx502provider_unavailableYes
Other 4xxSame statusprovider_request_rejectedNo

Errors the gateway raises itself:

CodeStatusMeaning
GATEWAY_INVALID_REQUEST400The body isn't JSON, has no model, or uses a field the target protocol can't represent.
GATEWAY_REQUEST_TOO_LARGE413The body is over 32 MiB.
GATEWAY_MODEL_NOT_AVAILABLE404The model isn't in Alien's list for this cloud.
GATEWAY_UNKNOWN_BINDING404No AI resource with that name is linked.
GATEWAY_UPSTREAM_FAILED502The request to the provider didn't complete. Retryable.
GATEWAY_AMBIENT_CREDENTIAL_UNAVAILABLEThe workload's cloud credential couldn't be obtained. Retryable.
GATEWAY_WORKLOAD_IDENTITY_INVALIDThe workload identity can't authorize this binding.
GATEWAY_BINDING_CONFIG_INVALID400The binding couldn't be parsed.

On this page