npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@classytic/arc-ai

v0.3.0

Published

Agent toolkit on AI SDK v7 — sub-agents, context management, hooks, session, provider tools, memory, multi-tenant scope

Downloads

351

Readme

@classytic/arc-ai

Agent toolkit on AI SDK v7. Composable primitives for production agents — DB-agnostic, tree-shakable, multi-tenant aware.

Not a framework. Small pieces that compose with the AI SDK you already use.

Install

npm i @classytic/arc-ai ai zod
npm i @ai-sdk/anthropic    # or @ai-sdk/openai / @ai-sdk/google

arc-ai is provider-agnostic — any AI SDK v7 LanguageModel works. Beyond the first-party providers above, the same createAgent interface accepts Ollama (ollama-ai-provider-v2), OpenRouter (@openrouter/ai-sdk-provider — Kimi K2, DeepSeek, Qwen, Llama, …), vLLM / LM Studio / LocalAI / llama.cpp via @ai-sdk/openai-compatible, plus Groq / Together / Fireworks / Replicate / Bedrock / Azure. See skills/arc-ai/references/recipes.md → Picking a provider.

30 seconds

import { createAgent } from '@classytic/arc-ai';
import { anthropic } from '@ai-sdk/anthropic';
import { tool, isStepCount } from 'ai';
import { z } from 'zod';

const agent = await createAgent({
  id: 'support',
  model: anthropic('claude-haiku-4-5'),
  instructions: 'You are a support agent.',
  tools: {
    lookup: tool({
      description: 'Look up an order',
      inputSchema: z.object({ orderId: z.string() }),
      execute: async ({ orderId }) => db.orders.find(orderId),
    }),
  },
  stopWhen: isStepCount(10),
});

const { text } = await agent.generate({ prompt: 'Where is order 123?' });

Skill (read this first)

The package ships a curated skill at skills/arc-ai/:

  • SKILL.md — entry-point: quickstart, subpath cheat-sheet, pre-flight checklist
  • references/recipes.md — opinionated patterns per primitive (memory, sub-agents, sessions, attachments, prompt caching, serverless, picking a provider)
  • references/gotchas.md — 16 sharp edges with one-line fixes

These ship inside node_modules/@classytic/arc-ai/skills/ — open from there if you've installed via npm.

What you get

