Overview
Call frontier models through the customer's own cloud, with no API keys in your app.
alien.AI is managed model inference. Declare it in your alien.ts and Alien wires your workload to the AI service already in the customer's cloud — Bedrock, Vertex AI, or Azure AI Foundry — so calls are billed to that cloud account and authorized by the workload's own identity. There is no API key in your application.
Platform Mapping
| Platform | Backing Service | Provisioned by |
|---|---|---|
| AWS | Amazon Bedrock | Nothing to provision |
| GCP | Vertex AI | Alien (enables the API) |
| Azure | Azure AI Foundry | Alien (creates the account and deployments) |
| Kubernetes / On-Prem | External (your provider key) | You, via an external binding |
| Local | External (your provider key) | You, via OPENAI_API_KEY |
On AWS nothing is created at all — Bedrock is an account-level API, so deploying the resource just grants your workload access. On GCP, Alien enables the Vertex AI API and grants the role. On Azure it goes further and creates an AI Foundry account with model deployments (see Behavior).
When to Use
Use AI when your product calls language models and you deploy into your customers' clouds. Each customer's inference runs on their account, under their quotas and data-handling terms, and you ship no keys.
The tradeoff is that the model menu is the customer's, not yours: what you can call depends on which cloud they run and what they've enabled there. If your product needs one specific model everywhere, or a provider none of the three clouds host, bring your own key with an external binding instead.
Stack Definition
const assistant = new alien.AI("assistant").build()| Parameter | Type | Default | Description |
|---|---|---|---|
id | string | — | Resource identifier: letters, digits, hyphens and underscores ([A-Za-z0-9-_]), up to 64 characters. Immutable after create. |
There is nothing else to configure. The model is chosen per request in your code, not in the stack, so a stack file does not pin you to a model or a provider.
Link it to a workload and grant ai/invoke:
const api = new alien.Worker("api")
.code({ type: "source", src: "./api", toolchain: { type: "typescript" } })
.link(assistant)
.permissions("execution")
.build()
export default new alien.Stack("assistant-app")
.platforms(["aws", "gcp", "azure"])
.add(assistant, "live")
.add(api, "live")
.permissions({
profiles: {
execution: { "*": ["ai/invoke"] },
},
})
.build()ai/invoke grants inference and nothing else — no model management, no deployment writes. See Permissions.
Calling a Model
import { ai } from "@alienplatform/sdk"
const llm = ai("assistant")
// Model ids differ per cloud, so take one the deployment actually has.
const [model] = await llm.getAvailableModels()
const completion = await llm.chat.completions.create({
model: model.id,
messages: [{ role: "user", content: "Summarize this support thread." }],
})Claude is the exception. It speaks Anthropic's API rather than OpenAI's, so it needs an Anthropic client — getAiConnection() gives you the endpoint to point it at, and there is still no key:
import { createAnthropic } from "@ai-sdk/anthropic"
import { getAiConnection } from "@alienplatform/sdk"
const connection = await getAiConnection("assistant")
const anthropic = createAnthropic({ baseURL: connection.baseURL, apiKey: "" })
const model = anthropic("claude-sonnet-4.6")Alien forwards your request to each model in that model's own format instead of translating between them, which is why the client has to match the model. See Behavior.
getAiConnection() works with any OpenAI- or Anthropic-compatible client, so the Vercel AI SDK, the OpenAI SDK, and the Anthropic SDK all attach the same way.
Discovering Models
Model availability differs per cloud and per account, so ask at runtime rather than hardcoding an id:
const models = await ai("assistant").getAvailableModels()
// [{ id: "gpt-oss-20b", provider: "openai", displayName: "GPT-OSS 20B" }, …]This returns only what the deployment can actually invoke right now — a model the account has not enabled does not appear. It is what you want behind a model picker.
Local Development
There is no cloud identity on your machine, so locally the resource becomes a bring-your-own-key binding and the SDK calls the provider directly:
OPENAI_API_KEY=sk-... alien devalien dev fails with an actionable error if the key is missing. The cloud model ids do not resolve locally, and getAvailableModels() returns a short built-in list for the provider rather than querying it, so pass whatever model id your key can reach.
See the API Reference for the full SDK surface, and Behavior for limits and per-platform detail.