@aeonic-agentguard/sdk-node
v0.1.14
Published
Aeonic Node.js SDK for AI agent monitoring and drift detection
Maintainers
Readme
@aeonic-agentguard/sdk-node
Runtime monitoring, drift detection, and governance for AI agents in Node.js applications.
The SDK observes agent-powered API routes at runtime, captures request/response samples, and sends them to Aeonic for analysis. Only routes you explicitly mark as agent routes are tracked.
Supported frameworks: Express, NestJS
Requirements
- Node.js 20+ (required by the SDK's SSE client dependency)
- Express
^4.18and/or NestJS^9/^10withreflect-metadataandrxjs
Installation
npm install @aeonic-agentguard/sdk-nodeEnvironment variables
Set these in your deployment platform or .env file (local development).
| Variable | Required | Description |
|----------|----------|-------------|
| AEONIC_API_KEY | Yes | API key from the Aeonic dashboard |
| PORT | Recommended | Your app's listen port (used when Aeonic runs assessments against your agent) |
| AEONIC_DEBUG | No | Set to true for more verbose SDK logs (troubleshooting) |
| AEONIC_LOAD_DOTENV | No | Set to false in production to disable automatic .env loading |
AEONIC_API_KEY=your-api-key
PORT=3000Keep
.envout of version control. In production, prefer platform environment variables over.envfiles.
Quick start
1. Initialize the SDK
Call init() once at application startup. Pass your Express or NestJS app instance.
import { init } from "@aeonic-agentguard/sdk-node";
init({
api_key: process.env.AEONIC_API_KEY!,
app, // Express app or NestJS app from NestFactory.create()
service_name: "my-service", // optional, shown in the Aeonic dashboard
capture_payloads: {
max_samples: 10, // optional, default: 10
},
});init() options
| Option | Required | Default | Description |
|--------|----------|---------|-------------|
| api_key | Yes | — | Aeonic API key |
| app | Yes | — | Express or NestJS application instance |
| service_name | No | — | Logical service name in the dashboard |
| capture_payloads.max_samples | No | 10 | Samples buffered per agent before flush |
| introspection_delay_ms | No | 2000 | Delay before route introspection at startup |
| agentguard_enabled | No | true | Enable AgentGuard registration and assessments |
What init() does:
- Registers your service with Aeonic
- Discovers declared agent routes and emits agent inventory
- Connects to AgentGuard for assessments and agent status updates (non-blocking)
You may call init() before or after defining routes; the SDK defers route introspection briefly so routes can be registered first.
Express integration
Aeonic uses two pieces in Express:
expressMiddleware()— global middleware (register once)withAgentMiddleware()— per-route marker for agent endpoints
import express from "express";
import {
init,
expressMiddleware,
withAgentMiddleware,
} from "@aeonic-agentguard/sdk-node";
const app = express();
app.use(express.json());
app.use(expressMiddleware());
app.post(
"/agent/finance",
withAgentMiddleware({
name: "RefundRiskAgent",
type: "finance",
model: ["gpt-4o"],
source: "manual",
}),
async (req, res) => {
res.json({ approved: true, amount: req.body.amount });
},
);
init({
api_key: process.env.AEONIC_API_KEY!,
app,
service_name: "express-app",
});
app.listen(process.env.PORT ?? 3000);Mounted routers: If agent routes live under
app.use("/api/agents", router), registerexpressMiddleware()on that router (or ensure it runs in the same stack aswithAgentMiddleware) so samples are captured reliably.
withAgentMiddleware() fields
| Field | Type | Description |
|-------|------|-------------|
| name | string | Unique agent name |
| type | string | Agent category (e.g. finance, support) |
| model | string[] | Models used by this agent |
| source | string | Optional; the SDK sets "manual" when you use this middleware |
NestJS integration
main.ts
import "reflect-metadata";
import { NestFactory } from "@nestjs/core";
import { init } from "@aeonic-agentguard/sdk-node";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
init({
api_key: process.env.AEONIC_API_KEY!,
app,
service_name: "nest-app",
capture_payloads: { max_samples: 10 },
});
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();app.module.ts
import { Module } from "@nestjs/common";
import { APP_INTERCEPTOR } from "@nestjs/core";
import { AeonicInterceptor } from "@aeonic-agentguard/sdk-node";
import { AppController } from "./app.controller";
@Module({
controllers: [AppController],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: AeonicInterceptor,
},
],
})
export class AppModule {}Controller
import { Controller, Post, Body } from "@nestjs/common";
import { WithAgent } from "@aeonic-agentguard/sdk-node";
@Controller("agent")
export class AppController {
@Post("finance")
@WithAgent({
name: "RefundRiskAgent",
type: "finance",
model: ["gpt-4o"],
})
finance(@Body() body: { amount: number }) {
return { approved: true, amount: body.amount };
}
}How it works
HTTP request
→ global middleware / interceptor
→ @WithAgent / withAgentMiddleware handler
→ response captured
→ samples buffered and sent to Aeonic- Non-agent routes are ignored entirely.
- Assessment calls (identified by the
X-Aeonic-Assessmentheader) skip sample collection but still execute normally. - The SDK never blocks or alters your application responses. Failures to reach Aeonic are logged and do not crash your app.
Sample collection vs assessments
| Flow | Trigger | Buffering |
|------|---------|-----------|
| Sample collection | Normal traffic to agent routes | Buffers until max_samples (default 10), then flushes |
| Assessments | AgentGuard SSE job from Aeonic | Calls your agent API immediately (one shot per step) |
Agent inventory
At startup, the SDK discovers agents declared via withAgentMiddleware() or @WithAgent() and reports them to Aeonic (route path, HTTP method, framework, and agent metadata). Inventory is emitted once per process lifecycle.
API reference
| Export | Used in | Purpose |
|--------|---------|---------|
| init | main.ts / entrypoint | One-time SDK initialization |
| expressMiddleware | Express app setup | Global response hook for sampling |
| withAgentMiddleware | Express routes | Mark a route as an agent endpoint |
| AeonicInterceptor | NestJS APP_INTERCEPTOR | Global interceptor for sampling |
| WithAgent | NestJS controllers | Mark a handler as an agent endpoint |
AgentGuard registration, SSE, and assessment execution run automatically when init() is called with agentguard_enabled (default true). You do not import or call those internally.
Troubleshooting
No agents appear in the dashboard
- Confirm agent routes use
withAgentMiddleware()or@WithAgent(). - Confirm
expressMiddleware()orAeonicInterceptoris registered. - Confirm
init()was called with a validapi_keyandapp. - Increase
introspection_delay_msif routes are registered late at startup.
Samples not flushing
- Default
max_samplesis 10 — send enough traffic or setcapture_payloads: { max_samples: 1 }while testing. - For mounted Express routers, register
expressMiddleware()on the router. - Look for
[Aeonic] Agent samples emitted successfullyin logs.
AgentGuard registration warnings
[Aeonic] AgentGuard registration failed: ...
[Aeonic] SDK will continue to function for sample collection onlyYour app continues to run. AgentGuard features (assessments, SSE status updates) require successful registration. Verify AEONIC_API_KEY and network egress to Aeonic.
NestJS: decorator metadata not detected
- Import
reflect-metadataat the top ofmain.ts. - Ensure
@WithAgent()is applied directly on the controller method.
Assessment calls fail locally
- Set
PORTto the port your app listens on. - The SDK calls your agent routes on
http://localhost:<PORT>during assessments; the app and SDK must run in the same process. - Ensure backend
agent_endpoint.urlmatches your real route path.
Enable debug logging
AEONIC_DEBUG=trueUse only for troubleshooting. Enables more verbose SDK logs.
Security and privacy
- Payloads are sampled, not streamed continuously.
- Only up to
max_samplesrequest/response pairs are collected per flush. - Non-agent routes are never inspected.
- Do not commit
AEONIC_API_KEYto source control.
License
MIT © Aeonic
