The SDK is for Node.js server applications. It connects to an explicit Local Core Unix socket or runner-service URL; it does not run the Kestrel Runtime inside the application process.
Install
pnpm add @kestrel-agents/sdk@0.8.5Node.js 20 or newer is required. Browser and edge-runtime use are not supported in this release.
Agent API
import { createAgent } from "@kestrel-agents/sdk";
const agent = createAgent({
id: "kestrel-agent",
profileId: "kestrel",
target: {
kind: "remote",
baseUrl: process.env.KESTREL_RUNNER_SERVICE_URL!,
authToken: process.env.KESTREL_RUNNER_SERVICE_TOKEN!,
},
});Use a local target when the server process should connect directly to Local Core:
const agent = createAgent({
id: "kestrel-agent",
profileId: "kestrel",
target: {
kind: "local",
socketPath: process.env.KESTREL_LOCAL_CORE_API_SOCKET!,
authToken: process.env.KESTREL_LOCAL_CORE_API_TOKEN!,
},
});Both targets use the Execution Protocol. The target selects the deployment boundary, not a different runtime implementation.
Core methods
| Method | Required input | Result |
|---|---|---|
run() | sessionId, message, request context | terminal run event |
stream() | run input plus optional signal | live event stream and terminal result |
resume() | sessionId, requestId, message, context | terminal event for the continued interaction |
resumeStream() | resume input plus optional signal | live events and terminal result |
session(id).memory.get() | request context | revisioned memory snapshot |
session(id).memory.update() | expectedRevision, patch, context | persisted next snapshot |
subscribe() | explicit filter and context | filtered durable event stream |
Request context carries actor and optional tenant identity with every call:
const context = {
actor: {
actorId: "user-123",
actorType: "end_user" as const,
displayName: "Taylor Example",
tenantId: "acme",
},
tenantId: "acme",
};Resume a waiting interaction
await agent.resume(
{
sessionId: "kestrel-session-001",
requestId: "interaction-123",
message: "Approved. Continue.",
},
context,
);The request ID must come from the durable waiting interaction being answered. When the pending interaction is a recovery review, also submit the exact recovery option identifier exposed by the result. Never bind by display label.
Streaming and subscriptions
stream() and resumeStream() expose live request activity plus one terminal promise. subscribe() observes filtered persisted events independently and reconnects through durable cursor state. Consumers must validate event envelopes and tolerate duplicates.
Versioned session memory
const session = agent.session("kestrel-session-001");
const memory = await session.memory.get(context);
await session.memory.update(
{
expectedRevision: memory.revision,
patch: {
findings: "The runner boundary needs review.",
nextAction: "Verify the runner ping example.",
},
},
context,
);Mission Control methods
The 0.8 runner protocol exposes mission_control.project.get and mission_control.action.execute for Project work, attempts, evidence, review, and acceptance. Runtime operator methods continue to own active and waiting runs. Resolve Project and action authority on the server before dispatch.
Advanced runner client
Import KestrelClient from @kestrel-agents/sdk/runner when an application
needs direct Execution Protocol operations for jobs, operator state, Mission
Control, checkpoints, recovery, or subscriptions.
import { KestrelClient } from "@kestrel-agents/sdk/runner";
const client = new KestrelClient({
target: {
kind: "remote",
baseUrl: process.env.KESTREL_RUNNER_SERVICE_URL!,
authToken: process.env.KESTREL_RUNNER_SERVICE_TOKEN!,
},
});The root Agent API is the default application surface. The runner subpath is appropriate when the application intentionally owns lower-level command and event handling.
Errors, cancellation, and terminal outcomes
Transport, HTTP, protocol-validation, terminal failure, cancellation, and waiting are distinct outcomes. Preserve the underlying safe error code and correlation; do not turn a cancelled or waiting run into a generic failure.
Constraints and compatibility
- keep credentials and actor resolution in server-owned code
- use explicit filters for subscriptions; the SDK does not expose a global event firehose
- use
stream.resultorrun()results for terminal state rather than inferring completion from a disconnected stream - close long-lived clients when the owning server process or scope ends
- follow the exact dependency contracts declared by Runtime, Protocol, SDK, adapters, and clients; equal semantic versions are not required
Start with Build your first agent, then use Next.js integration or the AI SDK presentation adapter as needed.