Aex Brain
Build an application

Build with sessions

Send messages, stream progress, retrieve results and reconnect your tools.

A session is one conversation and the work the agent does for it. It keeps the model, loop and tools you selected, along with messages and progress. Save its ID to open it later.

Complete the quickstart first. These TypeScript/JavaScript excerpts use its brain and session inside the .then() callback. Keep the client alive to send more messages.

Send messages and read the answer

await session.send("Where is order A-1001?");
const { messages } = await session.transcript();
console.log(messages);

Each message starts a turn: the loop can call the model and tools before finishing. send() waits for that turn and returns session state, not the answer. Read the transcript for messages. An idle session can have a failed turn; inspect turn_failed events as in the quickstart, or use outcome(sequence) for a submitted turn. Request errors reject the promise; catch them at your application boundary. Close the client when your application is finished with it.

Stream progress

Start reading before sending. This pattern prints events until the turn ends or fails and closes the subscription even if the request fails:

const subscription = new AbortController();
let cursor = session.state.lastSequence;
const watching = (async () => {
  for await (const event of session.stream(cursor, subscription.signal)) {
    console.log(event.type, event.data);
    if (event.sequence !== undefined) cursor = event.sequence;
    if (event.type === "turn_failed") throw new Error(JSON.stringify(event.data));
    if (event.type === "turn_ended") return;
  }
  throw new Error("Stream closed before the turn finished");
})();
try {
  await Promise.all([watching, session.send("Explain event streaming in one sentence.")]);
} finally {
  subscription.abort();
  await watching.catch(() => {});
}

The complete streaming example uses the quickstart's server, packages and model key. Run it with node streaming-session.mjs. Aborting a subscription stops listening; it does not cancel the agent's work. To stop the turn, call session.interrupt(). A send() signal requests cancellation of an exclusively owned turn; do not send concurrently through another owner of that session.

Reconnect from a cursor

Save the last processed event's sequence. Open await brain.sessions.get(sessionId), then call session.events(cursor) to read saved events and finish, or session.stream(cursor) to catch up and continue listening. Neither method automatically reconnects after a broken stream; your app opens the next subscription using its saved cursor.

Model deltas are live-only and have no sequence. Reconnection recovers saved events and the completed model response, not missed token deltas. See history for delivery and deduplication behavior.

Submit work and retrieve its outcome

const sequence = await session.submit("Summarize the conversation.", {
  idempotencyKey: "summary-1",
});
console.log({ sessionId: session.id, sequence });

submit() returns once Brain has saved the request. Persist the session ID and sequence. If you lose that response, repeat the same request with the same key; do not reuse the key for new work. Server-side work can continue after the client closes. Application tools still need their host process; use HTTP or remote tools for independent execution.

Later, open the saved session with a new client:

const session = await brain.sessions.get(sessionId);
const outcome = await session.outcome(sequence);
if (outcome.status === "failed") {
  throw new Error(JSON.stringify(outcome.terminal.data));
}
if (outcome.status === "ended") {
  console.log(outcome.answer ?? await session.transcript());
}

pending means check again later. ended means the loop finished; individual tool calls or background jobs may still have failed or be running. answer is present only if the loop emitted an assistant answer event. The complete submission example closes the submitter, polls from another client, checks failure and keeps the transcript.

Let an idle client disconnect

The SDK releases its shared tool connection after five seconds without active turns, unfinished tools or their follow-up work. Session handles, callbacks and history remain available. A later send(), submit() or Environment operation through the same live client reconnects before starting work. Reading history does not open the tool connection.

Configure the timeout when creating the client:

const brain = new Brain({
  baseUrl: "http://127.0.0.1:8080", token: "quickstart",
  connectionIdleTimeoutMs: 5_000,
});

Use connectionIdleTimeoutMs: 0 when other callers or future autonomous events must be able to invoke this client's tools. A disconnected browser cannot be woken by another caller. Closing the tab or process loses its callbacks; restore them as described below. The timeout does not end sessions or dispose of Environments. Event subscriptions remain open until you stop iteration or abort their signal. Explicit brain.close() disposes of the client permanently and later operations reject.

Reattach application tools

An open session handle alone does not restore your application's functions. Before stopping the original application, save await brain.credentials() in your credential store together with the session ID, then close that client. These are host credentials, separate from the Brain API token and model key; protect them as secrets.

After restarting, restore the same tool definitions and pass the saved credentials:

const brain = new Brain({
  baseUrl: "http://127.0.0.1:8080", token: "quickstart", credentials: savedCredentials,
});
try {
  const session = await brain.sessions.get(sessionId, { tools: [lookupOrder()] });
  await session.send("Look up order A-1002.");
  console.log(await session.transcript());
} finally {
  await brain.close();
}

Here savedCredentials and sessionId come from your storage; lookupOrder is the quickstart's function. Supply exactly the tools originally placed in that host, with identical schemas and environment names. Changed contracts require a new session. Reattachment accepts future calls; it does not replay interrupted calls or restore state captured in the old process.

Stop, finish or delete

CallEffect
session.interrupt()Stop the current turn and unfinished tools; allow later messages
session.end()Finish the conversation and keep its history
session.delete()Delete an ended or failed session and release its environments
brain.close()Close this client's connections; keep stored sessions

Cancellation does not undo completed external actions. A server restart with storage intact preserves saved history but fails interrupted work without automatic retry. See history and recovery for the exact guarantees.

On this page