Skip to content
Night Owls.dev
Jump to a page

@nightowlsdev/engine-mastra

EngineNative

The default engine as a named package, a mastraEngine() factory + MastraEngine re-export; installing it changes imports, not behavior.

What it does

**Use this when:** almost never explicitly — this IS the default. Omit `engine` from `defineSwarm` and you get exactly this engine, byte-identical. Install it only when you want the engine choice to be *visible* in your config (an explicit `engine: mastraEngine()` in a template, or to pin the family name), not because it changes anything. **How.** `mastraEngine()` returns `(opts) => new SwarmEngine(opts)` — the same factory `defineSwarm` uses by default — so `defineSwarm({ engine: mastraEngine() })` and omitting `engine` are equivalent. `owl install engine-mastra` writes that line into the config template. **What you get.** Everything — this is the baseline every other engine is measured against: full delegation and workflows, the complete governance plane (fail-closed tool gate, cost caps, secrets, telemetry), tier-3 events, and durable resume with semantic recall. *Under the hood:* it re-exports `MastraEngine` (== `SwarmEngine`), the `Engine` / `EngineCapabilities` / `AssembledEngineOpts` types, and `MASTRA_ENGINE_CAPABILITIES` — the descriptor react's affordance-gating and the runner boot guards read. Today the loop still physically lives in `@nightowlsdev/core` (a v0 re-export facade; the loop + its Mastra-backed storage move here as one coordinated wave at core@1.0).

Install

pnpm add @nightowlsdev/engine-mastra

Key exports

  • mastraEngine
  • MastraEngine (re-export of SwarmEngine)
  • MASTRA_ENGINE_CAPABILITIES
  • types: Engine, EngineCapabilities, AssembledEngineOpts
  • nightOwlsPlugin

Usage

engine-mastra.ts
import { defineSwarm } from "@nightowlsdev/core";
import { mastraEngine, MASTRA_ENGINE_CAPABILITIES } from "@nightowlsdev/engine-mastra";

// Explicit and byte-identical to omitting `engine`, installing this package
// changes imports, not behavior; defineSwarm builds the same engine either way.
const swarm = defineSwarm({ agents, engine: mastraEngine() });

// Every engine exposes a capabilities descriptor, @nightowlsdev/react reads the
// live one via useEngineCapabilities() to gate affordances (e.g. hide Stop when
// cancellation isn't supported); this is the one this engine reports.
console.log(MASTRA_ENGINE_CAPABILITIES.kind); // "native"

What it provides

engine-mastra is the default engine given a named, CLI-installable package in the engine-* family. mastraEngine() returns the EXACT SwarmEngine defineSwarm already builds when you omit engine, so installing this package changes your imports, not your behavior. It is the only engine today that offers full multi-agent delegation (agents-as-tools, depth-4, nested attribution), strict/advisory workflows, and semantic-recall memory — alongside the full governance plane, tier-3 events (all 14 SwarmEvent types, including swarm.handoff), and durable cross-process resume.

When to use it

  • You build a multi-agent pack — crews, delegation, agents-as-tools — which no other engine supports in v1 (delegation is Mastra-only today).
  • You use defineWorkflow procedures (strict or advisory) or semantic-recall / working-memory / observational memory.
  • You want the maximum-capability default engine but as an explicit, named package your nightowls.config and the owl CLI can install and wire.

When not to

  • You expected installing this to change runtime behavior — it does not; omitting engine from defineSwarm is byte-identical.
  • You want the loop built on a different native stack (raw Vercel AI SDK, @openai/agents) — install engine-ai-sdk or engine-openai-agents instead.
  • You want the run loop to execute on a remote runtime (A2A endpoint, a Vercel Eve app) — use an adapter engine and accept reduced governance.

