Runtime
@agentskit/runtime is the execution engine for autonomous agents. It runs a ReAct loop — observe, think, act — until the model produces a final answer or a step limit is reached.
When to use
- Headless agents (CLI workers, jobs, tests) with tools, memory, retrieval, and optional delegation.
- You already use
@agentskit/adapters; the same factories work here.
For interactive terminal chat prefer @agentskit/ink; for browser UI prefer @agentskit/react.
Install
npm install @agentskit/runtime @agentskit/adapters
@agentskit/core is included transitively; add it explicitly if you need types without pulling the full runtime graph.
Basic usage
import { createRuntime } from '@agentskit/runtime'
import { anthropic } from '@agentskit/adapters'
const runtime = createRuntime({
adapter: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-sonnet-4-6' }),
})
const result = await runtime.run('What is 3 + 4?')
console.log(result.content) // "7"
Demo adapter (no API key)
import { createRuntime } from '@agentskit/runtime'
import { generic } from '@agentskit/adapters'
const runtime = createRuntime({
adapter: generic({ /* custom send/parse */ }),
})
ReAct loop
Each call to runtime.run() enters the following loop:
observe → think → act → observe → ...
- Observe — retrieve context from memory or a retriever and inject it into the prompt.
- Think — send messages + tools to the LLM and stream the response.
- Act — if the LLM calls tools, execute them and append results as
toolmessages. - Repeat until the model returns a plain text response or
maxStepsis reached.
RunResult
runtime.run() resolves to a RunResult object:
interface RunResult {
content: string // Final text response from the model
messages: Message[] // Full conversation including tool calls and results
steps: number // How many loop iterations ran
toolCalls: ToolCall[] // Every tool call made during the run
durationMs: number // Total wall-clock time
}
Example
const result = await runtime.run('List the files in the current directory', {
tools: [shell({ allowed: ['ls'] })],
})
console.log(result.content) // Model's final answer
console.log(result.steps) // e.g. 2
console.log(result.durationMs) // e.g. 1340
result.toolCalls.forEach(tc => {
console.log(tc.name, tc.args, tc.result)
})
RuntimeConfig
interface RuntimeConfig {
adapter: AdapterFactory // Required — the LLM provider
tools?: ToolDefinition[] // Tools available to the agent
systemPrompt?: string // Default system prompt
memory?: ChatMemory // Persist and reload conversation history
retriever?: Retriever // RAG source injected each step
observers?: Observer[] // Event listeners (logging, tracing)
maxSteps?: number // Max loop iterations (default: 10)
temperature?: number
maxTokens?: number
delegates?: Record<string, DelegateConfig>
maxDelegationDepth?: number // Default: 3
}
RunOptions
Override per-call defaults on runtime.run(task, options):
const result = await runtime.run('Summarize this document', {
systemPrompt: 'You are a concise summarizer.',
tools: [readFileTool],
maxSteps: 5,
skill: summarizer,
})
Aborting a run
Pass an AbortSignal to cancel mid-run. The runtime checks the signal before each step and before each tool call.
const controller = new AbortController()
setTimeout(() => controller.abort(), 5000) // cancel after 5 s
const result = await runtime.run('Long running task', {
signal: controller.signal,
})
Memory
When a memory is configured, the runtime saves all messages at the end of each run. On the next run it reloads prior context automatically.
import { createRuntime } from '@agentskit/runtime'
import { createInMemoryMemory } from '@agentskit/core'
import { anthropic } from '@agentskit/adapters'
const runtime = createRuntime({
adapter: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-sonnet-4-6' }),
memory: createInMemoryMemory(),
})
await runtime.run('My name is Alice.')
const result = await runtime.run('What is my name?')
console.log(result.content) // "Your name is Alice."
For durable storage use sqliteChatMemory or redisChatMemory from @agentskit/memory.
Memory is saved after RunResult is assembled — if you abort early, partial messages are still persisted up to the abort point.
Retriever (RAG)
Pass a Retriever (for example from createRAG) via retriever in RuntimeConfig. Each loop step can inject retrieved context before the model thinks — same contract as chat UI.
Observers
observers accepts Observer instances from @agentskit/core for low-level events. Pair with @agentskit/observability when you need structured traces.
Troubleshooting
| Symptom | Likely fix |
|---|---|
Hits maxSteps with no answer | Model keeps calling tools; raise maxSteps, tighten tool descriptions, or adjust system prompt. |
| Tool timeout / hang | Add signal with a deadline; ensure tools reject on overload. |
| No prior context | Confirm memory uses the same conversationId (for backends that scope by id). |
| Empty retrieval | Check embedder dimensions match vector store; verify ingest ran for your corpus. |
See also
Start here · Packages · TypeDoc (@agentskit/runtime) · Tools · Skills · Delegation · @agentskit/core