Run your first agent on Aex
Aex hosts the agent session; your app brings a model key and tools. In a few steps you'll ask an agent whether an order has shipped and print its answer.
1. Get your keys
You need Node.js 22 or newer and an OpenAI API key. Sign in to the dashboard and create an Aex API key. Copy it right away: the secret is only shown once.
export AEX_API_KEY="your-aex-key"
export OPENAI_API_KEY="your-openai-key"In PowerShell, use $env:AEX_API_KEY = "your-aex-key" and $env:OPENAI_API_KEY = "your-openai-key". Keep keys on your server and out of source control. Your model provider bills its calls separately.
2. Install
mkdir aex-example
cd aex-example
npm init -y
npm install @aexhq/sdk@0.89.0 @aexhq/agentloop-pi@11.0.0 zod@4.4.33. Add a tool and run the agent
Save this as order.mjs. The same API works in TypeScript.
import { Aex, tool } from "@aexhq/sdk";
import { pi } from "@aexhq/agentloop-pi";
import { z } from "zod";
const lookupOrder = tool({
name: "lookup_order",
description: "Look up an order by id.",
input: z.object({ id: z.string() }),
run: ({ id }, ctx) => ctx.finish({ id, status: "shipped" }),
});
const aex = new Aex({ apiKey: process.env.AEX_API_KEY });
aex.sessions.create({
model: { provider: "openai", name: "gpt-4.1-mini", apiKey: process.env.OPENAI_API_KEY },
agentloop: pi(),
tools: [lookupOrder()],
}).then(async session => {
const after = session.state.lastSequence;
await session.send("Look up order A-1001. Has it shipped?");
for await (const event of session.events(after)) {
if (event.type === "turn_failed") throw new Error(JSON.stringify(event.data));
}
console.log(JSON.stringify(await session.transcript(), null, 2));
console.log("Session:", session.id);
}).catch(error => {
console.error(error);
process.exitCode = 1;
});node order.mjsYou'll see the lookup result in the transcript, followed by an answer that order A-1001 has shipped. Now swap the sample lookup for your own data, or add more session.send(...) calls in the callback to keep the conversation going.
The loop ran on Aex and the lookup ran in your app. After five idle seconds the client released its tool connection so the script could exit; the session and its history are still there. A later send through the same live client reconnects automatically.
If other callers or future autonomous events need these tools, pass connectionIdleTimeoutMs: 0 to new Aex(...). Event subscriptions stay open until you stop them. aex.close() disposes of the client, session.end() finishes the conversation and session.delete()removes its history.
Keep building
- Sessions: follow live output, reconnect and stop work.
- Tools: connect your API or database.
- Agent loops: choose how the agent works.
- Environment control: choose automatic setup and optional model diagnostics.
- Structured output: get a validated JSON answer.
- Images and PDFs: upload with a scoped grant and verify completion. Model file support varies.
- Application tools: run tools in your deployed server or serverless backend.
- Client browser tools: work in the user's connected tab with scoped access.
- Managed tools: use a sandbox profile granted to your account.
Aex is built on Brain's session and extension APIs, so the Brain guides apply here too. Import their shared helpers from @aexhq/sdk.
Use session.submit() when your request has to return before the work finishes. Save the turn sequence it returns and call session.outcome(sequence) from a later request. Declare your backend with aex.environments.application() and place ordinary tools there. Aex admits the endpoint when you call sessions.create(), and saved conversations can call it again on later turns. Your app hosts its business functions and checks current user access. Inline hostEnv tools need their process connected.
Choose an agent loop
Aex runs Pi, Codex and OpenCode on the server. Import a factory from its extension package and pass it to session creation:
import { pi } from "@aexhq/agentloop-pi";
const session = await aex.sessions.create({ model, agentloop: pi({ maxTokens: 4096 }), tools });Use Pi 11.0.0, Codex 11.0.0 or OpenCode 1.0.0 with Aex SDK 0.89.0. Each factory selects an installed runtime and passes its session settings. Executables and worker capacity are configured when the server starts.
Hosted Tools still support aex.prepare(tool) to load code before requests arrive. Read the Environment preparation reference for Tool runtimes and custom programs.
Structured output
Use a typed answer when your application needs data it can validate and use directly. Inside the callback, pass a Zod schema with the message:
const answer = await session.send("Return the order status", {
output: { type: z.object({ id: z.string(), status: z.string() }), maxRetries: 2 },
});
console.log(answer.status);Aex adds schema instructions to the prompt, parses the completed turn's assistant answer as JSON and validates it locally. The return type follows the schema. Ordinary sends return session state. Pi and Codex emit the assistant output this needs.
maxRetries counts additional correction turns and defaults to two. Zero checks one answer. Invalid JSON or schema issues trigger a request for a complete corrected answer; Markdown fences and surrounding prose fail parsing. Zod defaults, transforms and async refinements apply to the returned value. Exhaustion throws StructuredOutputError with attempts, lastOutput and issues. Provider and transport failures do not trigger corrections.
Keep the calling process alive and coordinate exclusive sends during the operation. Each attempt is a separate durable turn, can call tools and remains visible in history and streams. Local validation does not change a completed server turn. A top-level signal cancels active work and stops further corrections. An idempotencyKey lets unchanged requests and validation feedback reuse their completed turns; the whole operation is not atomic.
A short-lived caller can use submit(), read the completed transcript later and validate it in application code. Typed answers require the caller to stay connected through send(). See the SDK guidefor error handling, replay and a complete example.
Starting with Brain SDK 0.34 and Aex SDK 0.84, this prompt and correction policy belongs to Aex. Existing Aex typed sends keep their syntax. Import their types and errors from @aexhq/sdk. Aex clients and handles now use composition; use AexSessionHandle for explicit handle types. The migration guidealso shows how to wrap an existing standalone Brain handle.
Use the CLI
npm install -g @aexhq/cli@0.51.0
aex login
aex keys create "My application"
aex usageLogin opens your browser on the same computer. The command guidecovers keys, account management and billing.
Hosting prices and limits
Model hosting is offered at $0.22 per million input + output tokens. Managed compute, attachment storage and downloads have separate prices. You supply your model key and pay that provider separately.
The dashboard shows your exact offered and accepted prices. Existing preview accounts stay in preview until they accept a pricebook. Prepaid services require accepted prices and credits. Set a monthly spending limit; there are no automatic topups.
Spending controls can interrupt work but do not cap your separate model-provider bill. Read the billing guidefor charges, estimates and refunds.
Aex is in early preview, and APIs and limits may change. Maintenance can interrupt work; saved history stays available, and uncertain actions are never retried automatically.