v0.0.2 · Python 3.10+

The seam under your agent harness

Loomkit is a tiny, swappable LLM orchestration core — without LangChain-scale bloat. A Protocol, a few dataclasses, one optional provider.

$pip install loomkit

Why Loomkit

Smallest useful surface

v0 ships only what you need to call a model and swap backends later. Everything else is deliberately deferred.

Provider Protocol

Anything with the right generate() signature is a provider. No inheritance, no registration, no base class.

Message · Response · Usage

A handful of dataclasses. The smallest useful surface for chat-style generation.

Gemini out of the box

One concrete provider via the official google-genai SDK. Optional extra — core stays zero-deps.

Built to layer

Streaming, tools, retries, and agents land through the Provider seam without breaking call sites.

Quickstart

Generate in a few lines

Install the Gemini extra, set GEMINI_API_KEY (or GOOGLE_API_KEY), and call generate().

  • Typed against the Provider Protocol — swap backends freely
  • Response includes text, finish reason, and usage
  • Core package stays dependency-free
quickstart.py
import osfrom loomkit import Messagefrom loomkit.providers.gemini import GeminiProvider  # Reads GEMINI_API_KEY (or GOOGLE_API_KEY) from envprovider = GeminiProvider() resp = provider.generate(    [        Message(role="system", content="You are concise."),        Message(role="user", content="Name three primary colors."),    ],    model="gemini-2.5-flash",    temperature=0.2,) print(resp.text)print(resp.finish_reason, resp.usage)

Design

Why a Protocol, not a base class

Provider is a typing.Protocol. Adding a new backend means writing one class with a generate() method matching the signature — no imports from loomkit, no inheritance, no registration.

Call sites typed against Provider accept any conforming class.

my_provider.py
class MyProvider:    def generate(self, messages, *, model, temperature=None,                 max_tokens=None, stop=None) -> Response: ...  # No loomkit imports. No inheritance. No registration. # Call sites typed against Provider accept any conforming class.

What's next

Deferred — and how it lands

Features layer through the Provider seam without breaking existing call sites. No kitchen-sink framework, just composable surfaces.

  • Streaminggenerate_stream() returning chunk iterables
  • Tool / function callingtools= kwarg; Message.content grows to a parts list
  • AsyncSibling AsyncProvider Protocol with async def generate(...)
  • Retries / rate limitingDecorator providers — RetryingProvider(inner, ...)
  • Tracing / observabilitySame shape — TracingProvider(inner, sink)
  • Agent loopsOne layer up: loomkit.agents consumes a Provider
  • GraphsTop of the stack; consumes agents

Install

Pick your extras

Core is zero-deps. Gemini and dev tooling are optional extras. Requires Python 3.10+.

Core only

Zero dependencies

pip install loomkit

With Gemini

Adds google-genai

pip install 'loomkit[gemini]'

Dev setup

Plus pytest

pip install 'loomkit[gemini,dev]'

Weave your own stack

Start with the core. Swap providers. Layer agents when you need them — not before.