Build your first Worker
In this example, we are going to build the smallest useful piece of an application that can run in a customer's cloud: a serverless service with one HTTP route and one private operation your product can invoke.
The code is deliberately simple. The point is to see the complete path: develop one service locally, deploy it to AWS, Google Cloud, Azure, or Kubernetes, and call it from your product without opening an admin port into the customer's network.
A Worker is Alien's stateless, event-driven compute resource. It runs as AWS Lambda on AWS, Google Cloud Run on GCP, Azure Container Apps on Azure, or a Deployment and Service on Kubernetes. The same Worker can receive HTTP requests, Commands, queue messages, storage events, and schedules.
We will write the Worker in TypeScript or Rust. During development it runs on your computer; after deployment, Alien creates the corresponding compute in your cloud or a customer's environment.
Your product sends an HTTP request or invokes a Command. A Worker running in the customer environment executes your TypeScript or Rust and returns the result.
We will start with alien.ts, the file that describes what Alien should build and run. Then we will write the HTTP and Command handlers in an ordinary application file and call both locally.
Describe the application in alien.ts
const agent = new alien.Worker("agent")
.code({ type: "source", src: "./", toolchain: { type: "typescript" } })
.commandsEnabled(true)
.publicEndpoint("api")
.permissions("execution")
.build()publicEndpoint("api") creates an HTTP endpoint. commandsEnabled(true) lets the Worker register Command handlers.
The endpoint and the Command solve different problems. /health intentionally accepts inbound HTTPS. echo remains reachable through the Commands API even if you remove the public endpoint entirely. The execution permission profile is also explicit: Alien turns that profile into the cloud permissions assigned to this Worker.
Write the application code
const app = new Hono()
app.get("/health", c => c.json({ status: "ok" }))
command("echo", async params => params)
export default appRun it locally
alien init basic-worker-ts
cd basic-worker-ts
alien devIn another terminal:
alien dev commands invoke \
--deployment default \
--command echo \
--params '{"hello":"world"}'Then open the URL printed by alien dev and request /health.
Deploy it for a customer
Local development proves that the handlers work. A release makes the same Worker available for customer deployments:
alien releasePublishes a version. Nothing is deployed for a customer yet.
alien onboard acme-corpCreates a deployment link for that customer.
The customer opens the link and deploys into their environment.
After setup, the Worker runs as Lambda, Cloud Run, Container Apps, or Kubernetes compute in the customer's environment.
Call it from your control plane
The CLI is useful while testing a deployment:
alien commands invoke \
--deployment acme-corp \
--command echo \
--params '{"hello":"from the control plane"}'Your product can call the same API with the TypeScript client:
import { CommandsClient } from "@alienplatform/commands"
const commands = await CommandsClient.forDeployment({
deploymentId: customer.deploymentId,
apiKey: process.env.ALIEN_API_KEY!,
})
const result = await commands
.target("agent")
.invoke("echo", { hello: "from the control plane" })The request starts in your control plane, but the handler executes inside the customer's environment. For a real integration, replace echo with a narrow operation such as search-documents or generate-report. That lets sensitive data stay near the customer's database or storage and returns only the result your product needs. It can also avoid moving large inputs back to your cloud before the work begins.
What you built
You built the smallest complete control-plane-to-customer-cloud loop: release code once, let a customer deploy it, and invoke a named operation from your product. The echo handler is deliberately simple; the useful pattern is where it executes and how little access your control plane needs.
Complete source: basic-worker-ts and basic-worker-rs.