HazelJS Autonomous Package
@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
tenantIdfrom 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
| Mode | Behavior |
|---|---|
disabled | No autonomous execution |
observe-only | Record observations only |
suggest | Recommendations only |
approval-required | HITL before effects |
governed-auto | Execute 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
| Concern | Primitive |
|---|---|
| Decorators / contracts | @hazeljs/core (@Autonomous, @Observe, @Capability) |
| Call-time authorization | @hazeljs/agent-gatekeeper |
| Durable runs (optional) | @hazeljs/agent DurableRunStore via createAgentBackedRunStore |
| Effect isolation | Optional @hazeljs/agent-vm (not reimplemented) |
| Advanced decisions | Optional @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 withcreateAgentBackedRunStore. - Replay — dry-run only; never repeats live side effects.
- Simulation —
simulate()always setssimulation: true(hard live-effect barrier). - Recovery — interrupted
executingruns enterreconcile; do not blindly re-issue irreversible ops.
Security
A capability executes only when all hold server-side:
- Capability is registered
- Service grants include the capability id
- Gatekeeper policy allows (or approval consumed)
- Tenant context is trusted (framework identity via
resolveTenantId) - Budgets / rate limits / loop protection permit
- 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
Related
- Autonomous Runtime guide
- Agent Gatekeeper
- Decision Runtime
- Agent package
- Core package —
@Autonomous/@Observe/@Capabilitymetadata - Agent OS guide