cd /news/ai-agents/hazeljs-agent-1-0-1-production-harde… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-27241] src=dev.to β†— pub= topic=ai-agents verified=true sentiment=↑ positive

@hazeljs/agent 1.0.1: Production Hardening for Real Deployments

The Hazel team released @hazeljs/agent 1.0.1, a patch focused on production hardening with Redis-backed state, durable tool approvals, circuit breakers, and observability. The update is backward compatible and addresses multi-instance deployment risks such as state loss and broken approvals across replicas.

read5 min publishedJun 14, 2026

We are shipping @hazeljs/agent 1.0.1 β€” a patch release focused on operational durability, resilience consolidation, and production observability. If you run agents behind a load balancer, need human-in-the-loop tool approvals, or want circuit breakers and traces in production, this release is for you.

1.0.1 is backward compatible. No breaking API changes β€” only new optional configuration, factories, and exports.

A minimal production bootstrap with Redis-backed state, durable approvals, and strict event handling:

import { HazelApp } from '@hazeljs/core';
import { Agent, Tool, AgentModule, AgentService } from '@hazeljs/agent';
import { createClient } from 'redis';

@Agent({ name: 'ops-agent', description: "'Operations assistant' })"
class OpsAgent {
  @Tool({ description: "'Restart a service', requiresApproval: true })"
  async restartService(input: { service: string }) {
    return { restarted: input.service, at: new Date().toISOString() };
  }
}

const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();

await AgentModule.forRootAsync({
  redis: { client: redis },
  useRedisApprovals: true,
  runtime: {
    strictEventHandlers: true,
    enableCircuitBreaker: true,
    observabilityProvider: myObservabilityProvider, // optional
  },
});

const app = new HazelApp({ modules: [AgentModule] });
const agentService = app.get(AgentService);

agentService.on('agent.tool.approval.requested', (event) => {
  // Approve from any replica β€” request is stored in Redis
  agentService.approveToolExecution(event.data.requestId, 'admin');
});

await agentService.execute('ops-agent', 'Restart the payment worker');

Same agent code as 1.0.0 β€” only module wiring changes for production.

@hazeljs/agent

1.0.0 shipped a full agent runtime: execution loop, tools, memory/RAG, multi-agent graphs, A2A, streaming, and guardrails hooks. What it did not optimize for was multi-instance production:

Area 1.0.0 default Production risk
Execution state In-memory Lost on process restart
Tool approvals In-memory Map s
Broken across replicas; lost on crash
Retry / rate limit Local utilities Drift from @hazeljs/resilience
Observability Local metrics + events No OTel spans or LLM cost bridge
RAG errors Silently returned []
Hard to debug in prod

1.0.1 closes these gaps without changing how you define agents or tools.

New factory helpers pick the right persistence backend from config or environment:

import {
  createStateManager,
  createStateManagerFromEnv,
  AgentModule,
} from '@hazeljs/agent';

// Sync β€” when you already have a connected Redis client
const stateManager = createStateManager({
  backend: 'redis',
  redisClient,
});

// Async β€” connects from REDIS_URL
const stateManager = await createStateManagerFromEnv({
  redisUrl: process.env.REDIS_URL,
});

Environment variables:

Variable Values Behavior
AGENT_STATE_BACKEND
memory , redis , database
Explicit backend selection
REDIS_URL
Redis connection URL Auto-selects Redis when set

AgentModule.forRoot()

and ** AgentModule.forRootAsync()** wire Redis state when a client or URL is provided:

import { AgentModule } from '@hazeljs/agent';
import { createClient } from 'redis';

const redisClient = createClient({ url: process.env.REDIS_URL });
await redisClient.connect();

await AgentModule.forRootAsync({
  redis: { client: redisClient },
  useRedisApprovals: true,
  runtime: {
    strictEventHandlers: process.env.NODE_ENV === 'production',
  },
});

forRoot()

redis.client

forRootAsync()

REDIS_URL

or redis.url

before bootSee PERSISTENCE.md for Redis, Prisma, and hybrid setups.

Tool approvals no longer live only in process memory. A new ** IApprovalStore** interface supports:

InMemoryApprovalStore

RedisApprovalStore

When AgentModule

is configured with Redis, approvals are stored in Redis automatically so human-in-the-loop flows work across replicas.

New exports:

import {
  IApprovalStore,
  InMemoryApprovalStore,
  RedisApprovalStore,
  createApprovalStore,
} from '@hazeljs/agent';

Local retry and rate-limit utilities now delegate to ** @hazeljs/resilience**:

RetryHandler

β†’ RetryPolicy

RateLimiter

β†’ TokenBucketLimiter

The public API of RetryHandler

and RateLimiter

is preserved (marked @deprecated

for direct resilience use in a future minor). The deprecated ** circuit-breaker.js** shim was removed.

Circuit breaker behavior is now validated end-to-end: repeated LLM failures through AgentRuntime.execute()

open the circuit and subsequent calls fail fast with CircuitBreakerError

.

Failed agent executions (AgentState.FAILED

) now propagate as errors through the circuit breaker and retry layers instead of returning silently.

Optional peers were added for production tracing and cost tracking:

@hazeljs/observability

(optional)@opentelemetry/api

(optional)When you pass an ** observabilityProvider** in runtime config, the agent emits OpenTelemetry spans:

Span When
agent.execute
Full agent run
agent.tool.execute
Tool invocation
agent.llm
LLM chat call

Span attributes include agent.name

, agent.execution_id

, agent.tool.name

, and session metadata. LLM usage is bridged to ** trackCost()** when the provider is configured.

import { AgentRuntime } from '@hazeljs/agent';

const runtime = new AgentRuntime({
  observabilityProvider: myObservabilityProvider,
  llmProvider,
});

No hard dependency on OTel β€” spans are no-ops unless a provider is injected.

RAG search failures no longer silently return an empty context. The runtime now:

agent.rag.failed

AgentEventType.RAG_QUERY_FAILED

)ragContext: []

(graceful degradation)AgentEventEmitter

accepts ** strictEventHandlers: true**. When enabled, errors in event handlers propagate instead of being swallowed β€” recommended for production.

If @hazeljs/ai

never registers __HAZELJS_AI_ENHANCED_SERVICE__

, AgentService

now logs a clear error after 500ms instead of failing silently. Set runtime.llmProvider

explicitly or ensure the AI module loads first.

State managers use minimal interfaces instead of any

:

RedisClientLike

PrismaClientLike

DatabaseStateManager

Safer to wire real clients without losing type checking at the boundary.

474 tests pass with coverage thresholds enforced. New integration coverage includes:

RedisApprovalStore

Test locations:

tests/integration/production-hardening.test.ts

tests/integration/hardening-coverage.test.ts

Jest uses tsconfig.jest.json

for monorepo-friendly typechecking; optional @hazeljs/eval

peer is stubbed during tests.

npm install @hazeljs/agent@1.0.1

No code changes required for existing apps. To adopt production features incrementally:

redis: { client }

or await AgentModule.forRootAsync({ redis: { url } })

useRedisApprovals: true

with a Redis client@hazeljs/observability

and pass observabilityProvider

runtime.strictEventHandlers: true

in productionNot in 1.0.1, planned for future minors:

@hazeljs/flow

__HAZELJS_AI_ENHANCED_SERVICE__

Questions or feedback? Open an issue or join the discussion on GitHub.

── more in #ai-agents 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/hazeljs-agent-1-0-1-…] indexed:0 read:5min 2026-06-14 Β· β€”