{"slug": "hazeljs-agent-1-0-1-production-hardening-for-real-deployments", "title": "@hazeljs/agent 1.0.1: Production Hardening for Real Deployments", "summary": "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.", "body_md": "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.\n\n**1.0.1 is backward compatible.** No breaking API changes — only new optional configuration, factories, and exports.\n\nA minimal production bootstrap with Redis-backed state, durable approvals, and strict event handling:\n\n``` js\nimport { HazelApp } from '@hazeljs/core';\nimport { Agent, Tool, AgentModule, AgentService } from '@hazeljs/agent';\nimport { createClient } from 'redis';\n\n@Agent({ name: 'ops-agent', description: \"'Operations assistant' })\"\nclass OpsAgent {\n  @Tool({ description: \"'Restart a service', requiresApproval: true })\"\n  async restartService(input: { service: string }) {\n    return { restarted: input.service, at: new Date().toISOString() };\n  }\n}\n\nconst redis = createClient({ url: process.env.REDIS_URL });\nawait redis.connect();\n\nawait AgentModule.forRootAsync({\n  redis: { client: redis },\n  useRedisApprovals: true,\n  runtime: {\n    strictEventHandlers: true,\n    enableCircuitBreaker: true,\n    observabilityProvider: myObservabilityProvider, // optional\n  },\n});\n\nconst app = new HazelApp({ modules: [AgentModule] });\nconst agentService = app.get(AgentService);\n\nagentService.on('agent.tool.approval.requested', (event) => {\n  // Approve from any replica — request is stored in Redis\n  agentService.approveToolExecution(event.data.requestId, 'admin');\n});\n\nawait agentService.execute('ops-agent', 'Restart the payment worker');\n```\n\nSame agent code as 1.0.0 — only module wiring changes for production.\n\n`@hazeljs/agent`\n\n1.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**:\n\n| Area | 1.0.0 default | Production risk |\n|---|---|---|\n| Execution state | In-memory | Lost on process restart |\n| Tool approvals | In-memory `Map` s |\nBroken across replicas; lost on crash |\n| Retry / rate limit | Local utilities | Drift from `@hazeljs/resilience`\n|\n| Observability | Local metrics + events | No OTel spans or LLM cost bridge |\n| RAG errors | Silently returned `[]`\n|\nHard to debug in prod |\n\n**1.0.1 closes these gaps** without changing how you define agents or tools.\n\nNew factory helpers pick the right persistence backend from config or environment:\n\n``` js\nimport {\n  createStateManager,\n  createStateManagerFromEnv,\n  AgentModule,\n} from '@hazeljs/agent';\n\n// Sync — when you already have a connected Redis client\nconst stateManager = createStateManager({\n  backend: 'redis',\n  redisClient,\n});\n\n// Async — connects from REDIS_URL\nconst stateManager = await createStateManagerFromEnv({\n  redisUrl: process.env.REDIS_URL,\n});\n```\n\nEnvironment variables:\n\n| Variable | Values | Behavior |\n|---|---|---|\n`AGENT_STATE_BACKEND` |\n`memory` , `redis` , `database`\n|\nExplicit backend selection |\n`REDIS_URL` |\nRedis connection URL | Auto-selects Redis when set |\n\n`AgentModule.forRoot()`\n\nand ** AgentModule.forRootAsync()** wire Redis state when a client or URL is provided:\n\n``` js\nimport { AgentModule } from '@hazeljs/agent';\nimport { createClient } from 'redis';\n\nconst redisClient = createClient({ url: process.env.REDIS_URL });\nawait redisClient.connect();\n\nawait AgentModule.forRootAsync({\n  redis: { client: redisClient },\n  useRedisApprovals: true,\n  runtime: {\n    strictEventHandlers: process.env.NODE_ENV === 'production',\n  },\n});\n```\n\n`forRoot()`\n\n`redis.client`\n\n`forRootAsync()`\n\n`REDIS_URL`\n\nor `redis.url`\n\nbefore bootSee [PERSISTENCE.md](https://./PERSISTENCE.md) for Redis, Prisma, and hybrid setups.\n\nTool approvals no longer live only in process memory. A new ** IApprovalStore** interface supports:\n\n`InMemoryApprovalStore`\n\n`RedisApprovalStore`\n\nWhen `AgentModule`\n\nis configured with Redis, approvals are stored in Redis automatically so **human-in-the-loop flows work across replicas**.\n\nNew exports:\n\n``` js\nimport {\n  IApprovalStore,\n  InMemoryApprovalStore,\n  RedisApprovalStore,\n  createApprovalStore,\n} from '@hazeljs/agent';\n```\n\nLocal retry and rate-limit utilities now delegate to ** @hazeljs/resilience**:\n\n`RetryHandler`\n\n→ `RetryPolicy`\n\n`RateLimiter`\n\n→ `TokenBucketLimiter`\n\nThe public API of `RetryHandler`\n\nand `RateLimiter`\n\nis preserved (marked `@deprecated`\n\nfor direct resilience use in a future minor). The deprecated ** circuit-breaker.js** shim was removed.\n\n**Circuit breaker behavior is now validated end-to-end:** repeated LLM failures through `AgentRuntime.execute()`\n\nopen the circuit and subsequent calls fail fast with `CircuitBreakerError`\n\n.\n\nFailed agent executions (`AgentState.FAILED`\n\n) now **propagate as errors** through the circuit breaker and retry layers instead of returning silently.\n\nOptional peers were added for production tracing and cost tracking:\n\n`@hazeljs/observability`\n\n(optional)`@opentelemetry/api`\n\n(optional)When you pass an ** observabilityProvider** in runtime config, the agent emits OpenTelemetry spans:\n\n| Span | When |\n|---|---|\n`agent.execute` |\nFull agent run |\n`agent.tool.execute` |\nTool invocation |\n`agent.llm` |\nLLM chat call |\n\nSpan attributes include `agent.name`\n\n, `agent.execution_id`\n\n, `agent.tool.name`\n\n, and session metadata. LLM usage is bridged to ** trackCost()** when the provider is configured.\n\n``` js\nimport { AgentRuntime } from '@hazeljs/agent';\n\nconst runtime = new AgentRuntime({\n  observabilityProvider: myObservabilityProvider,\n  llmProvider,\n});\n```\n\nNo hard dependency on OTel — spans are no-ops unless a provider is injected.\n\nRAG search failures no longer silently return an empty context. The runtime now:\n\n`agent.rag.failed`\n\n`AgentEventType.RAG_QUERY_FAILED`\n\n)`ragContext: []`\n\n(graceful degradation)`AgentEventEmitter`\n\naccepts ** strictEventHandlers: true**. When enabled, errors in event handlers propagate instead of being swallowed — recommended for production.\n\nIf `@hazeljs/ai`\n\nnever registers `__HAZELJS_AI_ENHANCED_SERVICE__`\n\n, `AgentService`\n\nnow **logs a clear error after 500ms** instead of failing silently. Set `runtime.llmProvider`\n\nexplicitly or ensure the AI module loads first.\n\nState managers use minimal interfaces instead of `any`\n\n:\n\n`RedisClientLike`\n\n`PrismaClientLike`\n\n`DatabaseStateManager`\n\nSafer to wire real clients without losing type checking at the boundary.\n\n**474 tests** pass with coverage thresholds enforced. New integration coverage includes:\n\n`RedisApprovalStore`\n\nTest locations:\n\n`tests/integration/production-hardening.test.ts`\n\n`tests/integration/hardening-coverage.test.ts`\n\nJest uses `tsconfig.jest.json`\n\nfor monorepo-friendly typechecking; optional `@hazeljs/eval`\n\npeer is stubbed during tests.\n\n```\nnpm install @hazeljs/agent@1.0.1\n```\n\n**No code changes required** for existing apps. To adopt production features incrementally:\n\n`redis: { client }`\n\nor `await AgentModule.forRootAsync({ redis: { url } })`\n\n`useRedisApprovals: true`\n\nwith a Redis client`@hazeljs/observability`\n\nand pass `observabilityProvider`\n\n`runtime.strictEventHandlers: true`\n\nin productionNot in 1.0.1, planned for future minors:\n\n`@hazeljs/flow`\n\n`__HAZELJS_AI_ENHANCED_SERVICE__`\n\n**Questions or feedback?** [Open an issue](https://github.com/hazel-js/hazeljs/issues) or join the discussion on [GitHub](https://github.com/hazel-js/hazeljs).", "url": "https://wpnews.pro/news/hazeljs-agent-1-0-1-production-hardening-for-real-deployments", "canonical_source": "https://dev.to/arslan_mecom/hazeljsagent-101-production-hardening-for-real-deployments-1j18", "published_at": "2026-06-14 20:21:07+00:00", "updated_at": "2026-06-14 20:40:46.834486+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Hazel", "@hazeljs/agent", "Redis", "AgentModule", "AgentService", "IApprovalStore", "RedisApprovalStore", "InMemoryApprovalStore"], "alternates": {"html": "https://wpnews.pro/news/hazeljs-agent-1-0-1-production-hardening-for-real-deployments", "markdown": "https://wpnews.pro/news/hazeljs-agent-1-0-1-production-hardening-for-real-deployments.md", "text": "https://wpnews.pro/news/hazeljs-agent-1-0-1-production-hardening-for-real-deployments.txt", "jsonld": "https://wpnews.pro/news/hazeljs-agent-1-0-1-production-hardening-for-real-deployments.jsonld"}}