Stark-Kit / Docs

Get Started

Stark-Kit is a lightweight, strictly typed, and provider-agnostic TypeScript framework for building AI agents. Write your agentic loops once and run them on OpenAI, Claude, Gemini, or Mistral — without touching your core application logic.

Why Stark-Kit?

Most agent frameworks tightly couple your business logic to a specific provider's SDK. When you need to switch models — for cost, capability, or compliance reasons — you end up rewriting large portions of your code. Stark-Kit addresses this by introducing a provider-agnostic execution model centered around a unified CanonicalMessage interface. Every LLM adapter speaks the same internal language, so your agent code never needs to know which provider it's running on.

Beyond provider portability, Stark-Kit ships with everything you need to build production-grade agentic systems out of the box:

  • Strictly Typed ToolsRuntime schema validation via Zod — the model can't call a tool with wrong arguments.
  • Real-Time StreamingStream text chunks, tool call events, and lifecycle states as they occur.
  • Lifecycle HooksIntercept calls before they reach the LLM or before/after tool execution.
  • Human-in-the-Loop (HITL)Pause execution mid-run to get human approval before running sensitive tools.
  • Agent HandoffsRoute conversations between specialized agents at runtime.
  • Structured OutputsBind an agent to a Zod schema and force structured JSON responses.

Architecture

Stark-Kit has three main components that work together to keep vendor logic separate from your agent code:

1. The Agent

An Agent encapsulates everything that defines an agent's behaviour: its system instructions, the tools it can call, the provider it runs on, runtime parameters like temperature and max steps, lifecycle hooks, and an optional output schema. An agent is a pure configuration object — it doesn't do anything on its own. It tells the run loop how to behave.

2. The Provider

A Provider is a standard interface implemented by each LLM adapter:OpenAIProvider, ClaudeProvider, GeminiProvider, and MistralProvider. Each adapter translates Stark-Kit's internal message structure into the native format that provider expects, and maps the response back to a unified shape. You can also implement the Provider interface yourself to add any LLM backend.

3. The Run Loop

run() and runStream() are the orchestrators. They manage the message history, call the provider, execute tools when requested, apply lifecycle hooks, handle HITL pauses, and transition control between agents during handoffs. The loop repeats until the model stops calling tools, a HITL pause is triggered, or maxSteps is exceeded.

overview.ts
import "dotenv/config";
import { Agent, run, defineTool, OpenAIProvider } from "@mehularora/stark-kit";
import z from "zod";
// 1. Create a provider — reads OPENAI_API_KEY from environment
const provider = new OpenAIProvider({ model: "gpt-4o" });
// 2. Define a typed tool
const lookupTool = defineTool({
name: "lookupUser",
description: "Look up a user by email.",
parameters: z.object({ email: z.string().email() }),
execute: async ({ email }) => {
return { id: 1, name: "Alice", email };
},
});
// 3. Configure the agent
const agent = new Agent({
name: "SupportBot",
provider,
instructions: "You are a support assistant. Look up user data when needed.",
tools: [lookupTool],
maxSteps: 10,
});
// 4. Run the loop
const result = await run({ agent, messages: "Who is user@example.com?" });
if (result.status === "complete") {
console.log(result.content);
}
Tip: Ready to write your first agent? Head to Quick Start for the fastest path to a running agent, or jump straight to Make Your First Agent for a full walkthrough with tools and streaming.