Skip to content

Integrations

The protoprompt core keeps zero required dependencies. Everything external arrives via optional extras; imports happen inside constructors, so protoprompt.integrations itself is instant to import.

LLM clients

Full clients implement the backwards-compatible LLMClientProtocol (chat + embed). Narrow integrations may implement only ChatClientProtocol or EmbeddingClientProtocol; CompositeLLMClient pairs independent capabilities.

Class Extra Targets
integrations.OpenAIClient [openai] OpenAI, LiteLLM, vLLM (via base_url)
integrations.OllamaClient [ollama] local/remote Ollama (/api/chat, /api/embed)
integrations.HttpxLLMClient [http] any OpenAI-compatible REST (LM Studio, llama.cpp)
integrations.AnthropicClient [anthropic] native Anthropic Messages API (chat)
integrations.GoogleGenAIClient [google] Gemini Developer API / Vertex AI (chat + embed)
integrations.BedrockConverseClient [bedrock] Amazon Bedrock Converse (chat)

See the provider and framework matrix for native token counting, auth semantics, PydanticAI/LlamaIndex bridges, and the Google ADK support decision.

from protoprompt import ContextBuilder, ContextInput, InMemStore
from protoprompt.integrations import OllamaClient

llm = OllamaClient(host="http://localhost:11434")
builder = ContextBuilder(InMemStore(), llm)

HttpxLLMClient accepts a transport= (e.g. httpx.MockTransport) — handy for network-free tests.

API-free embeddings

These classes implement only EmbeddingClientProtocol and do not pretend to be chat models.

Class Extra Notes
SentenceTransformersClient [local] HF models on CPU/GPU
FastEmbedClient [fastembed] ONNX runtime, light install

Both encode batches in a worker thread (asyncio.to_thread) and never block the event loop.

from protoprompt import CompositeLLMClient
from protoprompt.integrations import FastEmbedClient, OpenAIClient

llm = CompositeLLMClient(
    chat_client=OpenAIClient(),
    embedding_client=FastEmbedClient(),
)

Vector stores

Class Source Notes
SqliteStore (core) dependency-free persistent, replace-on-add
QdrantStore [qdrant] server (url=), embedded local (path=), in-memory
ChromaStore [chroma] as before
PgVectorStore [postgres] async pgvector, explicit schema setup
PostgresMemoryLedger [postgres] experimental synchronous Ledger; fresh-v7 dedicated schema
ElasticsearchStore [elasticsearch] Elasticsearch 9 dense vectors
OpenSearchStore [opensearch] OpenSearch Lucene HNSW

Redis supplies embedding cache, session, and profile adapters rather than vector retrieval. PostgresMemoryLedger is not a vector store or an async adapter: it explicitly provisions an isolated PostgreSQL schema and serializes Ledger writes with a transaction-scoped advisory lock. See PostgreSQL, Redis, and Elasticsearch/OpenSearch.

Managed credential stores are AWSSecretsManagerStore ([aws-secrets]) and GCPSecretManagerStore ([gcp-secrets]); see Secrets. Local document ingestion and framework converters are covered by Readers, and the authenticated service recipe by FastAPI.

Tenant/user/thread isolation

The host application pins a MemoryScope to DocumentIndexer, Retriever, ContextBuilder, and Pipeline. The model receives no parameter with which it could switch tenants. Scope maps to the same metadata keys in every store, and the internal doc_id gets a deterministic namespace, so identical logical IDs from different users never overwrite each other.

from protoprompt import ContextBuilder, MemoryScope, Pipeline
from protoprompt.rag import DocumentIndexer

scope = MemoryScope(tenant="acme", user="u-42", thread="support-chat")
indexer = DocumentIndexer(store, embedding_client, scope=scope)
builder = ContextBuilder(store, embedding_client, scope=scope)
pipeline = Pipeline(
    store,
    chat_client=chat_client,
    embedding_client=embedding_client,
    scope=scope,
)

An empty MemoryScope() and an omitted scope preserve the 0.3 storage layout, allowing one-tenant-at-a-time migration without rewriting all data. kind is useful for single-purpose adapters; a builder that reads both RAG and session memory will normally leave it empty (kind="").

Async stores

Any store can run asynchronously:

from protoprompt import as_async, AsyncInMemStore

# ready-made async twin of InMemStore
store = AsyncInMemStore()

# or wrap a sync backend: every call is dispatched to a thread
store = as_async(ChromaStore(persist_dir="./chroma"))

Builders and the Pipeline accept sync and async stores alike.

Embedding cache

from protoprompt import CachedLLMClient, InMemoryEmbeddingCache

cached = CachedLLMClient(OllamaClient(), InMemoryEmbeddingCache(capacity=4096))
# repeated build() calls with the same query skip the model entirely

Observability hooks

New integrations should use typed events: ContextEvent, RetrieveEvent, CompressEvent, ProfileEvent, RecallEvent, EvictEvent, and CacheEvent. Each carries a trace_id, opaque scope_id, duration, and safe metrics. EventDispatcher recursively redacts prompt, content, document, profile, secret, token, and other content-bearing fields by default.

from protoprompt import ContextBuilder, EventDispatcher

events = EventDispatcher(lambda event: telemetry.emit(event.to_dict()))
builder = ContextBuilder(store, embeddings, scope=scope, event_sink=events)

Existing ContextHooks and PipelineHooks remain supported: the typed event is sent first, followed by the compatibility hook. Observer failures are logged and never interrupt the main operation.

from protoprompt import ContextHooks, PipelineHooks, TokenBudgetedContextBuilder

hooks = ContextHooks(
    on_section_used=lambda label, tokens: print(f"+{tokens} {label}"),
    on_block_dropped=lambda label, reason: print(f"-{label} ({reason})"),
    on_build_done=lambda report: print(f"total: {report.used_tokens}"),
)
builder = TokenBudgetedContextBuilder(store, llm, hooks=hooks)

Legacy hooks may receive the original Session or BudgetReport, so treat them as a trusted in-process API. Use typed events for external export.

Contract kit for adapter authors

protoprompt.testing provides executable contracts for chat clients, embeddings, and vector/profile/secret stores. It has no pytest dependency and checks sync and async implementations through the same API:

from protoprompt.testing import check_chat_client, check_vector_store

await check_chat_client(client)
report = await check_vector_store(store)
print(report.checks)

Official adapters run these exact contracts in CI. No live credentials are required: HTTP clients use a local transport and server-backed stores use an isolated test collection.

Ownership and deprecation

Adapters shipped in the protoprompt distribution are maintained by the EnergoAI Hub/core maintainer group. Their supported upstream ranges are pinned in pyproject.toml; contract tests and at least one runnable example are the acceptance boundary. A community adapter without an active owner remains an external recipe and is not presented as officially supported.

An official adapter is documented as deprecated and listed in the changelog for at least one minor release before removal. Removal normally waits for the next major release and must include a replacement or migration path plus an explicit rollback. An urgent security issue may disable unsafe behaviour earlier, with the migration and rollback note shipped in the same release.