Aex Brain
Customize and operate

Write an agent harness

Supply an implementation when starting Brain and use its journaled services.

A harness gives Brain an agent implementation. Start with an upstream adapter when you want its loop and compaction behavior; implement this interface when your application needs different behavior.

This complete JavaScript example makes one model call per user message. Save it as harness.mjs beside an installed @aexhq/brain@0.41.0:

import { serveHarness } from "@aexhq/brain/harness";

await serveHarness({
  name: "single-call",
  stateVersion: "1",
  open() {
    return {
      async run(ctx) {
        if (!ctx.input) return;
        const messages = [...ctx.transcript, {
          role: "user",
          content: [{ type: "text", text: ctx.input.message }],
        }];
        const reply = await ctx.model({ messages, tools: [] });
        await ctx.setTranscript([...messages, reply.message]);
      },
      close() {},
    };
  },
});

TypeScript uses the same API and can annotate the implementation with AgentHarness. Other languages implement the stdio protocol. The repository includes a Python protocol fixture and a runnable JavaScript example.

Register it and create a session

export BRAIN_AGENTLOOPS='{"custom":{"command":"node","args":["/absolute/path/harness.mjs"]}}'
brain --data-dir ./brain-data --api-token local-development

Select that registration in the client:

const session = await brain.sessions.create({
  model, agentloop: { name: "custom", configuration: {} },
});

In PowerShell, assign the same JSON string to $env:BRAIN_AGENTLOOPS. The command is an executable with an argument array; Brain does not evaluate a shell command. Write diagnostics to stderr and reserve stdout for protocol frames.

A process serves multiple sessions. open receives a session id, an isolated native state directory, and deployment configuration. Its session object runs at most one activation at a time. ctx.configuration contains session options. close releases resources while retaining state; deletion removes the state directory.

Use Brain's services

Await ctx.model and ctx.callTool or ctx.callTools for external effects. Brain commits intent before dispatch and the terminal outcome before returning. A Tool invocation names its canonical tool and admitted environment; use the current environment_sequence for a replacement instance.

ctx.kv stores small journaled values. ctx.setTranscript publishes the conversation view, and ctx.emit publishes custom events. ctx.events contains pending runtime observations; background activations have no ctx.input. Environment control is available through ctx.environments under the session's harness grants.

Treat a fatal callback error or an aborted signal as the end of the activation. Brain rejects further effects and will not resume an unsuccessful native activation. Reserve keys beginning with brain.harness. for the runtime.

When wrapping an upstream agent, keep its session persistence and compaction upstream. Replace its provider and tool execution at awaited boundaries, disable network retries, and exclude built-in tools. An observer hook that runs after an effect cannot enforce Brain's journal ordering.

On this page