Basic Agent
The smallest useful Little Harness configuration.
Little Harness: published on npm as little-harness@0.2.0-alpha.0 (2026-10-05). Sections labeled UNRELEASED describe source-only changes. Release status
The smallest useful Little Harness agent has three pieces:
- instructions
- tools
- an execution call:
streamHarness()for chat orgenerateHarness()for a completed result
import { openai } from "@ai-sdk/openai";
import { tool, type UIMessage } from "ai";
import { z } from "zod";
import { createHarness, localHost, streamHarness } from "@little-stack/harness";
// Replace with your own data source.
const docs = [
{ title: "Renewals", body: "Renewal notices go out 60 days before the contract end date." },
{ title: "Billing", body: "Invoices are issued on the first business day of each month." },
];
const searchDocs = tool({
description: "Search the account team's documentation.",
inputSchema: z.object({ query: z.string() }),
execute: async ({ query }) =>
docs.filter((doc) => doc.body.toLowerCase().includes(query.toLowerCase())),
});
const harness = createHarness({
host: localHost(),
model: openai("gpt-5"),
system: "Answer account questions using the tools available to you.",
tools: { searchDocs },
});
export async function POST(req: Request) {
const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamHarness({
harness,
messages,
});
return result.toUIMessageStreamResponse();
}Add Continuity
Pass a stable session key when the next request belongs to the same conversation. In a chat UI, this is usually your app's chat id or thread id.
const result = streamHarness({
harness,
messages,
session: chatId,
});The same session can keep working files, generated artifacts, and trace continuity.
The client can stay on the normal AI SDK path.
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({ api: "/api/chat" }),
});
sendMessage({ text: "Turn that into a short action list." });Generate A Final Result
Use generateHarness() when the caller does not need live UI streaming.
import { Output } from "ai";
import { generateHarness } from "@little-stack/harness";
const result = await generateHarness({
harness,
type: "account.brief",
input: { accountId },
output: Output.object({ schema: accountBriefSchema }),
});
if (result.status !== "completed") {
// A tool parked the turn; see generateHarness() for resuming it.
return Response.json({ status: result.status }, { status: 202 });
}
return Response.json({
brief: result.output,
artifacts: result.artifacts,
trace: result.trace,
});The same harness configuration, session workspace, tools, skills, artifacts, and Persistent Dir behavior should apply to both execution APIs.
For a deeper walkthrough of streaming routes, final-result jobs, structured outputs, message files, and lifecycle callbacks, read Generating And Streaming.
Define Input Types
Use Input Types when a caller is
not naturally sending chat messages. Input Types give reusable meaning to open
strings like support.ticket_triage, validate the input, and can provide a
default structured output.
Add Skills
Skills are useful when the model needs procedural knowledge.
import { skill } from "@little-stack/harness";
const harness = createHarness({
host: localHost(),
model: openai("gpt-5"),
system: "Help account teams prepare customer briefs.",
tools: { searchDocs },
skills: [skill("./skills/customer-briefs")],
});Use skills for durable instructions like how to write a customer brief, how to interpret internal fields, or when to export a finished artifact.
Add Persistence Later
Do not start with Persistent Dirs unless the agent needs cross-session files. The private session workspace is enough for most first agents.
Add a Persistent Dir when you need the agent to remember user notes, project preferences, or app-managed files across sessions.
Next Steps
To keep several agents in one repo โ each a self-contained folder with auto-discovered tools and skills, plus a CLI to scaffold and chat with them โ see Agent Folders.