Little documentation
Guides and APIBuild Agents

Input Types

Defining reusable non-chat inputs for generateHarness and streamHarness.

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

Most app chat routes can pass raw AI SDK UIMessage[] directly. Input Types are for callers that are not naturally chat messages: Little Workflow planning requests, background jobs, ticket triage, document review, report generation, or product-specific commands.

An Input Type gives an open string a reusable meaning.

import { Output } from "ai";
import { createHarness, inputType, localHost } from "@little-stack/harness";
import { z } from "zod";

const ticketSchema = z.object({
  id: z.string(),
  subject: z.string(),
  body: z.string(),
  customerTier: z.enum(["free", "pro", "enterprise"]),
});

const triageSchema = z.object({
  priority: z.enum(["low", "medium", "high", "urgent"]),
  owner: z.string(),
  nextAction: z.string(),
});

const harness = createHarness({
  host: localHost(),
  model,
  system: "You help support teams route customer issues.",
  tools: { searchDocs, queryCustomer },
  inputTypes: {
    "support.ticket_triage": inputType({
      description:
        "Triage one support ticket and decide priority, owner, and next action.",
      inputSchema: ticketSchema,
      output: Output.object({ schema: triageSchema }),
      toMessages: ({ input }) => [
        {
          role: "user",
          content:
            `Triage this support ticket.\n\n` +
            `Subject: ${input.subject}\n` +
            `Tier: ${input.customerTier}\n\n` +
            input.body,
        },
      ],
    }),
  },
});

Then callers can use the type without repeating prompt glue.

const result = await generateHarness({
  harness,
  type: "support.ticket_triage",
  input: ticket,
  session: ticket.id,
});

if (result.status === "completed") result.output.priority;

Two Input Modes

Little Harness should support two input modes:

streamHarness({ harness, messages });
generateHarness({ harness, type: "support.ticket_triage", input: ticket });

Use messages for AI SDK chat. Use type and input for caller-defined requests. A call should not need both shapes at once.

What Definitions Do

An Input Type definition can:

  • describe what the type means
  • validate the caller's input
  • convert product input into model messages
  • provide default structured output
  • add input-specific instructions without bloating the global system prompt

The definition belongs on createHarness({ inputTypes }) because it is reusable agent surface area, not one-off request plumbing.

Output Defaults

Input Types can define a default AI SDK Output shape.

inputType({
  description: "Write a renewal risk brief.",
  inputSchema: renewalInputSchema,
  output: Output.object({ schema: renewalBriefSchema }),
  toMessages,
});

A call may still override the output when it needs a different shape.

await generateHarness({
  harness,
  type: "account.renewal_brief",
  input,
  output: Output.text(),
});

Undefined Types

Undefined input types should not be hard failures by default. Little Harness can fall back to a generic representation and emit a host-facing warning:

await generateHarness({
  harness,
  type: "experiments.unregistered_task",
  input: payload,
});

The warning should appear in the trace and result metadata so developers can fix the missing definition. It should not be injected into the agent's normal model context by default.

Streaming Custom Inputs

Custom inputs can stream too. This is useful when a product command still needs live progress or a chat-like response.

const result = streamHarness({
  harness,
  type: "document.review",
  input: { documentId },
  session: documentId,
});

return result.toUIMessageStreamResponse();

On this page