Documentation•Reference

HazelJS Autonomous Package

npm downloads

@hazeljs/​autonomous is the Autonomous Application Runtime (AAR) for HazelJS — governed autonomy for ordinary @Injectable() services.

Models and rules may propose actions. They must not bypass authorization. AAR coordinates existing Agent OS primitives (Gatekeeper, HITL, durable runs) so services can observe domain events, decide, approve, and execute without becoming @Agent classes.

Observation ≠ Decision ≠ Policy ≠ Authorization ≠ Execution

There is no permission-bypassing mode. “Fully autonomous” means governed-auto within explicit grants + Gatekeeper allow. Confidence / model output never collapses those layers.

Quick Reference

  • Purpose: Opt-in control plane so ordinary services observe events, propose capabilities, pause for HITL, and execute only when granted + Gatekeeper-allowed.
  • When to use: Order ops, remediations, shipping switches, refunds — domain services that should act on events without an LLM agent loop.
  • Key APIs: AutonomousModule.forRoot, AutonomousRuntime (emit, resume, inspect, timeline, replay, diff, recover, listRuns), simulate, evaluateOutcome, MemoryAutonomousRunStore, createAgentBackedRunStore, decorators from @hazeljs/​core: @Autonomous, @Observe, @Capability.
  • Dependencies: Peer @hazeljs/​core, @hazeljs/​agent-gatekeeper. Optional: @hazeljs/​agent (durable store bridge), @hazeljs/​decision, @hazeljs/​agent-vm, @hazeljs/​event-emitter.
  • Common mistakes: Treating AAR as a second agent runtime; granting every capability by default; trusting tenantId from model/event payloads; dry-run replay with live side effects; confusing AAR with roadmap @AutonomousOptimization (HTTP self-tuning — separate, unimplemented).

Installation

npm install @hazeljs/​autonomous @hazeljs/​core @hazeljs/​agent-gatekeeper
# optional production durability:
npm install @hazeljs/​agent
# optional:
npm install @hazeljs/​decision @hazeljs/​agent-vm @hazeljs/​event-emitter

Or:

hazel add autonomous --setup

Enable experimentalDecorators (and typically emitDecoratorMetadata) in tsconfig.json.

Minimal example

import { Injectable, Autonomous, Observe, Capability, HazelModule } from '@hazeljs/​core';
import { AutonomousModule } from '@hazeljs/​autonomous';

@Injectable()
@Autonomous({
  id: 'order-operations',
  objective: 'Maintain reliable order processing',
  mode: 'approval-required',
  capabilities: ['orders.retry'],
})
export class OrderOperationsService {
  @Observe('orders.failed')
  onFailure(event: { orderId: string }) {
    return event;
  }

  @Capability({
    id: 'orders.retry',
    effect: 'idempotent',
    approval: 'auto',
    idempotencyKey: true,
  })
  retryOrder(input: { orderId: string }) {
    return { retried: input.orderId };
  }
}

@HazelModule({
  imports: [AutonomousModule.forRoot({ observability: { enabled: true } })],
  providers: [OrderOperationsService],
})
export class AppModule {}

Emit and resume:

import { AutonomousRuntime } from '@hazeljs/​autonomous';

const runtime = container.resolve(AutonomousRuntime);
const [runId] = await runtime.emit('orders.failed', { orderId: 'ORD-1' }, { tenantId: 't1' });
await runtime.resume(runId!, { approved: true, actor: 'ops' });

Modes

ModeBehavior
disabledNo autonomous execution
observe-onlyRecord observations only
suggestRecommendations only
approval-requiredHITL before effects
governed-autoExecute only granted + Gatekeeper-allowed capabilities

Default capability grants: none (default deny).

Architecture

@Service @Autonomous
  → @Observe → AutonomousRuntime
    → decision engine (rules /​ optional Decision Plane)
      → Gatekeeper (authorize)
        → HITL when required
          → capability method
            → durable run + timeline
ConcernPrimitive
Decorators / contracts@hazeljs/​core (@Autonomous, @Observe, @Capability)
Call-time authorization@hazeljs/​agent-gatekeeper
Durable runs (optional)@hazeljs/​agent DurableRunStore via createAgentBackedRunStore
Effect isolationOptional @hazeljs/​agent-vm (not reimplemented)
Advanced decisionsOptional @hazeljs/​decision

Capabilities

@Capability({
  id: 'payments.refund',
  effect: 'irreversible',
  approval: 'required',
  reconcile: 'reconcileRefund',
})
async refund(input: RefundInput) {
  return this.payments.refund(input);
}

Effect classes: read-only | idempotent | reversible | irreversible.

Irreversible capabilities cannot auto-retry without idempotencyKey or reconcile (HAZEL_AUTONOMOUS_RETRY_UNSAFE).

Durability, replay, simulation

  • Memory store — tests and local demos (MemoryAutonomousRunStore).
  • Production — bridge Agent DurableRunStore / SQL with createAgentBackedRunStore.
  • Replay — dry-run only; never repeats live side effects.
  • Simulation — simulate() always sets simulation: true (hard live-effect barrier).
  • Recovery — interrupted executing runs enter reconcile; do not blindly re-issue irreversible ops.

Security

A capability executes only when all hold server-side:

  1. Capability is registered
  2. Service grants include the capability id
  3. Gatekeeper policy allows (or approval consumed)
  4. Tenant context is trusted (framework identity via resolveTenantId)
  5. Budgets / rate limits / loop protection permit
  6. Effect / simulation barriers permit

Approvals bind capability id, argument digest, tenant, and expiry. Argument changes invalidate prior approval. Observation payloads are redacted before timeline persistence (redactPayload).

Full guide: Autonomous Runtime.

CLI

hazel add autonomous --setup
hazel agent runs list
hazel agent runs inspect <run-id>
hazel agent runs timeline <run-id>
hazel agent runs replay <run-id> --dry-run
hazel agent runs diff <run-a> <run-b>

Local examples

npm run example:order-ops --workspace=@hazeljs/​autonomous
npm run demo:failure --workspace=@hazeljs/​autonomous