Alternatives

  • Omitting engine entirelyYou don't need a named engine in config or the CLI wiring — defineSwarm defaults to this same Mastra SwarmEngine already, so the package is pure ergonomics.
  • engine-ai-sdk / engine-openai-agentsYou want a from-scratch native loop on the raw AI SDK or the OpenAI Agents SDK and can live single-agent (no delegation/workflows/semantic recall) in v1.
  • An adapter engine (engine-a2a / engine-eve / engine-trigger-chat)The agent loop already runs on a remote runtime you don't execute inside of; you trade the governance plane for reach.

Strengths

  • The only full-capability engine today: delegation (maxDepth 4, nested attribution), workflows, semantic recall, tier-3 events, full governance, durable resume.
  • Zero capability cost through the engine wall — it IS the default, so you pay nothing to go through Night Owls' own types.
  • Exports MASTRA_ENGINE_CAPABILITIES, the machine-readable descriptor react's affordance gating and the runner boot guards read to know what the loop supports.

Limits & trade-offs

  • It is a v0 re-export FACADE — the swarm loop physically lives inside @nightowlsdev/core until core@1.0 (when the loop plus the Mastra half of storage move here in one coordinated wave).
  • Installing it buys nothing at runtime over omitting engine — only a named package + owl-install wiring.
  • MastraEngine is an identity alias of core's SwarmEngine, so it does not decouple you from the default engine; it just names it.

How it works

mastraEngine() returns (opts) => new SwarmEngine(opts) — the same construction defineSwarm performs internally when engine is omitted. defineSwarm hands the factory the fully-assembled AssembledEngineOpts (composed hooks, skill resolver, workflows, telemetry, secrets, onEvent). MastraEngine is a direct re-export of @nightowlsdev/core's SwarmEngine class, and MASTRA_ENGINE_CAPABILITIES is the same static EngineCapabilities the default engine reports: kind native, events tier 3, delegation { maxDepth: 4 }, workflows/rules true, memory with semanticRecall/workingMemory/observational all true, governance all-on.

Examples

Install and wire it explicitly (byte-identical to the default)

Passing mastraEngine() constructs the same SwarmEngine defineSwarm builds when engine is omitted.

engine-mastra-example-1.ts
import { defineSwarm } from "@nightowlsdev/core";
import { mastraEngine } from "@nightowlsdev/engine-mastra";

export default defineSwarm({
  agents,
  engine: mastraEngine(),
});

Read the capability descriptor

The descriptor is what react's useEngineCapabilities() and the runner boot guards gate on — mastra is the one engine that reports delegation + workflows today.

engine-mastra-example-2.ts
import { MASTRA_ENGINE_CAPABILITIES } from "@nightowlsdev/engine-mastra";

console.log(MASTRA_ENGINE_CAPABILITIES.kind); // "native"
console.log(MASTRA_ENGINE_CAPABILITIES.delegation); // { maxDepth: 4, attribution: "nested" }
console.log(MASTRA_ENGINE_CAPABILITIES.workflows); // true

Doing the parts it doesn't support

  • Running the loop in the background / durably across process deathThe engine runs in-process. Wrap it with @nightowlsdev/runner-background (Trigger v4 tasks + wait tokens) or runner-nextjs to enqueue runs and resume from a durable snapshot; pair with a cross-process StorageAdapter (storage-supabase) so durable resume actually survives a restart.
  • A different underlying stackSwap the factory: defineSwarm({ engine: aiSdkEngine() }) or openAiAgentsEngine() keeps your swarm description unchanged and only changes the loop — at the cost of delegation/workflows/semantic recall in v1.

Related

  • coreThe required base — the loop this package names still lives here in v0, and every primitive comes from core.
  • engine-ai-sdkThe sibling native engine on the raw AI SDK, for when you want a different stack and can live single-agent.
  • reactuseEngineCapabilities() reads MASTRA_ENGINE_CAPABILITIES to gate UI affordances (Stop, delegation lanes).
  • runner-backgroundRun this in-process loop durably in the background (Trigger v4 tasks + wait tokens).
  • capability-bundlesPackage a whole multi-agent crew — the workloads only this engine can run — for reuse.