loom-ai
Pluggable AI orchestration framework with swappable backends. Zero required dependencies.
Install
pip install flossware-loom-ai # core (stdlib only)
pip install flossware-loom-ai[server] # + FastAPI REST server
pip install flossware-loom-ai[postgresql] # + PostgreSQL/pgvector storage
pip install flossware-loom-ai[redis] # + Redis queues
pip install flossware-loom-ai[all] # everything
Quick Start
As a Python library
from loom_ai import LoomConfig, Document, ChatMessage
# Zero-config: all in-memory / no-op backends
cfg = LoomConfig.from_env()
# Store a document
doc_id = await cfg.storage.store_document(Document(
id="doc-1", title="Example", content="Hello world"
))
# Multi-model consensus (requires LOOM_LLM_BASE_URL)
responses = await cfg.llm.consensus(
[ChatMessage(role="user", content="Explain distributed systems")],
models=["gemini-3.5-flash", "llama-3.3-70b", "mistral-small"],
)
As a REST server
# Minimal — just LLM routing
export LOOM_LLM_BASE_URL=http://localhost:4000/v1
python -m loom_ai
# Full stack
export LOOM_STORAGE=postgresql
export LOOM_QUEUE=redis
export LOOM_GRAPH=memory
export LOOM_LLM_BASE_URL=http://localhost:4000/v1
python -m loom_ai
Routes mount dynamically based on configuration:
| Backend | Routes | When |
|---|---|---|
| Storage | /knowledge/* |
Always |
| Queue | /pipeline/* |
Always |
| Search | /search/* |
Always |
| Secrets | /secrets/* |
Always |
| LLM | /llm/* |
LOOM_LLM_BASE_URL set |
| Graph | /graph/* |
LOOM_GRAPH != disabled |
| Health | /health |
Always |
Configuration
All via environment variables (defaults in parentheses):
| Variable | Options | Default |
|---|---|---|
LOOM_STORAGE |
memory, postgresql |
memory |
LOOM_QUEUE |
memory, redis |
memory |
LOOM_SECRETS |
env, dotenv, postgresql |
env |
LOOM_EMBEDDING |
noop, openai, litellm |
noop |
LOOM_SEARCH |
memory, postgresql |
memory |
LOOM_GRAPH |
disabled, memory, orientdb |
disabled |
LOOM_LLM_BASE_URL |
Any OpenAI-compatible URL | (none) |
LOOM_LLM_API_KEY |
Bearer token | (none) |
LOOM_LLM_MODEL |
Default model id | gpt-4o-mini |
LOOM_HOST |
Server bind address | 0.0.0.0 |
LOOM_PORT |
Server port | 5000 |
Don't set it? Don't get it. Set nothing at all and you get a pure in-memory orchestrator.
Architecture
loom_ai/
protocols.py 7 Protocol interfaces (async, stdlib-only)
models.py 9 dataclasses (Document, Chunk, ChatMessage, etc.)
config.py LoomConfig registry with from_env() factory
prompts.py Built-in consensus prompt templates
server.py Optional FastAPI REST server
backends/
memory.py In-memory implementations (zero deps)
env_secrets.py Environment variable secrets
http_llm.py HTTP LLM backend (urllib, zero deps)
7 Pluggable Protocols
| Protocol | Purpose | Default | Enterprise |
|---|---|---|---|
StorageBackend |
Documents, chunks, embeddings | In-memory dicts | PostgreSQL + pgvector |
QueueBackend |
Named task queues | In-memory deque | Redis |
SecretsBackend |
API keys and config | os.environ |
PostgreSQL encrypted |
EmbeddingBackend |
Text to vectors | Zero vectors | OpenAI / Jina / Voyage |
SearchBackend |
Full-text + semantic | Substring + cosine | tsvector + pgvector ANN |
GraphBackend |
Knowledge graph | Disabled | OrientDB |
LLMBackend |
Chat + consensus | HTTP (any OpenAI-compatible) | Same |
Multi-Model Consensus
Fan out to N models, synthesize with an arbiter:
from loom_ai.prompts import build_worker_messages, build_arbiter_messages
# Workers respond independently
worker_msgs = build_worker_messages("review", "Check this code for bugs")
responses = await cfg.llm.consensus(
[ChatMessage(role=m["role"], content=m["content"]) for m in worker_msgs],
models=["gemini-3.5-flash", "llama-3.3-70b", "codestral"],
timeout_seconds=60,
retries=2,
)
# Arbiter synthesizes
arbiter_msgs = build_arbiter_messages(
"Check this code for bugs",
[{"model": r.model, "response": r.content} for r in responses],
)
synthesis = await cfg.llm.chat(
[ChatMessage(role=m["role"], content=m["content"]) for m in arbiter_msgs],
model="gemini-3.5-flash",
temperature=0.3,
)
Free AI Providers
See docs/free-ai-providers.md for 20+ free model providers with signup links, compatible with the HttpLLMBackend via LiteLLM proxy.
License
Apache 2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flossware_loom_ai-1.2.tar.gz.
File metadata
- Download URL: flossware_loom_ai-1.2.tar.gz
- Upload date:
- Size: 46.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6be6ac654c5f5bd26b31b0265ddf4bb077fb404e786a68dc42440b07b3a2ae74
|
|
| MD5 |
0f272e85e4bd34965b7327a850904b5b
|
|
| BLAKE2b-256 |
43855d9e1b6b71e23fafdd80ac142ad4cd15455ba80f0e91288174f622111e48
|
File details
Details for the file flossware_loom_ai-1.2-py3-none-any.whl.
File metadata
- Download URL: flossware_loom_ai-1.2-py3-none-any.whl
- Upload date:
- Size: 38.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8fab5d2d29593d48b3b18588814336e54ab302707c73070164b2ae4cf20b76bc
|
|
| MD5 |
6dec4217f64cb904b3adf6757033333c
|
|
| BLAKE2b-256 |
c21a666f7a398ff3914782c0a435fd5b965d809b82f9966890baa60d9bbad191
|