Aviary

Agent

A governed AI agent for NestJS — chat, tool-calling, per-tool RBAC, token quota, cost tracking, and human-in-the-loop approval, with each turn optionally a replay-safe durable workflow and wired into the ecosystem's durable, telescope, and diagnostics glue.

@dudousxd/nestjs-agent brings an in-app AI assistant to NestJS the way Laravel brings batteries-included features to PHP. Every app that builds a copilot rewrites the same machinery: the agentic loop (model → tools → model), a tool registry, RBAC per tool, token quota, cost tracking, audit, human approval for destructive actions, and resumable streaming. All of that is mechanism — the library. Your domain (which tables, which tenant column, which roles) stays policy you supply.

The turn can be a durable workflow

Out of the box the turn runs on an inline runner — in-process, no extra dependencies. Add @dudousxd/nestjs-durable and flip durable: true and each turn instead runs as a durable workflow: every model and tool call becomes a checkpointed step, so a crash mid-turn replays from cache, and human-in-the-loop approval becomes a durable signal — the run suspends in the state store instead of holding a connection, and resumes when a human approves. Under durable: true, the turn's model call and tool executions are, by default, dispatched as routed durable steps (AgentRunSteps.llm / AgentRunSteps.tool) rather than pinned to the pod that started the run — either can land on any worker in the fleet (opt out with dispatchedSteps: false). Either way live tokens flow on a separate data plane (a TokenStreamSink), so streaming and durability compose instead of fighting — but a dispatched turn needs that sink to be cross-process (e.g. RedisTokenStreamSink), since the worker executing the step may not be the pod holding the SSE connection. The wire protocol your frontend speaks is identical, so you develop inline and flip to durable in production without touching your tools or UI. See Architecture for the full control/data-plane picture.

What you get

  • Tool framework@AiTool({ kind: 'read' | 'action' }) classes, auto-discovered. action tools never auto-execute; the run pauses for approval.
  • Governance out of the box — RBAC per tool, per-agent system prompts and tool allow-lists, daily token quota, and an audit trail of every tool call.
  • Cost accounting — a usage ledger per turn, rolled up into spend per model / per actor / over time. A gateway's real reported cost wins; otherwise a cache-aware estimate against a versioned pricing table (prompt cache-write / cache-read priced at their own rates).
  • A governance console@dudousxd/nestjs-agent-dashboard mounts a standalone AI-gateway console (bundled React SPA + NestJS module) at its own route, no Telescope required.
  • Streaming — SSE with resume; reconnect replays the buffered tokens.
  • Inline or durable — an in-process runner by default, or opt into the durable runner (add @dudousxd/nestjs-durable, set durable: true) for checkpointed, replay-safe turns — one AgentRunner SPI, identical wire protocol. Durable turns dispatch their model/tool steps across the worker fleet by default (AgentRunSteps.llm/.tool).
  • Run reliability + tracing — every run's start/end is durably recorded (agent_run, with a promptHash of the resolved system prompt) and every turn emits diagnostics spans (traceId = runId) that Telescope renders as a waterfall in its TRACES tab.
  • Multi-agent — an orchestrator delegates to named sub-agents via a synthesized ask_<name> tool; each delegation is a durable child run.
  • The data satellite@dudousxd/nestjs-agent-data packages governed, read-only SQL (AST-validated, RBAC + tenant scoping) as an opt-in tool.
  • A React frontend@dudousxd/nestjs-agent-react's useAgentChat (Vercel AI SDK v7) plus styling-agnostic chat components and an optional markdown renderer.
  • Zero provider code@dudousxd/nestjs-agent-ai-sdk's aiSdkModel(model) adapts any Vercel AI SDK v7 LanguageModel to the ModelProvider SPI, the first of a family of provider adapters, so an app supplies model without writing a wrapper.

The four glue points

  • Diagnostics — emits aviary:agent:* point events (run.started, message, tool-call, delegated, retrieved, quota.exceeded, run.failed, run.finished) on Node's diagnostics_channel, plus tracing spans (llm.turn, tool.execution, retrieval, follow-ups) correlated by traceId = runId.
  • Telescope@dudousxd/nestjs-agent-telescope adds an "Agent" tab with the governance sections (including Reliability and Approvals); runs also appear in the durable "Workflows" tab for free, and each run's spans render as a nested waterfall in Telescope's TRACES tab.
  • Codegen — a @dudousxd/nestjs-agent-codegen extension injects api.agent.* into the unified typed client.
  • Module conventionforRoot / forRootAsync, @Agent-decorated providers discovered at boot, and Symbol.for capabilities.

Status

Early development (0.x). The full family ships today — core, the NestJS module (inline + durable runners, the latter dispatching model/tool steps across the fleet by default), MikroORM and Drizzle persistence (including model pricing and run reliability), the governance read-model (spend, run reliability, tool stats, a cross-thread approvals inbox, paginated/filterable lists), the standalone dashboard, the telescope extension (including run tracing), governed SQL (-data), the React frontend (-react), the AI SDK model adapter (-ai-sdk), codegen, a Redis-backed multi-replica token sink (-transport-redis), and a runnable fully-offline end-to-end demo. The package surface and SPIs are still stabilizing.

Where to go next

On this page