AGENTO
v1.1.0 · Documentation
Documentation/Integrate the runtime/Sessions & custom stores

Sessions & custom stores

2026-10-15·source 4bebed4·3 min read·19 / 27

You will learn: Keep pending state consistent across requests and workers.

See why a session is more than chat history

The booking fixture returns a selection in one call and receives the user's choice in another. The runtime must remember the original API items, expiry, dependency frame, and later the exact prepared request. Reusing the same sessionId connects those calls.

Creating a new runtime for every message with its own memory store loses that state. Two independent workers with separate memory stores also cannot reliably continue each other's choices. Use one long-lived instance for a single-process app; for multiple workers, provide shared stores with the transaction contract below.

Choose the storage behavior before scaling

A shared key/value record is not enough. Two simultaneous confirmations must not both read the same approval before either consumes it. transact() must serialize the entire asynchronous operation for one session, including awaited network work. A lock lease must not silently expire while that work is still active.

Session state and retained credentials are separate stores. Sharing SessionStore alone does not make a token retained by worker A available to worker B. Either pass the authorized token on each continuation or supply the shared encrypted token-store configuration described in authentication.

Test this with two runtime instances, one shared store, and concurrent confirmation calls. Assert one write. Also test expiry, config change, and a worker interruption. A storage outage is an operational failure, not permission to replay a business effect.

What lives in a session

SessionStateV2 stores:

  • state — explicit runtime state;
  • history — bounded user/assistant messages;
  • facts — sourced values with optional TTL;
  • stack — dependency execution frames;
  • pending selection;
  • pending confirmation;
  • sanitized host context;
  • references published from selected API items;
  • configHash;
  • expiry and lifetime message count.

Transaction contract

The critical SessionStore method is not get() or set(). It is:

transact<T>(id: string, operation: () => Promise<T>): Promise<T>

The contract requires serialization of the entire async operation for one session across all runtime instances sharing that store.

A naive Redis implementation that does:

GET session
...
SET session

without a renewable distributed lock/fencing mechanism is not sufficient for multi-instance correctness.

Memory store

import { MemorySessionStore } from "agento-runtime";

Good for:

  • local development;
  • tests;
  • one-process deployments where runtime instances share the same store object.

Not enough for horizontal multi-process deployments.

Custom store interface

interface SessionStore {
  get(id: string): Promise<SessionStateV2 | null>;
  set(id: string, state: SessionStateV2): Promise<void>;
  delete(id: string): Promise<void>;
  touch(id: string, expiresAt: number): Promise<void>;
  transact<T>(id: string, operation: () => Promise<T>): Promise<T>;
}

Expiry and config changes

A session becomes invalid if its TTL expires or its stored configHash no longer matches the compiled runtime configuration. AGENTO clears incompatible state instead of trying to continue an operation under different rules.

Interrupted execution marker

If a stored session is found in EXECUTING, AGENTO treats the previous effectful operation as uncertain rather than automatically replaying it. Reconcile first.

Host context

Pass trusted request/session metadata:

context: {
  tenant: { id: "tenant_42" },
  locale: "ar-PS"
}

Then map explicitly:

X-Tenant-Id:
  source: session
  path: $.tenant.id

Do not put access tokens in ordinary context; use auth.token.