agentskit.js
Packages

@agentskit/core

Shared contract layer — TypeScript types, headless chat controller, stream helpers. Zero-dep, under 10 KB gzipped.

The shared contract layer for AgentsKit: TypeScript types, the headless chat controller, stream helpers, and building blocks used by @agentskit/react, @agentskit/ink, @agentskit/runtime, and adapters. No third-party runtime dependencies — keep this package small and stable.

#When to use

  • You implement a custom adapter, tool, memory, or UI on top of official types.
  • You need createChatController without React (advanced integrations).
  • You want to understand messages, tool calls, and stream chunks across the ecosystem.

You usually do not import core directly in a typical React app except for types — prefer useChat and @agentskit/react.

#Install

npm install @agentskit/core

Most feature packages already depend on core; you add it explicitly when authoring libraries or sharing types.

#Public exports (overview)

#Chat controller and config

ExportRole
createChatControllerHeadless state machine: send, stream, tools, memory, skills, retriever
Types: ChatConfig, ChatController, ChatState, ChatReturnConfiguration and controller shape

The controller merges system prompts, runs retrieval, dispatches tool calls, persists via ChatMemory, and exposes subscribe/update patterns consumed by UI packages.

#Primitives and streams

ExportRole
buildMessageConstruct a typed Message
consumeStreamDrive StreamSource → chunks + completion
createEventEmitterInternal event bus for observers
executeToolCallRun a tool from a ToolCall payload
safeParseArgsParse JSON tool arguments safely
createToolLifecycleinit / dispose for tools
generateIdStable IDs for messages and calls

#Agent loop helpers

ExportRole
buildToolMapName → ToolDefinition map
activateSkillsMerge skill system prompts and skill-provided tools
executeSafeToolGuarded execution (confirmation hooks, errors)

#Memory and RAG (lightweight)

ExportRole
createInMemoryMemory, createLocalStorageMemorySimple bundled memories for tests or demos
serializeMessages / deserializeMessagesPersistence helpers
validateMemoryRecord from @agentskit/core/memory-validationBounded runtime validation for untrusted serialized messages
createStaticRetriever, formatRetrievedDocumentsRetriever helpers for static context

Heavy backends live in @agentskit/memory; vector stores and chunking in @agentskit/rag.

#Error handling

ExportRole
AgentsKitErrorBase error class with code, hint, and docsUrl fields
AdapterErrorThrown on adapter/stream failures; links to adapter docs
ToolErrorThrown on tool lookup or execution failures; links to tool docs
MemoryErrorThrown on memory load/save/deserialize failures; links to memory docs
ConfigErrorThrown on invalid configuration; links to error handling
ErrorCodesas const map of all AK_* error code strings

See Error handling below for usage examples.

#Tool factory

ExportRole
defineToolCreate a ToolDefinition with automatic type inference from a JSON Schema
DefineToolConfigConfig type for defineTool — schema is narrowed to a const type
InferSchemaTypeUtility type: extract TypeScript args type from a JSON Schema

See Type-safe tools with defineTool below.

#Types (high level)

AdapterFactory, StreamSource, StreamChunk, Message, ToolDefinition, ToolCall, SkillDefinition, ChatMemory, Retriever, VectorMemory, Observer, AgentEvent, and related types — full signatures in TypeDoc (below).

#Example: inspect types in a custom tool

import type { ToolDefinition, ToolExecutionContext } from '@agentskit/core'

export const myTool: ToolDefinition = {
  name: 'greet',
  description: 'Greets a user by name.',
  schema: {
    type: 'object',
    properties: { name: { type: 'string' } },
    required: ['name'],
  },
  async execute(args: Record<string, unknown>, _ctx: ToolExecutionContext) {
    const name = String(args.name ?? 'world')
    return `Hello, ${name}!`
  },
}

#Example: headless controller (advanced)

import { createChatController } from '@agentskit/core'
import { anthropic } from '@agentskit/adapters'

const chat = createChatController({
  adapter: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-sonnet-4-6' }),
})

chat.subscribe(() => {
  console.log(chat.getState().status, chat.getState().messages.length)
})

await chat.send('Hello')

Prefer useChat in React apps — it wraps this pattern with hooks.

#Error handling

AgentsKit uses a didactic error system inspired by the Rust compiler. Every error carries a machine-readable code, a human-readable hint, and a direct link to the relevant docs — so you can fix the problem without searching.

#Error classes

import {
  AgentsKitError,
  AdapterError,
  ToolError,
  MemoryError,
  ConfigError,
  RuntimeError,
  SandboxError,
  SkillError,
  ErrorCodes,
} from '@agentskit/core'
ClassThrown when
AgentsKitErrorBase class — all errors extend this
AdapterErrorAdapter is missing or a stream call fails
ToolErrorA tool is missing, forbidden, invalid, or its execute call fails
MemoryErrorMemory load, save, deserialization, or backend access fails
ConfigErrorRequired configuration is absent or invalid
RuntimeErrorRuntime input, step, or delegation fails
SandboxErrorSandbox policy, backend, or peer setup fails
SkillErrorA skill is invalid or duplicated

#Error shape

class AgentsKitError extends Error {
  readonly code: string       // e.g. 'AK_TOOL_EXEC_FAILED'
  readonly hint: string | undefined   // actionable fix
  readonly docsUrl: string | undefined // direct docs link
  readonly cause: unknown     // original error, if any
}

toString() formats the error Rust-compiler-style:

error[AK_ADAPTER_MISSING]: No adapter provided
  --> Hint: Pass an adapter when creating the chat controller, e.g.
            createChatController({ adapter: openai({ apiKey, model: 'gpt-4o' }) })
  --> Docs: https://www.agentskit.io/docs/data/providers

