Getting started
Install
npm install @syntropy-systems/skep
Requires Node.js 20+. The package ships ESM with type declarations and has zero runtime dependencies.
Your first skep
A run needs three things: cells to work in, a mind to decide, and a prompt.
import { skep, registerCell, cell, cellKit, text, xml } from "@syntropy-systems/skep";
import { llmMind } from "@syntropy-systems/skep/agents/llm";
type Notes = { items: string[] };
const k = cellKit<Notes>();
// ── state ──
const enter = ({ items }: { items: string[] }): Notes => ({ items });
// ── show ──
const show = (s: Notes) => xml`
<notes>${s.items.map((n, i) => xml`<note id="${i}">${n}</note>`)}</notes>
`;
// ── does ──
const add = k.action({
describe: "Append a note.",
locks: ["write"], // only a bee carrying the write key sees this
input: { note: text("note text") },
run: ({ note }, ctx) => { // note: string
ctx.update((s) => ({ items: [...s.items, note] }));
ctx.observe(`added: ${note}`);
},
});
// ── assembly ──
const notes = cell<Notes, { items: string[] }>("notes", { enter, show, does: { add } });
const hive = skep({
cells: [registerCell(notes, { items: ["buy honey"] }, { as: "worker" })],
mind: llmMind(),
});
const comb = await hive.run("Add a note reminding me to refill the feeder.");
console.log(comb.result.outcome, "—", comb.result.summary);
A bee never sees the add action unless it carries the write key — here the cell is
registered as: "worker" (holds read + write). A scout (only read) would see the
notes cell but not add. The resolve action is injected automatically, so the bee can
always finish.
Pointing at a model
llmMind() talks to any OpenAI-compatible chat-completions endpoint. Configure it per
instance, or via environment variables:
| Variable | Default | Purpose |
|---|---|---|
OPENAI_BASE_URL |
http://localhost:8080/v1 |
Base URL of the endpoint. |
SKEP_MODEL |
local-model |
Model id sent in each request. |
OPENAI_API_KEY |
(unset) | Sent as Authorization: Bearer …. |
const mind = llmMind({ baseUrl: "https://api.openai.com/v1", model: "gpt-4o-mini", apiKey: process.env.OPENAI_API_KEY });
Because the mind lives on the bee, different bees can run different models — pass a stronger
one when you spawn a reviewer: ctx.spawn(cell, input, goal, { mind: llmMind({ model: "..." }) }).
No model? Run the mock
Every decision point is just a Mind, so you can drive a run with no network at all — a
scripted policy that returns canned decisions. The repo's code-browser example ships one:
npm run run:mock # deterministic, offline
Watching it work
Pass onEvent to see the lifecycle (and createDebugTui to see the exact text each bee
reads before deciding):
import { createDebugTui } from "@syntropy-systems/skep/debug/tui";
await hive.run(prompt, { onEvent: createDebugTui(), budget: 25, maxSteps: 8 });