v0.0.58 — Zero-dependency security layer for AI agent systems. Ed25519 identity, JWT auth, constraint enforcement, encrypted audit, human-in-the-loop access requests, constraint-aware agent flows, and end-to-end agent session tracing.
npm install agents-chainRequires Node.js 18+. Ships ESM + CommonJS.
- Host + Agent identity — Ed25519 keypairs with JWK thumbprints as stable IDs
- 11-step JWT verification — signature, replay protection, delegation chain, grant + constraint enforcement
- Grant constraints — field-level rules:
max,min,in,not_in, exact equality - Access requests — denied calls suspend and wait for human approval out-of-band (HMAC-verified, 4 scopes)
- Constraint-aware mode — returns structured violation envelopes so AI agents can reason about permissions and explicitly request approval
- Encrypted audit log — AES-256-GCM ring buffer with auth overhead tracking, access request lifecycle events
- Session tracing —
openTrace()/closeTrace()groups all capability and LLM calls into a singleTraceRunwith token counts, model names, tool calls, and per-span results - Zero dependencies — everything defaults to in-memory, external systems are adapter-injected
import { AppChain, isChainAuthError } from 'agents-chain';
const chain = await AppChain.create({
providerName: 'billing-service',
issuer: 'https://billing.example.com',
capabilities: [{
name: 'createInvoice',
description: 'Create an invoice',
inputSchema: {
type: 'object',
required: ['customerId', 'amount'],
properties: {
customerId: { type: 'string' },
amount: { type: 'number' },
},
},
outputSchema: { type: 'object' },
execute: async (args, ctx) => {
return { invoiceId: 'inv_001', amount: args.amount };
},
}],
});
const grants = [{
capability: 'createInvoice',
status: 'active' as const,
constraints: { amount: { max: 5000 } },
expiresAt: Date.now() + 86_400_000,
}];
const secured = chain.wrap({}, grants);
await secured.createInvoice({ customerId: 'c1', amount: 500 }); // ✅
await secured.createInvoice({ customerId: 'c1', amount: 99999 }); // ❌ constraint_violatedWhen constraintAware is enabled, capability calls return structured ConstraintAwareResult envelopes instead of throwing errors. This lets AI agents understand violations and decide whether to request human approval.
const chain = await AppChain.create({
// ...capabilities, accessRequests config...
constraintAware: true,
});
const secured = chain.wrap(service, grants);
// Allowed call — returns success envelope
const result = await secured.sendSms({ to: '+1234', message: 'Hello' });
// { success: true, result: {...}, permission: "not_required", capability: "sendSms" }
// Violation — returns structured error instead of throwing
const denied = await secured.sendSms({ to: '+9999', message: 'Hello' });
// {
// success: false,
// permission: "constraint_violated",
// violations: [{ field: "to", constraint: "in", expected: ["+1234"], actual: "+9999", message: "..." }],
// guidance: "Call request_permission to request human approval",
// capability: "sendSms",
// activeConstraints: { to: { in: ["+1234"] } }
// }With constraintAware: true and accessRequests configured, a built-in request_permission capability is auto-registered. The agent explicitly decides when to request human approval:
Step 1: Agent calls sendSms(+9999)
→ Returns structured violation (no suspension, no throw)
Step 2: Agent calls request_permission({ capability: "sendSms", args: {...}, reason: "..." })
→ Suspends until human approves/denies
→ Returns: { success: true, permission: "approved", result: {...} }
OR: { success: false, permission: "denied", reason: "..." }
The agent receives a constraint context string via chain.getConstraintContext(grants) that can be injected into its system prompt.
When accessRequests is configured, denied calls suspend instead of throwing. The call blocks until a human approves or denies via an HMAC-verified code:
const chain = await AppChain.create({
// ...
accessRequests: {
approvalSecret: process.env.APPROVAL_SECRET,
requestTTLMs: 5 * 60 * 1000,
notifier: {
async notify(request) {
console.log(`Code: ${request.verificationCode}`);
},
},
},
});
// Approve with 4 scopes: call, value, capability, global
chain.approve({ requestId, code, scope: 'value' });Read more about access requests
The audit log captures the full lifecycle of capability calls, including access request events:
| Result | Description |
|---|---|
success |
Capability executed successfully |
denied |
Call rejected by auth or constraints |
error |
Capability threw during execution |
access_requested |
Agent requested human approval (call suspended) |
access_approved |
Human approved the access request |
access_denied |
Human denied the access request |
Export audit entries to external systems via HttpAuditExporter or implement your own AuditExporter.
Track a complete agent session — every capability call, every LLM invocation, token counts, and tool calls — as a single exportable TraceRun:
import { AppChain, HttpTraceExporter } from 'agents-chain';
const chain = await AppChain.create({
// ...
traceExporter: new HttpTraceExporter({
endpoint: 'https://gateway.melduo.com/traces',
apiKey: process.env.MELDUO_API_KEY,
}),
});
// Open a trace at session start
const traceId = chain.openTrace();
// Pass traceId into wrap() and openai()/anthropic() to group spans
const secured = chain.wrap(myService, grants, traceId);
const openai = chain.openai(new OpenAI({ apiKey: '...' }), traceId);
await secured.sendEmail({ to: 'user@example.com', subject: 'Hello' });
await openai.chat.completions.create({ model: 'gpt-4o', messages: [...] });
// Close the trace — assembles the TraceRun and exports it
const run = await chain.closeTrace(traceId, 'success');
// run.summary.totalTokens → 1240
// run.summary.modelsUsed → ["gpt-4o"]
// run.spans → [{ capability, result, durationMs, modelMetadata }, ...]For custom LLM providers (Google, Cohere, etc.), implement and register a ModelMetadataExtractor.
| Section | Description |
|---|---|
| Getting Started | Installation, quick start, how it works |
| Core Concepts | Host & Agent, Capabilities, Grants, Verification, Audit |
| Tracing & Observability | Session traces, token counts, model extractors, exporters |
| Access Requests | Suspend/resume, approval scopes, security model |
| Examples | Basic service, SMS gateway, access request flow |
| API Reference | AppChainConfig, types, error codes |
| Architecture | Module map, data flows, internals |
MIT — brianmwangidev
