Skip to main content
Alpha

@netscript/ai

The provider-agnostic AI engine core for NetScript: a composition root, a global model registry, the domain vocabulary and capability ports for chat/embeddings/vision/tools/agents/MCP, and a set of opt-in provider adapters. This page is generated from the package's public surface with deno doc (US-2). For the full index of packages and plugins return to the reference overview.

The base @netscript/ai entrypoint takes no @netscript/* runtime dependency and pulls no provider SDK into the module graph. Provider adapters (Anthropic, OpenAI-compatible, OpenRouter, Ollama, OpenAI embeddings/vision) live on separate subpath exports and self-register into the shared registry as a side effect of being imported — so an application chooses its providers with one-line side-effect imports and only those SDKs enter the graph:

import "@netscript/ai/anthropic"; // self-registers the 'anthropic' provider
import { getModel } from "@netscript/ai";

const handle = await getModel("anthropic:claude-sonnet-4-5");

Export map

The package publishes the following entrypoints. Each is generated from its own deno doc surface.

Export Entrypoint Purpose
@netscript/ai ./mod.ts Composition root (createAiRuntime / getAiRuntime) and the model registry accessors.
@netscript/ai/contracts ./src/contracts/mod.ts Domain vocabulary: messages, content parts, model identity, agent chunks, usage, errors.
@netscript/ai/ports ./src/ports/mod.ts Capability port interfaces, their no-op/unconfigured defaults, and the provider registries.
@netscript/ai/anthropic ./anthropic.ts Anthropic model provider (wraps @tanstack/ai-anthropic).
@netscript/ai/openai-compatible ./openai-compatible.ts OpenAI-compatible model provider (any base URL / key / model list).
@netscript/ai/openrouter ./openrouter.ts OpenRouter model provider with reasoning-effort passthrough.
@netscript/ai/ollama ./ollama.ts Local Ollama model provider with a reachability preflight.
@netscript/ai/openai-embeddings ./openai-embeddings.ts OpenAI-compatible embeddings and vision provider.
@netscript/ai/tools ./tools.ts Standard-Schema tool definitions, in-memory registry, and the render_ui wire contract.
@netscript/ai/agent ./agent.ts The E3 agent loop, typestate, and history strategies.
@netscript/ai/mcp ./mcp.ts MCP transports (stdio, Streamable-HTTP), auth modes, and tool registration.
@netscript/ai/testing ./src/testing/mod.ts Deterministic fakes for downstream unit tests.

Composition root and model registry (@netscript/ai)

The root entrypoint is the composition root plus the model-registry accessors. Model providers are resolved through a module-level registry (not stored on the runtime), so provider packages self-register independently of runtime construction.

Symbol Kind Signature Description
createAiRuntime function createAiRuntime(config?: AiRuntimeConfig): AiRuntime Compose a runtime, defaulting every unspecified port. Pure wiring — no IO, no global mutation.
getAiRuntime function getAiRuntime(config?: AiRuntimeConfig): AiRuntime Lazy process singleton (shaped like @netscript/kv's getKv()); config is used only on first call.
isAiRuntimeInitialized function isAiRuntimeInitialized(): boolean Whether the singleton has been constructed.
resetAiRuntime function resetAiRuntime(): void Clear the singleton (test isolation).
registerModelProvider function registerModelProvider(id, factory): void Register a provider factory under an id (re-registering overwrites).
getModelProvider function getModelProvider(id, config?): ModelProviderPort Resolve a fresh provider instance, or throw ModelProviderNotFoundError.
getModel function getModel(ref: ModelRef, config?): Promise<ModelHandle> Resolve a "<provider>:<model>" ref (or ModelSelector) end-to-end.
listModelProviders function listModelProviders(): readonly string[] Ids of all currently-registered providers.
resetModelRegistry function resetModelRegistry(): void Clear the provider registry (test isolation).
getEmbeddingProvider / getVisionProvider function (id, config?) => …ProviderPort Resolve a registered embedding / vision provider.
registerEmbeddingProvider / registerVisionProvider function (id, factory) => void Register an embedding / vision provider factory.
listEmbeddingProviders / listVisionProviders function () => readonly string[] Ids of registered embedding / vision providers.
resetEmbeddingRegistry / resetVisionRegistry function () => void Clear the embedding / vision registries (test isolation).
AiRuntime interface - Composed runtime: resolved ports plus getModelProvider / getModel bound to the default provider.
AiRuntimeConfig interface - Optional ports injected into createAiRuntime; each omitted capability falls back to its default.
ModelProviderPort interface - A concrete model backend (listModels / getModel / supports / optional createChatClient).
ModelProviderConfig type alias Readonly<Record<string, unknown>> Opaque, provider-defined config bag passed to a provider factory.
ModelHandle / ModelRef type alias - Resolved model (descriptor + provider id) and its "<provider>:<model>"-or-selector reference.
AiError class - Base error for the AI stack.
AiNotConfiguredError class - Thrown when a capability/provider is used without required configuration.
ModelProviderNotFoundError class - Thrown when a ref names an unregistered provider id.

Runtime capability ports and their defaults

createAiRuntime injects each capability port, defaulting any omitted field to a no-op or a throwing "unconfigured" port. Model providers are not on the runtime — they are resolved from the global registry.

AiRuntimeConfig field Port Default when omitted
telemetry TelemetryPort No-op (createNoopTelemetryPort).
tools ToolRegistryPort No-op (createNoopToolRegistry).
embeddings EmbeddingProviderPort Throwing unconfigured port.
vision VisionProviderPort Throwing unconfigured port.
mcp McpTransportPort Throwing unconfigured port.
skills SkillLoaderPort No-op returning no skills.
agentLoop AgentLoopPort Throwing unconfigured port.
memory AgentMemoryPort No-op store.
defaultModelProvider string Unset — getModelProvider() then requires an explicit id.

Domain contracts (@netscript/ai/contracts)

The provider-neutral vocabulary. The tables below list the primary surface; the module is the source of truth via deno doc packages/ai/src/contracts/mod.ts.

Group Symbols
Messages Message, MessageRole, MessageContent, ContentPart, TextContentPart, ImageContentPart, AudioContentPart, VideoContentPart, DocumentContentPart, ContentModality, ContentSource, DataContentSource, UrlContentSource
Model identity ModelId, ModelDescriptor, ModelCapabilities, ModelSelector, ModelRef, ModelHandle
Agent stream chunks AgentChunk, AgentChunkType, TextChunk, ToolCallChunk, ToolResultChunk, MessageChunk, UsageChunk, ErrorChunk, DoneChunk
Tools ToolDescriptor, ToolParameters, ToolCall, ToolResult, ToolCallState, ToolResultState, ToolInputIssue, JsonSchema, RenderUiToolDescriptor, RenderUiResult, UiResource
Usage Usage, UsageCostBreakdown, PromptTokensDetails, CompletionTokensDetails, ProviderUsageDetails
Errors AiError, AiNotConfiguredError, InvalidModelRefError, ModelProviderNotFoundError, ToolNotFoundError, ToolInputValidationError

Capability ports (@netscript/ai/ports)

The capability seams the engine is programmed against, their default implementations, and the model/embedding/vision registries. Primary surface:

Group Symbols
Model registry registerModelProvider, getModelProvider, getModel, parseModelRef, listModelProviders, isModelProviderRegistered, resetModelRegistry, ModelProviderPort, ModelProviderFactory, ModelProviderConfig
Embedding / vision registries registerEmbeddingProvider, getEmbeddingProvider, listEmbeddingProviders, isEmbeddingProviderRegistered, resetEmbeddingRegistry, registerVisionProvider, getVisionProvider, listVisionProviders, isVisionProviderRegistered, resetVisionRegistry
Chat ChatClientPort, ChatModelProviderPort, ChatClientRequest, ChatClientCallOptions, ChatClientEvent, ChatTextEvent, ChatToolCallEvent, ChatFinishEvent, ChatErrorEvent, ChatFinishReason
Embeddings / vision EmbeddingProviderPort, EmbeddingCallOptions, EmbeddingResponse, VisionProviderPort, VisionCallOptions, VisionResponse
Agent AgentLoopPort, AgentLoopInput, AgentLoopOptions, AgentMemoryPort, MemoryRecord, RecallQuery, RecallResult
Tools / skills / telemetry ToolRegistryPort, ToolHandler, SkillLoaderPort, SkillDescriptor, TelemetryPort, TelemetrySpan, TelemetryAttributes, TelemetryAttributeValue
MCP McpTransportPort, McpTransportKind, McpConnectorConfig, McpClientConnection, McpConnectOptions, McpConnectionState, McpAuthConfig, McpAuthMode, McpToolRegistry, McpToolDescriptor, McpToolResult
Reachability ReachabilityPort, ReachabilityCheckOptions, ReachabilityResult, createAssumeReachablePort
Default factories createNoopTelemetryPort, createNoopToolRegistry, createNoopSkillLoader, createNoopAgentMemory, createUnconfiguredAgentLoop, createUnconfiguredEmbeddingProvider, createUnconfiguredVisionProvider, createUnconfiguredMcpTransport

Model providers

Each provider lives on its own subpath. Importing the subpath self-registers the provider under its stable id and re-exports the adapter class and config type for direct construction. All chat adapters translate the wrapped SDK to the owned chat vocabulary — no provider-SDK type escapes the public surface — and support per-turn cancellation through the chat client's stream(_, { signal }) option.

@netscript/ai/anthropic

Registry id "anthropic". Wraps @tanstack/ai-anthropic; the model catalog is taken verbatim from the wrapped package's ANTHROPIC_MODELS.

Symbol Kind Description
AnthropicModelProvider class ModelProviderPort backed by @tanstack/ai-anthropic.
ANTHROPIC_PROVIDER_ID variable "anthropic".
AnthropicModelProviderConfig interface Provider configuration (below).
Config field Type Default
apiKey string Falls back to the ANTHROPIC_API_KEY environment variable at client construction.
baseURL string Anthropic default (override to route through a gateway/proxy).

@netscript/ai/openai-compatible

Registry id "openai-compatible". Wraps @tanstack/ai-openai/compatible for any endpoint that speaks the OpenAI wire (its own base URL, key, and model list).

Symbol Kind Description
OpenAiCompatibleModelProvider class ModelProviderPort backed by @tanstack/ai-openai/compatible.
OPENAI_COMPATIBLE_PROVIDER_ID variable "openai-compatible".
OpenAiCompatibleModelProviderConfig interface Provider configuration (below).
OpenAiCompatibleApi type alias "chat-completions" | "responses".
Config field Type Default
baseURL string Required to construct a client (e.g. https://api.deepseek.com/v1).
apiKey string Required to construct a client. No environment fallback — pass it yourself.
models readonly string[] Empty; when unset the provider is optimistic (supports returns true).
api OpenAiCompatibleApi "chat-completions".
name string "openai-compatible".

When baseURL or apiKey is missing, createChatClient throws AiNotConfiguredError (the provider still lists and reports its configured models).

@netscript/ai/openrouter

Registry id "openrouter". Reuses the OpenAI-compatible transport pinned to OpenRouter, with the one wire divergence being reasoning: OpenRouter expects a top-level reasoning: { effort } object.

Symbol Kind Description
OpenRouterModelProvider class ModelProviderPort pinned to the OpenRouter endpoint.
OPENROUTER_PROVIDER_ID variable "openrouter".
DEFAULT_OPENROUTER_BASE_URL variable "https://openrouter.ai/api/v1".
OPENROUTER_API_KEY_ENV variable "OPENROUTER_API_KEY" — the env var read when apiKey is omitted.
openRouterReasoningModelOptions function Pure normalizer: ReasoningEffort{ reasoning: { effort } } (or undefined).
OpenRouterModelProviderConfig interface Provider configuration (below).
ReasoningEffort type alias "low" | "medium" | "high".
Config field Type Default
apiKey string Falls back to the OPENROUTER_API_KEY environment variable. createChatClient throws AiNotConfiguredError when neither is present.
baseURL string https://openrouter.ai/api/v1.
models readonly string[] Empty; optimistic supports when unset.
reasoningEffort ReasoningEffort Unset — no reasoning object emitted.

@netscript/ai/ollama

Registry id "ollama". Reuses the OpenAI-compatible transport pinned to a local Ollama daemon at {host}/v1, with a reachability preflight and a placeholder key (Ollama ignores authorization).

Symbol Kind Description
OllamaModelProvider class ModelProviderPort for a local Ollama daemon; exposes checkReachable().
OLLAMA_PROVIDER_ID variable "ollama".
DEFAULT_OLLAMA_HOST variable "http://localhost:11434".
createHttpReachabilityPort / HttpReachabilityAdapter function / class Fetch-backed probe of GET {host}/api/tags.
DEFAULT_REACHABILITY_PATH variable Default probe path.
createAssumeReachablePort function A port that reports reachable without probing (tests).
OllamaModelProviderConfig interface Provider configuration (below).
ReachabilityPort / ReachabilityCheckOptions / ReachabilityResult interface Reachability seam and its non-throwing result.
Config field Type Default
host string http://localhost:11434.
models readonly string[] Empty; optimistic supports when unset.
reachability ReachabilityPort Fetch-backed probe of GET {host}/api/tags.
fetch typeof fetch Global fetch (override for the default probe in tests).

@netscript/ai/openai-embeddings

Registry id "openai-embeddings", registered for both the embedding and vision capabilities. Speaks the OpenAI-compatible HTTP API directly with Web fetch (no provider SDK).

Symbol Kind Description
OpenAiEmbeddingsProvider class Implements EmbeddingProviderPort (embed) and VisionProviderPort (analyze).
OPENAI_EMBEDDINGS_PROVIDER_ID variable "openai-embeddings".
DEFAULT_OPENAI_EMBEDDING_MODEL variable "text-embedding-3-small".
DEFAULT_OPENAI_VISION_MODEL variable "gpt-4o-mini".
OpenAiEmbeddingsProviderConfig interface Provider configuration (below).
Config field Type Default
apiKey string Required; sent as a bearer token. No environment fallback. embed / analyze throw AiNotConfiguredError when absent.
baseURL string https://api.openai.com/v1.
embeddingModel string text-embedding-3-small.
visionModel string gpt-4o-mini.
fetch typeof fetch Global fetch (override in tests).

Tools (@netscript/ai/tools)

Define server-executable (or client-deferred) tools, validate their input with Standard Schema (bring any conforming schema — zod, valibot, arktype, or hand-written), and dispatch them through an in-memory registry that satisfies ToolRegistryPort. The core adds no schema DSL and takes no @netscript/* dependency.

Symbol Kind Description
defineAiTool function Start a tool definition chain (.parameters(...).input(schema).server(handler)).
createToolRegistry function Build an in-memory registry from tool definitions.
renderUiTool variable Built-in render_ui wire contract (input schema + metadata only, no renderer).
AiToolRegistry interface Registry surface extending ToolRegistryPort.
AiToolBuilder / AiToolBuilderWithInput interface Typestate builder surfaces.
AiToolDefinition interface A defined tool (input/output typed).
AiToolExecutionResult interface Result of a dispatch (output, or deferred for client tools).
AiToolInvocationContext interface Context passed to a server handler.
AiToolServerHandler type alias The server execution function.
AiToolExecutionKind type alias "server" | "client".
RenderUiToolInput interface Input shape of the render_ui contract.
ToolInputValidationError class Thrown when a tool's input fails schema validation.

Agent loop (@netscript/ai/agent)

The E3 agent loop drives a bounded, cancellable model/tool interaction and emits AgentChunks. It consumes its collaborators purely by factory injection — importing this subpath pulls no provider SDK.

Symbol Kind Description
createAgentLoop function Construct a loop from AgentLoopDeps (a ChatModelProviderPort, a ToolRegistryPort, an optional history strategy).
DEFAULT_MAX_STEPS variable Default step ceiling for a run.
slidingWindowHistory function A HistoryStrategy that keeps the last N messages.
DEFAULT_HISTORY_WINDOW variable Default window used by slidingWindowHistory.
SlidingWindowOptions interface { maxMessages } for the sliding-window strategy.
HistoryStrategy interface History-trimming seam.
isTerminalState function Narrow an AgentLoopState to a terminal state.
AgentLoopState type alias "idle" | "running" | "awaiting-tool" | "done" | "aborted" | "errored".
TerminalAgentLoopState type alias "done" | "aborted" | "errored".
AgentMaxStepsExceededError class Thrown when a run exceeds its step ceiling.

The subpath also re-exports the seams the loop is programmed against (AgentLoopPort, ChatClientPort / ChatModelProviderPort and their event types, ToolRegistryPort) so it is a self-contained wiring surface.

MCP (@netscript/ai/mcp)

MCP transport adapters and tool registration: stdio, reconnectable Streamable-HTTP, injected auth modes, and lifecycle state.

Symbol Kind Description
createMcpTransport function Build a transport from McpTransportConfig (kind: "stdio" or "streamable-http").
registerMcpTools function Discover and register a transport's tools into a ToolRegistry.
StdioMcpTransport / StdioMcpTransportConfig class / interface Stdio transport and its config.
StreamableHttpMcpTransport / StreamableHttpMcpTransportConfig class / interface Reconnectable Streamable-HTTP transport and its config.
McpTransportPort interface The transport seam.
McpAuthConfig / McpAuthMode type alias Injected auth: "none", "api-token", or "oauth".
McpConnectionState type alias "disconnected" | "connecting" | "connected" | "reconnecting" | "closed".
McpToolRegistration / McpToolDescriptor / McpToolResult interface Registration and tool-call vocabulary.

Testing (@netscript/ai/testing)

Deterministic fakes for unit-testing code built on the ports. This subpath is excluded from the provider dependency graph.

Symbol Kind Description
createFakeModelProvider function A ModelProviderPort over a fixed descriptor list.
createFakeChatModelProvider function A chat provider that replays scripted turns of ChatClientEvents.
createFakeEmbeddingProvider function An EmbeddingProviderPort returning a fixed vector.
createFakeVisionProvider function A VisionProviderPort returning fixed text.
createFakeAgentLoop function An AgentLoopPort that yields a fixed AgentChunk[].
createFakeAgentMemory function An AgentMemoryPort with toggleable recall.
createFakeTelemetryPort function A recording TelemetryPort (FakeTelemetryPort).
createInMemoryToolRegistry function A ToolRegistryPort for tests.

Configuration

@netscript/ai reads no @netscript/* config surface — capabilities are wired through AiRuntimeConfig (see runtime capability ports) and providers through their config bags. Two adapters resolve an API key from the environment when apiKey is omitted:

Environment variable Read by When
ANTHROPIC_API_KEY @netscript/ai/anthropic When apiKey is omitted (via the wrapped @tanstack/ai-anthropic client).
OPENROUTER_API_KEY @netscript/ai/openrouter When apiKey is omitted (exported as OPENROUTER_API_KEY_ENV).

The openai-compatible, openai-embeddings, and ollama providers do not read the environment. Pass apiKey (and baseURL/host) explicitly — commonly from Deno.env.get(...) in your composition code. Reading a key from the environment requires --allow-env for the variable in question.

Examples

Compose a runtime

import { createAiRuntime } from "@netscript/ai";

const ai = createAiRuntime();
// Telemetry defaults to a no-op port — safe to call with nothing wired.
ai.telemetry.recordEvent("agent.start");

Register a provider and resolve a model

import "@netscript/ai/anthropic"; // self-registers the 'anthropic' provider
import { getModel } from "@netscript/ai";

const handle = await getModel("anthropic:claude-sonnet-4-5");

Configure an OpenAI-compatible endpoint

import "@netscript/ai/openai-compatible"; // self-registers the provider
import { getModelProvider } from "@netscript/ai";

const provider = getModelProvider("openai-compatible", {
  baseURL: "https://api.deepseek.com/v1",
  apiKey: Deno.env.get("DEEPSEEK_KEY"),
  models: ["deepseek-chat", "deepseek-reasoner"],
});

Stream a reasoning turn through OpenRouter

import "@netscript/ai/openrouter"; // self-registers the provider
import { getModelProvider } from "@netscript/ai";

const provider = getModelProvider("openrouter", {
  apiKey: Deno.env.get("OPENROUTER_API_KEY"),
  models: ["anthropic/claude-sonnet-4.5"],
  reasoningEffort: "high",
});

Preflight a local Ollama daemon

import "@netscript/ai/ollama"; // self-registers the provider
import { getModelProvider } from "@netscript/ai";

const provider = getModelProvider("ollama", { models: ["llama3.2"] });
const health = await provider.checkReachable();
if (!health.reachable) {
  console.warn(`Ollama is down: ${health.detail}`);
}

Define, register, and dispatch a tool

import { createToolRegistry, defineAiTool } from "@netscript/ai/tools";

const add = defineAiTool("add")
  .parameters({
    type: "object",
    properties: { a: { type: "number" }, b: { type: "number" } },
    required: ["a", "b"],
  })
  .input(myAddSchema) // any StandardSchemaV1<unknown, { a: number; b: number }>
  .server(({ a, b }) => ({ sum: a + b }));

const registry = createToolRegistry([add]);
const { output } = await registry.dispatch("add", { a: 2, b: 3 });

Drive a bounded, cancellable agent loop

import { createAgentLoop, slidingWindowHistory } from "@netscript/ai/agent";

const loop = createAgentLoop({
  modelProvider, // a ChatModelProviderPort
  tools, // a ToolRegistryPort
  history: slidingWindowHistory({ maxMessages: 12 }),
});

for await (const chunk of loop.run({ model: "anthropic:claude-sonnet-4-5", messages })) {
  if (chunk.type === "text") console.log(chunk.delta);
  if (chunk.type === "done") console.log(chunk.usage);
}

Register MCP tools over Streamable-HTTP

import { createMcpTransport, registerMcpTools } from "@netscript/ai/mcp";
import { createToolRegistry } from "@netscript/ai/tools";

const transport = createMcpTransport({
  kind: "streamable-http",
  serverId: "search",
  url: "https://mcp.example.com",
  auth: { mode: "api-token", token: "injected-at-runtime", scheme: "Bearer" },
});

const registry = createToolRegistry();
await registerMcpTools(registry, transport);

Back to the reference overview.