agentskit.js
Packages

@agentskit/core

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 adapt

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
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 configuration docs
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,
  ErrorCodes,
} from '@agentskit/core'
ClassThrown when
AgentsKitErrorBase class — all errors extend this
AdapterErrorAdapter is missing or a stream call fails
ToolErrorA tool is not found or its execute throws
MemoryErrorMemory load, save, or deserialization fails
ConfigErrorRequired configuration is absent or invalid

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: openaiAdapter() })
  --> Docs: https://www.agentskit.io/docs/adapters

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_MEMORY_LOAD_FAILED      // memory.load() failed
ErrorCodes.AK_MEMORY_SAVE_FAILED      // memory.save() failed
ErrorCodes.AK_MEMORY_DESERIALIZE_FAILED // corrupt persisted state
ErrorCodes.AK_CONFIG_INVALID          // missing or bad config

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 · useStream · useReactive

Stability

  • Version: 1.6.1
  • Tier: stable
  • Contract: frozen
  • Roadmap: see packages roadmap for what this package needs to reach v1.0.
✎ Edit this page on GitHub·Found a problem? Open an issue →·How to contribute →

On this page