#ErrorCodes reference

import { ErrorCodes } from '@agentskit/core'

ErrorCodes.AK_ADAPTER_MISSING          // adapter not provided
ErrorCodes.AK_ADAPTER_STREAM_FAILED    // streaming call failed
ErrorCodes.AK_TOOL_NOT_FOUND          // tool name not registered
ErrorCodes.AK_TOOL_EXEC_FAILED        // execute() threw
ErrorCodes.AK_TOOL_PEER_MISSING       // optional tool peer is not installed
ErrorCodes.AK_TOOL_INVALID_INPUT      // tool arguments or proposal are invalid
ErrorCodes.AK_TOOL_QUOTA_EXCEEDED     // tool execution exceeds its quota
ErrorCodes.AK_TOOL_FORBIDDEN          // tool execution is denied by policy
ErrorCodes.AK_MEMORY_LOAD_FAILED      // memory.load() failed
ErrorCodes.AK_MEMORY_SAVE_FAILED      // memory.save() failed
ErrorCodes.AK_MEMORY_DESERIALIZE_FAILED // corrupt persisted state
ErrorCodes.AK_MEMORY_PEER_MISSING     // optional memory backend is not installed
ErrorCodes.AK_MEMORY_REMOTE_HTTP      // remote memory request failed
ErrorCodes.AK_CONFIG_INVALID          // missing or bad config
ErrorCodes.AK_RUNTIME_INVALID_INPUT   // runtime input is invalid
ErrorCodes.AK_RUNTIME_STEP_FAILED     // a runtime step failed
ErrorCodes.AK_RUNTIME_DELEGATE_FAILED // delegated agent execution failed
ErrorCodes.AK_SANDBOX_DENIED          // sandbox policy denied execution
ErrorCodes.AK_SANDBOX_INVALID_TOOL    // tool is invalid for the sandbox
ErrorCodes.AK_SANDBOX_PEER_MISSING    // optional sandbox backend is not installed
ErrorCodes.AK_SANDBOX_BACKEND_FAILED  // sandbox backend failed
ErrorCodes.AK_SKILL_INVALID           // skill definition is invalid
ErrorCodes.AK_SKILL_DUPLICATE         // skill identity is duplicated

RAG loader and reranker errors are package-specific. Import RagError / RagErrorCodes from @agentskit/rag for AK_RAG_LOAD_FAILED, AK_RAG_PEER_MISSING, and AK_RAG_RERANK_FAILED.

#Catching and narrowing errors

import { AgentsKitError, ToolError, ErrorCodes } from '@agentskit/core'

try {
  await runtime.run(task)
} catch (err) {
  if (err instanceof ToolError) {
    if (err.code === ErrorCodes.AK_TOOL_EXEC_FAILED) {
      console.error('Tool execution failed:', err.hint)
      console.error('See:', err.docsUrl)
    }
  } else if (err instanceof AgentsKitError) {
    // any other AgentsKit-originating error
    console.error(err.toString())
  } else {
    throw err // re-throw unknown errors
  }
}

#Throwing in custom tools

When your own tool implementation encounters a recoverable error, wrap it for consistent formatting:

import { ToolError, ErrorCodes } from '@agentskit/core'

export const myTool = {
  name: 'fetch_record',
  async execute(args: { id: string }) {
    const record = await db.find(args.id)
    if (!record) {
      throw new ToolError({
        code: ErrorCodes.AK_TOOL_EXEC_FAILED,
        message: `Record ${args.id} not found`,
        hint: 'Check that the id exists before calling fetch_record.',
        cause: undefined,
      })
    }
    return record
  },
}

#Type-safe tools with defineTool

The defineTool factory infers the TypeScript type of execute's args parameter directly from the JSON Schema you provide — no manual type annotation needed.

import { defineTool } from '@agentskit/core'

const getWeather = defineTool({
  name: 'get_weather',
  description: 'Get the current weather for a city.',
  schema: {
    type: 'object',
    properties: {
      city: { type: 'string', description: 'City name, e.g. "Madrid"' },
      units: { type: 'string', enum: ['metric', 'imperial'] },
    },
    required: ['city'],
  } as const,
  async execute(args) {
    // args.city  → string   (required)
    // args.units → string | undefined  (optional)
    const res = await fetch(`https://wttr.in/${args.city}?format=j1`)
    return res.json()
  },
})

The as const assertion on schema is what enables the inference — without it TypeScript cannot narrow the property types.

#InferSchemaType utility type

When you want to reference the inferred args type outside of defineTool, use InferSchemaType:

import type { InferSchemaType } from '@agentskit/core'

const schema = {
  type: 'object',
  properties: {
    query: { type: 'string' },
    limit: { type: 'integer' },
  },
  required: ['query'],
} as const

type SearchArgs = InferSchemaType<typeof schema>
// { query: string; limit?: number }

#Troubleshooting

IssueMitigation
Type errors after upgradePin all @agentskit/* to the same semver; core types move with the ecosystem.
createChatController vs useChatController is framework-agnostic; React hook adds state binding and Strict Mode safety.
Bundle size concernsTree-shake unused exports; avoid importing server-only utilities in client bundles.

#See also

Start here · Packages · TypeDoc (@agentskit/core) · React · Ink · Adapters · Runtime · Tools · Skills · useChat

#Stability

  • Version: 1.12.8
  • Tier: stable
  • Contract: frozen
  • Roadmap: see packages roadmap for what this package needs to reach v1.0.

Explore nearby

✎ Edit this page on GitHub·Found a problem? Open an issue →·How to contribute →

On this page

Ask the docs
Ask anything about AgentsKit. Answers come from the docs corpus and cite their sources.