@nightowlsdev/engine-openai-agents
EngineNativeThe third native engine, a governed @openai/agents run() loop with full governance (fail-closed tool gate, cost caps, secrets), native handoffs/guardrails. Single-agent v1 (multi-agent handoffs planned v1.1).
What it does
**Use this when:** you want the OpenAI Agents SDK's `run()` loop (`@openai/agents`) as your engine, fully governed in your own process — and one agent per swarm is enough for now. **How.** `openAiAgentsEngine()` into `defineSwarm({ engine })` (or `owl install engine-openai-agents`). `openAiAgentsEngine({ durable: true })` turns on durable park/resume when your storage persists the SDK's `RunState` snapshot across processes. Requires Node ≥ 22; peers `ai@^7` (provide it yourself) and bundles the `@openai/agents` family (pinned `0.12.0`) as direct dependencies. **What you get / what it can't do yet.** The full governance plane, same as its native siblings: fail-closed tool gate, cost caps, secrets, and telemetry (OTel spans). Tool approvals map onto the SDK's native approve/reject interruption; cancellation is mid-stream. The `preGeneration` veto isn't a leap of faith — a spike verified the SDK's `callModelInputFilter` fires exactly once per model launch and a thrown error aborts cleanly. The one real limit is that **v1 is single-agent** (`delegation`/`workflows` are `false`); the SDK's native handoffs become Night Owls delegation in v1.1.
Install
pnpm add @nightowlsdev/engine-openai-agentsKey exports
- openAiAgentsEngine
- OpenAiAgentsEngine
- OPENAI_AGENTS_ENGINE_CAPABILITIES
- nightOwlsPlugin
Usage
import { defineSwarm } from "@nightowlsdev/core";
import { openAiAgentsEngine, OPENAI_AGENTS_ENGINE_CAPABILITIES } from "@nightowlsdev/engine-openai-agents";
// The third native engine, a governed @openai/agents run() loop. Single-agent v1: no
// delegation/workflows yet (native handoffs become multi-agent delegation in v1.1).
const swarm = defineSwarm({ agents, engine: openAiAgentsEngine() });
// Same full-governance posture as engine-mastra/engine-ai-sdk, verified, not assumed.
console.log(OPENAI_AGENTS_ENGINE_CAPABILITIES.governance.preGeneration); // true
console.log(OPENAI_AGENTS_ENGINE_CAPABILITIES.kind); // "native"What it provides
engine-openai-agents is the third NATIVE engine: a from-scratch swarm loop built directly on the OpenAI Agents SDK (@openai/agents' run()) instead of Mastra or the raw AI SDK. It reuses the SAME governance plane as its native siblings — pre-generation reserve, fail-closed tool gate, cost caps, secrets, tier routing, telemetry — and its full-governance claim is verified, not assumed: a spike confirmed the SDK's RunConfig.callModelInputFilter fires exactly once per model launch and a thrown error aborts the run cleanly. v1 is deliberately single-agent (delegation and workflows both false); tool approvals map onto the SDK's native approve/reject interruption and telemetry emits OTel spans.
When to use it
- You want the loop built on the OpenAI Agents SDK (run()) — you already use @openai/agents, its guardrails, or its tracing.
- Your swarm is single-agent and you want full governance plus OTel telemetry on this stack rather than Mastra.
- You want tool approvals expressed as the SDK's native boolean approve/reject interruption, backstopped by Night Owls' fail-closed gate.
When not to
- Your pack is multi-agent — delegation is false here; the SDK's native handoffs become Night Owls delegation in v1.1, not v1.
- You send PDFs or text-class document attachments — the aisdk() bridge throws on file inputs, so multimodal is image-only (pdf:false, text:false) at this version.
- You need client-tool suspend/resume (camera, selection, apply-to-scene) — hitl.clientTools is false; the SDK's only pause primitive is the boolean tool-approval interruption.
Alternatives
- engine-mastra (the default)You need delegation, workflows, or semantic recall — only there today.
- engine-ai-sdkYou want a native single-agent loop but on the raw Vercel AI SDK (streamText) rather than the OpenAI Agents SDK — same full-governance posture, and it supports PDF/text attachments this engine can't.
- @openai/agents directlyYou want the OpenAI Agents SDK with no Night Owls governance plane, cost caps, secrets boundary, or swappable-engine contract — a plain run() with none of the gating.
Strengths
- Full governance verified against the SDK: a spike proved callModelInputFilter fires once per launch and a throw aborts cleanly (never a stranded/partial generation), so governance.preGeneration: true is honest.
- Native tool-approval interruption mapped onto Night Owls' fail-closed gate; mid-stream cancellation; OTel spans (telemetry: true — the only adapter/native split where an adapter can't match).
- The RunState.toString() snapshot is genuinely cross-process-serializable (JSON, schema v1.13), so durable resume can legitimately earn true when you opt in.
- Same swarm description as every other engine — swap the factory, keep the crew definition.
Limits & trade-offs
- Single-agent only in v1 — delegation and workflows are both false; native handoffs become delegation in v1.1.
- Multimodal is image-only: the @openai/agents-extensions aisdk() bridge throws UserError on file inputs, so PDFs and text-class documents are unreachable (pdf:false, text:false), not merely unwired.
- No client-tool path (clientTools:false), so browser-executed tools and the resolved swarm.client_action fields don't apply here.
- Heavy dependency surface: Node >= 22 and a peer on ai@^7 (you provide it), plus the pinned @openai/agents / -core / -extensions / -openai family bundled as direct dependencies.
How it works
openAiAgentsEngine({ durable }) returns (opts) => new OpenAiAgentsEngine(opts, { durable }) from the fully-assembled AssembledEngineOpts. The loop drives @openai/agents' run(); pre-generation gating rides RunConfig.callModelInputFilter (verified to fire once per model launch), tool approvals ride the SDK's native approve/reject interruption backstopped by the fail-closed gate, and cancellation is mid-stream. durableResume is a per-INSTANCE flip (default false) that earns true only when the injected StorageAdapter persists the SDK's RunState.toString() snapshot across processes. OPENAI_AGENTS_ENGINE_CAPABILITIES is the static descriptor: tier 3 with swarm.handoff and swarm.client_action absent from emits (single-agent, no client-tool path).
Examples
Wire the OpenAI-Agents engine
Same swarm description; the loop runs on @openai/agents' run(). Needs Node >= 22 and a peer ai@^7; the @openai/agents family is bundled.
import { defineSwarm } from "@nightowlsdev/core";
import { openAiAgentsEngine } from "@nightowlsdev/engine-openai-agents";
export default defineSwarm({
agents,
engine: openAiAgentsEngine(),
});Confirm the full-governance posture
The preGeneration:true claim is spike-verified, not assumed. Durable resume opts in when your storage persists the RunState snapshot cross-process.
import { openAiAgentsEngine, OPENAI_AGENTS_ENGINE_CAPABILITIES } from "@nightowlsdev/engine-openai-agents";
const swarm = defineSwarm({ agents, engine: openAiAgentsEngine({ durable: true }) });
console.log(OPENAI_AGENTS_ENGINE_CAPABILITIES.governance.preGeneration); // true
console.log(OPENAI_AGENTS_ENGINE_CAPABILITIES.telemetry); // true (OTel spans)Doing the parts it doesn't support
- Multi-agent delegation and workflowsNot in v1 (delegation: false, workflows: false). Run multi-agent packs on engine-mastra; the SDK's native handoffs become Night Owls delegation in v1.1.
- PDF / text-class document attachmentsThe aisdk() bridge throws on file inputs at this version, so only images reach the model. Use engine-ai-sdk (native file transport for image/pdf/text) or feed documents as host-extracted advisory text, which works on every engine.
- Browser-executed client toolsclientTools is false — the SDK exposes only a boolean tool-approval interruption. Use engine-mastra (or engine-ai-sdk's approval path) if you need the client_action suspend/resume protocol.
Related
- core — The required base — this engine reuses core's governance plane (hooks, CostGovernor, secrets) verbatim.
- engine-ai-sdk — The sibling native engine on the raw AI SDK — same governance posture, and it supports the attachment classes this engine can't.
- engine-mastra — The default engine — the delegation / workflow / semantic-recall path this engine defers to.
- provider-openai — The OpenAI model provider you'd typically route this engine's agents through.
- approval-modes — How the tool-approval gate this engine backstops is configured for a deployment.