Skip to content

DizzyMii/Flint

Repository files navigation

Flint

Token-efficient agentic TypeScript runtime

npm version CI MIT node >=20 TypeScript 5.7

Docs · API Reference · Examples


Six primitives. One agent loop. No magic. Flint gives you well-typed building blocks for AI agents in TypeScript — and stays out of the way. JavaScript is the runtime; Flint gives you the tools.

Install

npm install flint @flint/adapter-anthropic

Setup

API key

Flint's Anthropic adapter reads your API key from the environment:

export ANTHROPIC_API_KEY=sk-ant-...

Or use a .env file with dotenv:

npm install dotenv
import 'dotenv/config';
import { anthropicAdapter } from '@flint/adapter-anthropic';

const adapter = anthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY! });

TypeScript config

Flint requires moduleResolution: "bundler" (or "node16" / "nodenext") and strict: true. Minimum tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "outDir": "dist"
  }
}

ESM

Flint is ESM-only. Add "type": "module" to your package.json:

{
  "type": "module"
}

If you're using a bundler (Vite, esbuild, tsup) this is handled automatically.

Verify your setup

Run this snippet to confirm everything is wired up:

import { call } from 'flint';
import { anthropicAdapter } from '@flint/adapter-anthropic';

const adapter = anthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY! });
const res = await call({
  adapter,
  model: 'claude-haiku-4-5-20251001',
  messages: [{ role: 'user', content: 'Reply with the single word: ready' }],
});
console.log(res.ok ? res.value.message.content : res.error.message);
// → "ready"

Quick start

import { call, tool, agent } from 'flint';
import { budget } from 'flint/budget';
import { anthropicAdapter } from '@flint/adapter-anthropic';
import * as v from 'valibot'; // any Standard Schema library works

const adapter = anthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY! });

// One-shot call
const res = await call({
  adapter,
  model: 'claude-opus-4-7',
  messages: [{ role: 'user', content: 'What is the capital of France?' }],
});
if (res.ok) console.log(res.value.message.content); // "Paris"

// Define a tool
const add = tool({
  name: 'add',
  description: 'Add two numbers',
  input: v.object({ a: v.number(), b: v.number() }),
  handler: ({ a, b }) => a + b,
});

// Agent loop with budget enforcement
const out = await agent({
  adapter,
  model: 'claude-opus-4-7',
  messages: [{ role: 'user', content: 'What is 123 + 456?' }],
  tools: [add],
  budget: budget({ maxSteps: 5, maxDollars: 0.10 }),
});
if (out.ok) console.log(out.value.message.content); // "579"

What you get

Core (flint)

  • 1 runtime dependency (@standard-schema/spec)
  • 6 primitives: call, stream, validate, tool, execute, count
  • agent() loop with step / token / dollar budget caps
  • 6 compress transforms + pipeline() combinator: dedup, windowLast, windowFirst, truncateToolResults, summarize, orderForCache
  • 4 recipes: react (ReAct pattern), retryValidate, reflect, summarize
  • RAG: chunk, store, retrieve
  • Conversation memory with async summarization
  • Safety: injection detection, redaction, permissions, approval gates, boundary wrapping

Adapters (zero runtime dependencies each)

  • @flint/adapter-anthropic — prompt-cache aware, pure fetch + ReadableStream
  • @flint/adapter-openai-compat — any OpenAI-compatible endpoint (OpenAI, Groq, Ollama, DeepSeek, Together)

Graph

  • @flint/graph — state-machine workflows with memory checkpointing

Platform

  • Node 20+ · Web API primitives only (fetch, ReadableStream, TextDecoder)

Packages

Package Description
flint Core primitives, agent loop, compress, memory, RAG, safety, recipes
@flint/adapter-anthropic Anthropic Messages API — prompt-cache aware
@flint/adapter-openai-compat Any OpenAI-compatible endpoint
@flint/graph State-machine agent workflows

Flint vs LangChain

For a full narrative comparison covering philosophy, dependencies, error handling, streaming, budget enforcement, safety, and prompt caching, see the Flint vs LangChain guide.

LangChain models everything as a class hierarchy — LLMs, chains, tools, and agents are objects you instantiate and compose. You learn LangChain's abstractions, then use them to talk to models. Flint is plain async functions: call, tool, agent. You learn the provider API once; Flint adds thin, well-typed helpers on top. LangChain's modular package system means installing 3+ packages with dozens of transitive dependencies per provider; Flint has one runtime dependency (@standard-schema/spec). Where LangChain's executor surfaces errors as thrown exceptions, Flint returns Result<T> — no try/catch at call sites.

