@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
createChatControllerwithout 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/coreMost feature packages already depend on core; you add it explicitly when authoring libraries or sharing types.
Public exports (overview)
Chat controller and config
| Export | Role |
|---|---|
createChatController | Headless state machine: send, stream, tools, memory, skills, retriever |
Types: ChatConfig, ChatController, ChatState, ChatReturn | Configuration 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
| Export | Role |
|---|---|
buildMessage | Construct a typed Message |
consumeStream | Drive StreamSource → chunks + completion |
createEventEmitter | Internal event bus for observers |
executeToolCall | Run a tool from a ToolCall payload |
safeParseArgs | Parse JSON tool arguments safely |
createToolLifecycle | init / dispose for tools |
generateId | Stable IDs for messages and calls |
Agent loop helpers
| Export | Role |
|---|---|
buildToolMap | Name → ToolDefinition map |
activateSkills | Merge skill system prompts and skill-provided tools |
executeSafeTool | Guarded execution (confirmation hooks, errors) |
Memory and RAG (lightweight)
| Export | Role |
|---|---|
createInMemoryMemory, createLocalStorageMemory | Simple bundled memories for tests or demos |
serializeMessages / deserializeMessages | Persistence helpers |
createStaticRetriever, formatRetrievedDocuments | Retriever helpers for static context |
Heavy backends live in @agentskit/memory; vector stores and chunking in @agentskit/rag.
Error handling
| Export | Role |
|---|---|
AgentsKitError | Base error class with code, hint, and docsUrl fields |
AdapterError | Thrown on adapter/stream failures; links to adapter docs |
ToolError | Thrown on tool lookup or execution failures; links to tool docs |
MemoryError | Thrown on memory load/save/deserialize failures; links to memory docs |
ConfigError | Thrown on invalid configuration; links to configuration docs |
ErrorCodes | as const map of all AK_* error code strings |
See Error handling below for usage examples.
Tool factory
| Export | Role |
|---|---|
defineTool | Create a ToolDefinition with automatic type inference from a JSON Schema |
DefineToolConfig | Config type for defineTool — schema is narrowed to a const type |
InferSchemaType | Utility 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'| Class | Thrown when |
|---|---|
AgentsKitError | Base class — all errors extend this |
AdapterError | Adapter is missing or a stream call fails |
ToolError | A tool is not found or its execute throws |
MemoryError | Memory load, save, or deserialization fails |
ConfigError | Required 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/adaptersErrorCodes 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 configCatching 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
| Issue | Mitigation |
|---|---|
| Type errors after upgrade | Pin all @agentskit/* to the same semver; core types move with the ecosystem. |
createChatController vs useChat | Controller is framework-agnostic; React hook adds state binding and Strict Mode safety. |
| Bundle size concerns | Tree-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.