Documentation menu
Documentation

How agents work

An agent instance is a durable, addressable micro-server with its own state, storage, connections, and work.

Start from a fresh project

This guide is self-contained. Create an empty Ayjnt project, then replace the starter agent with the files shown below. Run commands from the new project directory unless a step says otherwise.

terminal
bunx ayjnt new try-agents --empty
cd try-agents
bun install

# remove agents/alive once you are ready to add the guide's files

Class, route, instance

A folder such as agents/support/agent.ts defines an agent class and the route /support/:name. The class describes behavior; the final path segment selects one durable instance.

The same name always resolves to the same instance. That is the unit to model around: one user, game, coding session, project, or coordination boundary.

PartExampleMeaning
ClassSupportAgentShared behavior and lifecycle
Route/supportHuman-facing address
Instancecustomer-42Durable identity and isolated SQLite

Lifecycle

onStart() runs when an instance starts or wakes. HTTP reaches onRequest(). Realtime connections use onConnect(), onMessage(), onClose(), and onError(). State changes notify onStateChanged().

Instances can hibernate between events. Persist anything important in state or SQLite; do not treat in-memory fields as durable.

agents/support/agent.ts
import { Agent } from "ayjnt";

type State = { status: "idle" | "working"; task?: string };

export default class SupportAgent extends Agent<State> {
  initialState: State = { status: "idle" };

  async onStart() {
    console.log("ready", this.name);
  }

  async onRequest() {
    return Response.json(this.state);
  }
}

Run it and verify the result

Open http://localhost:8787/support/demo. Refreshing or reconnecting to the same name reaches the same durable instance.

terminal
bun run build
bun run dev

# the local app is now available at http://localhost:8787