Install

LangChain

npm install langchain @langchain/anthropic @langchain/core

Flint

npm install flint @flint/adapter-anthropic

Basic LLM call

LangChain

import { ChatAnthropic } from '@langchain/anthropic';
import { HumanMessage } from '@langchain/core/messages';

const llm = new ChatAnthropic({
  model: 'claude-opus-4-7',
  apiKey: process.env.ANTHROPIC_API_KEY,
});
const res = await llm.invoke([new HumanMessage('What is the capital of France?')]);
console.log(res.content); // "Paris"

Flint

import { call } from 'flint';
import { anthropicAdapter } from '@flint/adapter-anthropic';

const adapter = anthropicAdapter({ apiKey: process.env.ANTHROPIC_API_KEY! });
const res = await call({
  adapter,
  model: 'claude-opus-4-7',
  messages: [{ role: 'user', content: 'What is the capital of France?' }],
});
if (res.ok) console.log(res.value.message.content); // "Paris"

Tool definition

LangChain

import { tool } from '@langchain/core/tools';
import { z } from 'zod';

const add = tool(({ a, b }) => String(a + b), {
  name: 'add',
  description: 'Add two numbers',
  schema: z.object({ a: z.number(), b: z.number() }),
});

Flint

import { tool } from 'flint';
import * as v from 'valibot'; // any Standard Schema library works

const add = tool({
  name: 'add',
  description: 'Add two numbers',
  input: v.object({ a: v.number(), b: v.number() }),
  handler: ({ a, b }) => a + b,
});

Agent loop

LangChain

import { ChatAnthropic } from '@langchain/anthropic';
import { AgentExecutor, createToolCallingAgent } from 'langchain/agents';
import { ChatPromptTemplate } from '@langchain/core/prompts';
// add tool defined in previous snippet

const llm = new ChatAnthropic({ model: 'claude-opus-4-7', apiKey: process.env.ANTHROPIC_API_KEY });
const prompt = ChatPromptTemplate.fromMessages([
  ['system', 'You are a helpful assistant.'],
  ['placeholder', '{chat_history}'],
  ['human', '{input}'],
  ['placeholder', '{agent_scratchpad}'],
]);
const agent = createToolCallingAgent({ llm, tools: [add], prompt });
const executor = new AgentExecutor({ agent, tools: [add] });
const result = await executor.invoke({ input: 'What is 123 + 456?' });
console.log(result.output); // "579"

Flint

import { agent } from 'flint';
import { budget } from 'flint/budget';
// adapter and add defined above

const out = await agent({
  adapter,
  model: 'claude-opus-4-7',
  messages: [{ role: 'user', content: 'What is 123 + 456?' }],
  tools: [add],
  budget: budget({ maxSteps: 5, maxDollars: 0.10 }),
});
if (out.ok) console.log(out.value.message.content); // "579"

Why Flint

  • One dependency@standard-schema/spec only. No transitive framework sprawl.
  • No classes, no chains — plain functions that compose naturally.
  • Standard Schema — bring Zod, Valibot, ArkType, or any compatible library.
  • Budget-aware — every agent loop enforces step, token, and dollar limits.
  • Streaming firstAsyncIterable<StreamChunk> throughout.
  • Safety in core — injection detection, redaction, and approval gates are not an afterthought.
  • Results, not exceptionsPromise<Result<T>> everywhere; no try/catch at the call site.

Documentation

Full documentation at dizzymii.github.io/Flint:

  • Guide — installation, quick start, v0 status
  • Flint vs LangChain — full narrative comparison
  • Testing — mockAdapter, scriptedAdapter, testing patterns
  • FAQ — RAG, vector search, design decisions, common questions
  • Primitivescall, stream, validate, tool, execute, count, agent
  • Features — budget, compress, memory, RAG, recipes, safety, graph
  • Adapters — Anthropic, OpenAI-compatible, custom
  • Examples — basic call, tools, agent, streaming, RAG, multi-agent, memory, graph
  • Landlord@flint/landlord multi-agent orchestration
  • Reference — error types catalog

Contributing

See CONTRIBUTING.md.

License

MIT — see LICENSE.

Packages

 
 
 

Contributors