Documentation · Releases · Issues
Intention Kernel is a TypeScript runtime for durable, observable, model-driven agents without turning business behavior into a tree of hard-coded routes.
The model interprets what the user wants. The kernel validates that proposal against registered capabilities and policies, plans multiple operations by dependency, executes authorized code, reduces evidence-bearing facts, and composes one grounded response. LangGraph is the private execution engine; consumers depend only on Intention Kernel contracts.
Intention Kernel is licensed under Apache-2.0. Releases are distributed through GitHub as installable tarballs. The package is not published to the npm registry.
Download the .tgz asset from the GitHub release, then install it in your application:
npm install ./intention-kernel-0.8.0.tgzThe installed package provides two public modules:
| Import | Public API |
|---|---|
intention-kernel |
Agent and capability definitions, runtime execution, model gateways, versioned prompts, persistence contracts, and events. |
intention-kernel/testing |
Scenario evaluation, assertions, agent adapters, portable reports, event collection, and in-memory test fixtures. |
For example:
import { createKernel, defineAgent, defineCapability } from "intention-kernel";
import {
createMemoryDurability,
createEventCollector,
createAgentEvaluationAdapter,
runEvaluation,
parseEvaluationSuite,
parseEvaluationReport,
evaluateAssertions,
EvaluationError,
TESTING_VERSION,
} from "intention-kernel/testing";Testing and evaluation are part of the supported public API. Use them from your application, test runner, evaluation service, or development tools. The package includes their runtime implementation and TypeScript declarations.
createMemoryDurability() stores state in the current process. Use a transactional durability adapter when the application needs persistence across restarts. Evaluation can exercise an agent configured with that production adapter.
- An intention is a contextual user objective.
- A capability is one executable operation with schemas, fact dependencies and effect semantics.
- A fact is confirmed, versioned knowledge with evidence and lineage.
- A policy is a pure host-owned constraint applied after interpretation and before execution.
- A port is an infrastructure contract injected into capabilities.
- A provider tool is only an adapter-level representation; it is not a kernel primitive or execution authority.
Capabilities may delegate implementation work to a nested graph, state machine,
workflow engine or remote orchestrator through an injected port. The kernel does
not expose any of those engine types. Instead, the capability publishes
observable progress through context.events.emit():
async execute(context, input) {
const graph = context.ports["planningGraph"] as {
run(input: unknown, emit: typeof context.events.emit): Promise<unknown>;
};
const output = await graph.run(input, (name, data) => context.events.emit(name, data));
// Validate and return output, facts and evidence here.
}Each publication becomes a sanitized capability.event in the same step and
causal branch. This keeps nested execution visible without coupling consumers to
LangGraph. See the executable examples for a real
three-node subgraph.
import {
capabilityId,
defineCapability,
defineSchema,
evidenceId,
factType,
} from "intention-kernel";
type SearchInput = { query: string };
type SearchOutput = { products: readonly { id: string; name: string; price: number }[] };
const searchInput = defineSchema<SearchInput>({
vendor: "app",
validate: (value) => {
if (typeof value !== "object" || value === null || typeof Reflect.get(value, "query") !== "string") {
return { issues: [{ message: "query is required", path: ["query"] }] };
}
return { value: { query: String(Reflect.get(value, "query")) } };
},
jsonSchema: () => ({
type: "object",
properties: { query: { type: "string" } },
required: ["query"],
additionalProperties: false,
}),
});
const searchOutput = defineSchema<SearchOutput>({
vendor: "app",
validate(value) {
const products: unknown = Reflect.get(Object(value), "products");
if (!Array.isArray(products)) {
return { issues: [{ message: "products must be an array", path: ["products"] }] };
}
const parsed: SearchOutput["products"][number][] = [];
for (const item of products as unknown[]) {
const id: unknown = Reflect.get(Object(item), "id");
const name: unknown = Reflect.get(Object(item), "name");
const price: unknown = Reflect.get(Object(item), "price");
if (typeof id !== "string" || typeof name !== "string" || typeof price !== "number" || !Number.isFinite(price)) {
return { issues: [{ message: "Each product needs an id, name, and finite price", path: ["products"] }] };
}
parsed.push({ id, name, price });
}
return { value: { products: parsed } };
},
jsonSchema: () => ({
type: "object",
properties: {
products: {
type: "array",
items: {
type: "object",
properties: { id: { type: "string" }, name: { type: "string" }, price: { type: "number" } },
required: ["id", "name", "price"],
additionalProperties: false,
},
},
},
required: ["products"],
additionalProperties: false,
}),
});
export const searchProducts = defineCapability({
id: capabilityId("product.search"),
version: 1,
description: "Search products that match the user's current needs",
input: searchInput,
output: searchOutput,
requires: [],
provides: [{ type: factType("product.candidates"), version: 1 }],
effect: "read",
guidance: {
whenToUse: ["The user asks to find, browse or recommend products"],
whenNotToUse: ["The user is selecting from candidates already present in facts"],
examples: ["Show me an efficient family option"],
},
async execute(context, input) {
const catalog = context.ports["catalog"] as {
search(query: string, signal: AbortSignal): Promise<SearchOutput>;
};
const output = await catalog.search(input.query, context.signal);
const evidence = evidenceId("catalog-search-result");
return {
status: "completed",
output,
facts: [{
type: factType("product.candidates"),
version: 1,
value: output.products,
evidenceIds: [evidence],
dependsOn: [],
}],
evidence: [{
id: evidence,
source: "external",
content: `The catalog returned ${output.products.length} matching products.`,
data: output.products,
}],
artifacts: [{ id: "product-results", kind: "product-list", data: output.products }],
};
},
});Every business fact that may appear in the response needs evidence. The response model emits ordered text parts with evidence IDs; the kernel derives exact claim spans from those parts before semantic review. Capabilities may return needs_input, needs_dependency, needs_confirmation or a safe failed issue instead of throwing for expected domain outcomes.
import {
agentId,
createKernel,
defineAgent,
threadId,
turnId,
type Durability,
type ModelGateway,
} from "intention-kernel";
import { searchProducts } from "./search-products.js";
declare const modelGateway: ModelGateway; // Gemini, OpenAI, Anthropic or local adapter
declare const durability: Durability; // PostgreSQL or another transactional adapter
declare const catalog: unknown;
const kernel = createKernel({
modelGateway,
durability,
ports: { catalog },
limits: { turnTimeoutMs: 60_000, maxSteps: 64, recentMessageLimit: 20 },
});
const agent = await kernel.compile(defineAgent({
id: agentId("commerce.advisor"),
version: 1,
identity: "A helpful, concise product advisor",
capabilities: [searchProducts],
policies: [],
modelPolicy: {
"capability.select": "fast-routing-model",
"turn.interpret": "fast-structured-model",
"response.compose": "natural-response-model",
"response.grounding-review": "grounding-review-model",
},
}));
const result = await agent.run({
threadId: threadId("customer-42"),
turnId: turnId(crypto.randomUUID()),
input: { text: "Find an efficient option for my family and tell me the price" },
});
console.log(result.response.message);The same gateway instance may dispatch each model-policy value to a different provider. Capabilities and conversation state do not change when the model changes.
The selector receives only compact capability summaries. The interpreter then receives schemas and semantic guidance for the selected capabilities, never the entire registry. This progressive disclosure keeps the prompt bounded while the kernel still validates every proposed identifier, input, dependency and policy.
A write capability declares effect: "write" and an explicit confirmation mode. With confirmation: "required", the planner asks the user before execution. With confirmation: "capability", the capability owns the confirmation interaction and must validate consent before performing its mutation. Writes cannot use confirmation: "none".
Perform mutations through context.runEffect(operationKey, operation), which returns { value, receipt }. Preserve the key for the same logical operation across retries and turns; use a distinct key for a new operation. Completed receipts replay within the thread, and uncertain effects cannot be retried blindly. See capability confirmation and durable effects for the complete contract.
One user turn may contain multiple intentions. Independent reads execute concurrently. A dependent operation waits for the fact it requires and can consume a fact produced earlier in the same turn. Conflicting unrelated writes become an explicit user choice rather than an arbitrary model decision.
Describe use cases as conversation scenarios with ordered inputs and multiple acceptance criteria. Call the installed package from your application:
import type { CompiledAgent } from "intention-kernel";
import {
createAgentEvaluationAdapter,
parseEvaluationSuite,
runEvaluation,
type EvaluationEvaluators,
} from "intention-kernel/testing";
export function evaluateScenarios(
agent: CompiledAgent,
definition: unknown,
evaluators: EvaluationEvaluators = {},
) {
return runEvaluation({
suite: parseEvaluationSuite(definition),
target: { id: agent.id, fingerprint: agent.fingerprint },
adapter: createAgentEvaluationAdapter({ agent }),
evaluators,
});
}The function above is application code. Pass your compiled agent, the suite definition, and any custom evaluators; the returned report contains case outcomes and diagnostic evidence. The evaluation API requires no library repository checkout, build, package script, or specific test runner.
See Evaluating from your project for a complete suite, or the detailed evaluation guide for multiple turns, variants, assertion composition, business evaluators, and coding-agent iteration.
- Documentation site
- Installation and first agent
- Evaluation framework
- Scenario syntax and use cases
- Assertions and custom evaluators
- Reports and coding-agent iteration
- Execution architecture
- Application examples
- Public API
- Generated API reference
- Adapter guide
- Versioned model prompts
- Runtime invariants
- Competitive analysis
- Release posture
The reference under docs/reference/ is generated from the public TSDoc and emitted declarations.
The repository testing guide documents the library's build, lint, type, behavior, documentation, and package checks. The repository examples include scripted and model-backed demos. Their development commands apply to a clone of this library's source repository.
Applications that installed the package use the public APIs described above and their own execution or test setup.
See CONTRIBUTING.md for development and pull request guidance.
See SECURITY.md. The current 0.x line may change its public contract between minor versions. Once 1.0.0 is released, breaking changes require a new major version.
Intention Kernel was created by:
Licensed under the Apache License, Version 2.0.