| Capability | Subpath | Built-in | |---|---|---| | Agent lifecycle + hooks | /agent | createAgent, middleware, spawn, callOptionsSchema + prepareCall | | Per-call typed options (v7) | /agent | callOptionsSchemaprepareCall for runtime model/instructions/tools | | Self-improvement (Hermes pattern) | /agent/self-improvement | Background review fork that turns agents into learning agents | | Client-side tool type safety | /agent/infer-ui-message | InferArcAgentUIMessage<typeof agent> for useChat<>() | | Persistent memory (multi-tenant) | /brain | BrainManager, memoryScope, staleness caveats, cleanup | | Memory as AI SDK tools | /brain/tools | brainTools(brain, { scope }){ read_memory, write_memory, forget_memory } | | Anthropic memory adapter | /brain/anthropic-memory-adapter | anthropicMemoryAdapter(brain, { scope }) for memory_20250818 | | Sub-agents | /spawn | spawnAgent(child) — child agent as a tool, full UIMessage stream | | Chat stream endpoint | /session/chat-stream | createChatStream — multimodal-aware, project/folder scoping | | Multi-provider prompt caching | /caching/* | Anthropic + Bedrock + OpenAI + Google in one helper | | Multimodal attachments + RAG | /attachments/* | Direct-to-provider files, vector store, chunker, retriever | | Provider-agnostic tools | /tools | providerTools.webSearch() resolves per provider | | Image generation + view | /tools | imageGenerationTool, viewImageTool (vision-capable) | | JSONValue-safe tool outputs | /tools/json-safe, /tools/wrap-output-json-safe | Auto-coerce Date / ObjectId / Buffer / Map / Set / bigint so v7 convertToModelMessages doesn't crash | | Backend-agnostic filesystem tools | /tools/filesystem | Claude-Code-style read/write/edit/glob/grep | | Shell tool + sandbox adapter | /tools/shell/* | ShellExecutor interface + Node + sandbox impls | | Structured edits | /tools/structured-edit/* | smart_edit + multi_edit + apply_patch (V4A) | | Question / ask-the-user tool | /tools/question/* | HITL inbox + AI SDK tool factory | | MCP servers as tools | /mcp | loadMcpConfig('.mcp.json') | | Tool output storage | /tools/output-storage/* | Locator-based persistence, in-memory + S3 | | Mid-loop message injection | /messaging/* | Queue, UI injection, event bridge, Redis | | Permissions + approval | /permissions, /approval | 4-layer policy (allow/ask/deny/deny-always) | | Sandbox abstraction | /sandbox/* | Sandbox contract + in-memory / local-process / E2B / Vercel adapters | | Guardrails (input/output/step) | /guardrails/* | Regex, keyword-deny, max-length, Zod schema, llm-as-judge | | Agent-to-agent handoffs | /handoffs/* | First-class routing + history filters + nested-history summariser | | Swarm coordination | /swarm/* | Agents that share context + hand off via shared bus events | | Orchestration patterns | /orchestration/* | Concurrent / mixture-of-agents / director / keepalive | | Runs (audit ledger) | /runs/* | Canonical queryable RunRecord audit trail via onStepFinish/onFinish | | Run-state machine | /run-state/* | Idle / awaiting_question / awaiting_approval / paused / completed / etc. | | Event bus | /bus/* | Typed cross-subsystem observability bus + per-source bridges | | Tracing (OTel + console) | /tracing/* | Bus-driven span export; ConsoleTracingBridge (dev) + OtelBridge (peer) | | Checkpoint (state branching) | /checkpoint/* | Point-in-time agent state for HITL / eval / branching | | UI streaming primitives | /ui | composeStream, createUIMessageStream re-exports | | Model middleware | /middleware | wrapModel, extractReasoning, defaultSettings | | Model registry / resolution | /registry/* | resolveModel(spec, { registry }) for string-routed multi-tenant configs | | Serverless-safe stream drainers | /stream/* | consumeAgentStream, consumeChatStream for Trigger/Inngest/Temporal | | Streamline integration | /integrations/streamline | Durable-workflow bridge (peer: @classytic/streamline) | | Usage / cost / stop conditions | /usage, /usage/accumulate | Per-request token+cost accumulation, costExceeds / tokenBudget | | Skills | /skills, /skills/manage-tool, /skills/parse-frontmatter, /skills/curator | Markdown skills loaded into agents, manage-skill tool, curator review | | Test contracts | /testing, /testing/*-contract | Mock models + reusable store / sandbox / filesystem contracts | | Mongo stores | /stores/mongo/* | Brain, Conversation, Metadata, Agent, Skill, Vector | | SQLite stores | /stores/sqlite/* | Brain, Conversation (drizzle-orm + sqlitekit) | | S3-decorated brain + tool output | /stores/s3/* | Content→S3, metadata→delegate |

Multi-tenant memory (the typical app case)

Same agent, many companies, no cross-tenant leaks:

import { BrainManager, memoryScope } from '@classytic/arc-ai/brain';
import { MongoBrainStore } from '@classytic/arc-ai/stores/mongo/brain';

const brain = new BrainManager({
  store: new MongoBrainStore(),
  staleThresholdDays: 14,
});

// Write: most-specific scope the app knows
await brain.remember({
  type: 'feedback',
  name: 'tone',
  content: `Be formal.\n**Why:** Enterprise customer.\n**How to apply:** Every reply.`,
  scope: memoryScope.agent(req.user.companyId, 'support'),
});

// Read: hierarchical — agent + user + company + global, newest wins
const ctx = await brain.assembleContext(userPrompt, {
  scope: memoryScope.hierarchy({
    companyId: req.user.companyId,
    agentSlug: 'support',
    userId: req.user.id,
  }),
});

// Offboard — one call, subtree wipe, global untouched
await brain.forgetScope(
  memoryScope.hierarchy({
    companyId: offboardedCompanyId,
    includeGlobal: false,
  }),
);

Chat endpoint (one call, whole turn)

import { createChatStream }   from '@classytic/arc-ai/session/chat-stream';
import { SessionManager }     from '@classytic/arc-ai/session/session-manager';

const { response } = await createChatStream({
  agent, brain, session,
  message: req.body.message,
  agentSlug: 'support',
  userId: req.user.id,
  organizationId: req.user.companyId,
  projectId: req.body.projectId,     // indexed; cheap list queries
  folderPath: req.body.folderPath,   // indexed; prefix match
});
return response;   // SSE Web Response, x-conversation-id header set

Docs

docs/ — task-oriented, token-optimized. Nextra-ready .mdx.

| # | Topic | |---|---| | 1 | Quickstart | | 2 | Agents — createAgent, middleware, hooks, spawn, reasoning | | 3 | Memory — BrainManager, scope, cleanup, multi-tenant | | 4 | Sessions — chat stream, project/folder scoping | | 5 | Tools — providerTools, filesystem, MCP | | 6 | Messaging & UI — queue, UI injection, composeStream | | 7 | Testing — mock models, FS contract, store contracts | | 8 | Mongo Stores — mongokit, defineResource, cleanup | | 9 | Group Chats — visibility, participants, mentions, ACL | | 10 | Prompt Caching — multi-provider, tool defs, composition | | 11 | Patterns — composing prepareStep helpers + queue + cache | | 12 | Attachments — multimodal direct-to-provider + vector-search RAG | | 13 | Serverless — drain streams in Trigger / Inngest / Temporal / Lambda | | 14 | SandboxSandbox interface + reference impl | | 15 | Image GenerationimageGenerationTool + storage + viewImageTool | | 16 | SQLite Stores — sqlitekit + drizzle-orm | | 17 | Provider Capabilities — feature matrix per provider | | 18 | Handoffs — agent-to-agent routing, history filters, nested summariser | | 19 | Tracing — bus-driven span export (ConsoleTracingBridge + OtelBridge) | | 20 | Remote Sandboxes — E2B + Vercel Sandbox peer-optional adapters | | 21 | Swarm — coordinated agents over a shared bus | | 22 | Orchestration Patterns — concurrent, mixture-of-agents, director | | 23 | Plan Mode (recipe) — gated planning before execution | | 24 | Streaming + Keepalive — long-running stream survival

Attachments — multimodal + RAG in one module

Two paths share a single subpath family. Direct-to-provider (vision, PDF) goes through extractFileParts + convertToModelMessages; vector-search RAG (chunked + embedded + retrieved) is provider-blind.

import { chunkText }        from '@classytic/arc-ai/attachments/chunk-text';
import { embedTexts }       from '@classytic/arc-ai/attachments/embed-texts';
import { InMemoryVectorStore } from '@classytic/arc-ai/attachments/vector-store';
import { retrieveChunks, formatChunksForPrompt }
                            from '@classytic/arc-ai/attachments/retrieve-chunks';
import { openai }           from '@ai-sdk/openai';

const chunks = chunkText(documentText);
const { embeddings } = await embedTexts({
  model: openai.embedding('text-embedding-3-small'),
  values: chunks.map((c) => c.content),
});

const store = new InMemoryVectorStore();
await store.upsert(chunks.map((c, i) => ({
  id: `${fileId}:${c.index}`, scope: `co:${companyId}`, fileId,
  chunkIndex: c.index, content: c.content, embedding: embeddings[i]!,
})));

const hits = await retrieveChunks({
  store, embeddingModel: openai.embedding('text-embedding-3-small'),
  query: userMessage, scope: `co:${companyId}`,
});

const ragSystemBlock = formatChunksForPrompt(hits);

Direct-to-provider needs no glue beyond createChatStream — it already routes file parts through convertToModelMessages. For persistent provider files (Anthropic + OpenAI Files API) use /attachments/upload-to-provider to get back a stable ProviderFileReference.

When NOT to use arc-ai

arc-ai complements these. It does not replace them.

Requirements

Node.js 22+ · TypeScript 6+ · ESM-only · AI SDK 7.0+ · zod 4+

License

Proprietary — © Classytic. All rights reserved. See LICENSE.

The published npm package (@classytic/arc-ai) is free to install and use in your applications. The source code is not open source; redistribution, modification, or re-publication of the source is not permitted without prior written permission.