Aviary
Packages

@dudousxd/nestjs-agent-store-mikro-orm

MikroORM AgentStore adapter — threads, messages, tool calls, usage, and run reliability — with safe auto-schema.

The AgentStore SPI (from @dudousxd/nestjs-agent-core) backed by MikroORM. The store is a POJO that receives an EntityManager; every operation runs on a fresh em.fork() so per-request identity maps never bleed across concurrent turns.

pnpm add @dudousxd/nestjs-agent-store-mikro-orm @mikro-orm/core @mikro-orm/nestjs
npm install @dudousxd/nestjs-agent-store-mikro-orm @mikro-orm/core @mikro-orm/nestjs

Minimal example

import { MikroOrmModule } from '@mikro-orm/nestjs';
import { MikroOrmAgentStoreModule } from '@dudousxd/nestjs-agent-store-mikro-orm';
import { AgentModule } from '@dudousxd/nestjs-agent';

@Module({
  imports: [
    MikroOrmModule.forRoot(/* your config */),
    MikroOrmAgentStoreModule.forFeature(), // registers entities + binds AGENT_STORE (+ queries)
    AgentModule.forRoot({
      model: myModelProvider,
      // no `store` — the agent reads it from AGENT_STORE
      defaultRoles: ['ADMIN'],
      actorResolver: new HeaderActorResolver(),
    }),
  ],
})
export class AppModule {}

Create the tables with your normal MikroORM migrations, or call the exported ensureAgentSchema helper at boot for a quick start:

import { ensureAgentSchema } from '@dudousxd/nestjs-agent-store-mikro-orm';

await ensureAgentSchema(orm); // orm.schema.update({ safe: true }) — create + add-column only

MikroOrmAgentStoreModule.forFeature() is global

It binds AGENT_STORE, AGENT_GOVERNANCE_QUERIES, and AGENT_PRICING_STORE on a global Nest module. Import it once — AgentModule.forRoot({...}) (and the dashboard/telescope surfaces) resolve both tokens app-wide with no re-binding. Do not import it more than once expecting scoped behavior.

Exports

ExportKindPurpose
MikroOrmAgentStoreModuleDynamicModule factory.forFeature() registers the six entities and binds AGENT_STORE + AGENT_GOVERNANCE_QUERIES + AGENT_PRICING_STORE globally
MikroOrmAgentStoreclassAgentStore implementation — the write side (threads, messages, tool calls, usage), including the optional recordRunStart/recordRunEnd/bumpRunRetries run-reliability hooks the loop and durable runners call
MikroOrmGovernanceQueriesclassAgentGovernanceQueries implementation — the full read-model: spend by model/actor/thread, usage trend, recent activity, run reliability (runMetrics/runsByAgent/runErrors/runTrend/recentRuns), the approvals inbox (pendingApprovals), per-tool stats (toolStats), and paged/filterable reads (toolCallsPage/threadsPage/runsPage)
MikroOrmPricingStoreclassAgentPricingStore implementation — upsertModelPrice / listCurrentPrices, the write side of model pricing (see Cost & Governance)
ensureAgentSchema(orm, opts?)functionNon-destructive schema.update({ safe: true }) — create + add-column, never drop or alter
agentManagedTables()function → string[]The six agent table names, for a host's own MikroORM schema-diff skipTables — mirrors durableManagedTables()/telescopeManagedTables()
AGENT_ENTITIESEntitySchema[]The six agent entity schemas, pre-stamped with utf8mb4_unicode_ci for MySQL parity
agentEntities({ collation? })functionBuilds the entity schemas with a custom (or no) collation, e.g. for SQLite
AGENT_COLLATION'utf8mb4_unicode_ci'The default collation baked into AGENT_ENTITIES
entity classes (AgentThread, AgentMessage, AgentToolCall, AgentTokenUsage, AgentModelPricing, AgentRun)EntitySchema-backed classesThe six tables — agent_thread, agent_message, agent_tool_call, agent_token_usage, agent_model_pricing, agent_run

agent_run — the reliability + approvals table

Every turn is recorded as a run in agent_run (status, duration, error code/message, retry count, a promptHash for correlating error-rate shifts with prompt changes). MikroOrmGovernanceQueries reads it for the dashboard's Reliability section and for pendingApprovals/toolStats — created and healed by ensureAgentSchema like the other five tables, no separate wiring needed.

Peer dependencies

@mikro-orm/core (^6 \|\| ^7), @mikro-orm/nestjs (^6 \|\| ^7), and @nestjs/common (^10 \|\| ^11) — plus your driver package (@mikro-orm/postgresql, @mikro-orm/mysql, …).

When to use it

Reach for this adapter when MikroORM is already your app's ORM — MikroOrmModule.forRoot(...) owns the connection, and forFeature() just registers the agent's six entities alongside your own. If you'd rather bring an already-opened handle and skip MikroORM entirely, see store-drizzle.

  • Persistence — the AgentStore SPI, the two bound tokens, and choosing an adapter
  • Cost & Governance — the read-model this adapter feeds, and the ledger cost formula

On this page