Extensions¶
The extensions module provides OpenInference-compatible span instrumentation for custom pipeline steps -- retrieval, embedding, reranking, tool calls, and guardrails -- without depending on LlamaIndex or LangChain auto-instrumentors.
- Python:
coalex.extmodule with decorator syntax (@retrieval_span,@tool_span, etc.) - TypeScript:
@coalex-ai/sdk/extwith wrapper function syntax (retrievalSpan(),toolSpan(), etc.)
When to Use Extensions¶
Use extension decorators when:
- You have custom retrieval, embedding, or reranking logic that is not covered by auto-instrumentation.
- You want to instrument tool calls or guardrail checks as first-class spans.
- You are building a RAG pipeline from scratch without LlamaIndex or LangChain.
- You need fine-grained control over span attributes (via context managers).
Extensions complement auto-instrumentation
You can use coalex.auto_instrument() for LLM calls and extension decorators for your custom steps. They work together -- all spans appear in the same trace.
Available Extensions¶
Decorators (Python) / Wrapper Functions (TypeScript)¶
Each extension wraps a function and creates an OpenInference-compatible span with the appropriate openinference.span.kind.
| Python Decorator | TypeScript Wrapper | Span Kind | Use Case |
|---|---|---|---|
@retrieval_span |
retrievalSpan() |
RETRIEVER |
Document retrieval from a knowledge base, vector store, or API |
@embedding_span |
embeddingSpan() |
EMBEDDING |
Text-to-vector embedding calls |
@reranker_span |
rerankerSpan() |
RERANKER |
Re-scoring and reordering retrieved documents |
@tool_span |
toolSpan() |
TOOL |
External tool or function calls (APIs, databases, calculators) |
@guardrail_span |
guardrailSpan() |
GUARDRAIL |
Input/output validation and safety checks |
Context Managers¶
For cases where you need fine-grained control over when attributes are set (e.g., streaming, multi-step operations), three extensions provide context manager alternatives:
| Context Manager | Decorator Equivalent | Reference |
|---|---|---|
RetrievalSpan |
@retrieval_span |
Details |
EmbeddingSpan |
@embedding_span |
Details |
RerankerSpan |
@reranker_span |
Details |
No context managers for @tool_span and @guardrail_span
@tool_span and @guardrail_span are decorator-only. They do not have context manager alternatives because their attribute-setting logic is straightforward and does not benefit from deferred attribute assignment.
Data Classes¶
| Class | Module | Description |
|---|---|---|
Document |
coalex.ext.retrieval |
A retrieved document with content, id, score, and metadata fields. Used by @retrieval_span and @reranker_span. |
Utility Functions¶
| Function | Module | Description |
|---|---|---|
encode_documents() |
coalex.ext.retrieval |
Serializes a list[Document] to an OpenInference-compatible JSON string. |
Import Patterns¶
# Import individual decorators
from coalex.ext.retrieval import retrieval_span, Document
from coalex.ext.embedding import embedding_span
from coalex.ext.reranker import reranker_span
from coalex.ext.tool import tool_span
from coalex.ext.guardrail import guardrail_span
# Or import everything from the ext package
from coalex.ext import (
retrieval_span, RetrievalSpan, Document, encode_documents,
embedding_span, EmbeddingSpan,
reranker_span, RerankerSpan,
tool_span,
guardrail_span,
)
// Import individual wrappers
import { retrievalSpan, type Document } from "@coalex-ai/sdk/ext";
import { embeddingSpan, EmbeddingSpan } from "@coalex-ai/sdk/ext";
import { rerankerSpan, RerankerSpan } from "@coalex-ai/sdk/ext";
import { toolSpan } from "@coalex-ai/sdk/ext";
import { guardrailSpan } from "@coalex-ai/sdk/ext";
// Or import everything from the ext entrypoint
import {
retrievalSpan, RetrievalSpan, encodeDocuments,
embeddingSpan, EmbeddingSpan,
rerankerSpan, RerankerSpan,
toolSpan,
guardrailSpan,
} from "@coalex-ai/sdk/ext";
Full RAG Pipeline Example¶
import coalex
from coalex.ext.retrieval import retrieval_span, Document
from coalex.ext.embedding import embedding_span
from coalex.ext.reranker import reranker_span
from coalex.ext.guardrail import guardrail_span
from coalex.ext.tool import tool_span
from openai import OpenAI
coalex.register(api_key="your-key")
coalex.auto_instrument()
client = OpenAI()
@embedding_span(name="embed_query", model_name="text-embedding-3-small")
def embed(text: str) -> list[float]:
resp = client.embeddings.create(model="text-embedding-3-small", input=text)
return resp.data[0].embedding
@retrieval_span(name="search_knowledge_base", query_arg="query")
def retrieve(query: str) -> list[Document]:
vector = embed(text=query)
# ... search your vector store with `vector` ...
return [
Document(content="...", id="doc-1", score=0.95),
Document(content="...", id="doc-2", score=0.87),
]
@reranker_span(name="rerank_results", model_name="rerank-v3", top_k=3)
def rerank(query: str, documents: list[Document]) -> list[Document]:
# ... call your reranker API ...
return sorted(documents, key=lambda d: d.score or 0, reverse=True)[:3]
@guardrail_span(guardrail_name="pii_check")
def check_pii(text: str) -> float:
# Return a confidence score; raise to signal "fail"
if "SSN" in text:
raise ValueError("PII detected: SSN")
return 1.0
@tool_span(name="format_citation", description="Format a document as a citation")
def format_citation(doc_id: str, title: str) -> str:
return f"[{doc_id}] {title}"
with coalex.coalex_context(agent_id="rag-agent", request_id="req-001"):
docs = retrieve(query="What is the refund policy?")
ranked = rerank(query="What is the refund policy?", documents=docs)
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": f"Context: {ranked[0].content}"},
{"role": "user", "content": "What is the refund policy?"},
],
)
answer = response.choices[0].message.content
check_pii(answer)
citation = format_citation(doc_id=ranked[0].id, title="Refund Policy")
import { register, coalexContext, autoInstrument } from "@coalex-ai/sdk";
import {
retrievalSpan, embeddingSpan, rerankerSpan,
guardrailSpan, toolSpan, type Document,
} from "@coalex-ai/sdk/ext";
import OpenAI from "openai";
register({ apiKey: "your-key" });
autoInstrument();
const client = new OpenAI();
const embed = embeddingSpan(
{ name: "embed_query", modelName: "text-embedding-3-small" },
async (text: string): Promise<number[]> => {
const resp = await client.embeddings.create({ model: "text-embedding-3-small", input: text });
return resp.data[0].embedding;
},
);
const retrieve = retrievalSpan(
{ name: "search_knowledge_base" },
async (query: string): Promise<Document[]> => {
const vector = await embed(query);
// ... search your vector store with `vector` ...
return [
{ content: "...", id: "doc-1", score: 0.95 },
{ content: "...", id: "doc-2", score: 0.87 },
];
},
);
const rerank = rerankerSpan(
{ name: "rerank_results", modelName: "rerank-v3", topK: 3 },
async (query: string, documents: Document[]): Promise<Document[]> => {
// ... call your reranker API ...
return [...documents].sort((a, b) => (b.score ?? 0) - (a.score ?? 0)).slice(0, 3);
},
);
const checkPii = guardrailSpan(
{ guardrailName: "pii_check" },
async (text: string): Promise<number> => {
if (text.includes("SSN")) throw new Error("PII detected: SSN");
return 1.0;
},
);
const formatCitation = toolSpan(
{ name: "format_citation", description: "Format a document as a citation" },
async (docId: string, title: string): Promise<string> => {
return `[${docId}] ${title}`;
},
);
await coalexContext({ agentId: "rag-agent", requestId: "req-001" }, async () => {
const docs = await retrieve("What is the refund policy?");
const ranked = await rerank("What is the refund policy?", docs);
const response = await client.chat.completions.create({
model: "gpt-4o",
messages: [
{ role: "system", content: `Context: ${ranked[0].content}` },
{ role: "user", content: "What is the refund policy?" },
],
});
const answer = response.choices[0].message.content!;
await checkPii(answer);
const citation = await formatCitation(ranked[0].id!, "Refund Policy");
});
Async Support¶
All decorators support both synchronous and asynchronous functions. The decorator automatically detects whether the wrapped function is a coroutine and handles it correctly:
All wrapper functions support both synchronous and asynchronous functions. The wrapped function always returns a Promise:
API Reference¶
coalex.ext ¶
coalex.ext — OpenInference-compatible span decorators for RAG pipelines.
Use these decorators to instrument custom retrieval, embedding, reranking, tool, and guardrail logic without depending on LlamaIndex or LangChain auto-instrumentors.
Example::
from coalex.ext.retrieval import retrieval_span, Document
@retrieval_span(name="pubmed_retrieval", query_arg="query")
def retrieve(query: str) -> list[Document]:
...
return [Document(content=abstract, id=pmid)]
Classes¶
EmbeddingSpan ¶
Context manager for instrumenting an embedding call as an EMBEDDING span.
Example::
with EmbeddingSpan("embed", model_name="text-embedding-3-small") as e:
e.set_text(text)
vector = embed(text)
e.set_vector(vector, text)
Source code in coalex/ext/embedding.py
RerankerSpan ¶
Context manager for instrumenting a reranking step as a RERANKER span.
Example::
with RerankerSpan("rerank", model_name="rerank-v3", top_k=5) as r:
r.set_query(query)
r.set_input_documents(docs)
ranked = reranker.rerank(query, docs, top_k=5)
r.set_output_documents(ranked)
Source code in coalex/ext/reranker.py
Document
dataclass
¶
A retrieved document with OpenInference-compatible fields.
Source code in coalex/ext/retrieval.py
RetrievalSpan ¶
Context manager for instrumenting retrieval logic as a RETRIEVER span.
Use when you need fine-grained control over when documents and query are attached (e.g. streaming or multi-step retrieval).
Example::
with RetrievalSpan("my_retrieval") as r:
r.set_query(query)
docs = fetch_documents(query)
r.set_documents(docs)
Source code in coalex/ext/retrieval.py
Functions¶
embedding_span ¶
embedding_span(
name: str | None = None,
model_name: str | None = None,
query_arg: str = "text",
) -> Callable[[F], F]
Decorator that wraps an embedding function with an OpenInference EMBEDDING span.
Supports both sync and async functions. The span captures:
- openinference.span.kind = EMBEDDING
- embedding.model_name — if provided
- input.value — text being embedded
- embedding.embeddings — JSON-encoded vector if function returns list[float]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Span name. Defaults to the function name. |
None
|
model_name
|
str | None
|
Embedding model name to record. |
None
|
query_arg
|
str
|
Name of the kwarg containing the text to embed. |
'text'
|
Source code in coalex/ext/embedding.py
guardrail_span ¶
Decorator that wraps a guardrail function with an OpenInference GUARDRAIL span.
Supports both sync and async functions. The span captures:
- openinference.span.kind = GUARDRAIL
- guardrail.name — from guardrail_name or the function name
- guardrail.result — "pass" if no exception raised, "fail" otherwise
- guardrail.score — set this via the return value if it is a float
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Span name. Defaults to the function name. |
None
|
guardrail_name
|
str | None
|
Logical guardrail name recorded as an attribute. |
None
|
Source code in coalex/ext/guardrail.py
reranker_span ¶
reranker_span(
name: str | None = None,
model_name: str | None = None,
query_arg: str = "query",
docs_arg: str = "documents",
top_k: int | None = None,
) -> Callable[[F], F]
Decorator that wraps a reranker function with an OpenInference RERANKER span.
Supports both sync and async functions. The decorated function must accept a
list[Document] as input and return list[Document] as output. The span captures:
- openinference.span.kind = RERANKER
- reranker.model_name — if provided
- reranker.query — from query_arg kwarg or first str positional
- reranker.top_k — if provided
- reranker.input_documents — JSON-encoded input docs
- reranker.output_documents — JSON-encoded output docs
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Span name. Defaults to the function name. |
None
|
model_name
|
str | None
|
Reranker model name to record. |
None
|
query_arg
|
str
|
Name of the kwarg containing the query string. |
'query'
|
docs_arg
|
str
|
Name of the kwarg containing the input documents list. |
'documents'
|
top_k
|
int | None
|
Number of top documents to return (recorded as attribute). |
None
|
Source code in coalex/ext/reranker.py
encode_documents ¶
Serialize documents to OpenInference retrieval.documents JSON string.
retrieval_span ¶
Decorator that wraps a retrieval function with an OpenInference RETRIEVER span.
Supports both sync and async functions. The decorated function must return
list[Document]. The span captures:
- openinference.span.kind = RETRIEVER
- input.value — query string (from query_arg kwarg or first str positional)
- retrieval.documents — JSON-encoded list of documents
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Span name. Defaults to the function name. |
None
|
query_arg
|
str
|
Name of the kwarg containing the query string. |
'query'
|
Source code in coalex/ext/retrieval.py
tool_span ¶
Decorator that wraps a tool function with an OpenInference TOOL span.
Supports both sync and async functions. The span captures:
- openinference.span.kind = TOOL
- tool.name — span name
- tool.description — if provided
- tool.parameters — JSON-encoded kwargs passed to the function
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Tool name and span name. Defaults to the function name. |
None
|
description
|
str | None
|
Human-readable tool description. |
None
|