OpenSearch GenAI SDK
OTEL-native tracing and scoring for LLM applications. Instrument your AI workflows with standard OpenTelemetry spans and submit evaluation scores — all routed to OpenSearch through a single OTLP pipeline.
Features
- One-line setup —
register()configures the full OTEL pipeline (TracerProvider, exporter, auto-instrumentation) - Decorators —
@workflow,@task,@agent,@toolwrap functions as OTEL spans with GenAI semantic convention attributes - Auto-instrumentation — automatically discovers and activates installed instrumentor packages (OpenAI, Anthropic, Bedrock, LangChain, etc.)
- Scoring —
score()emits evaluation metrics as OTEL spans at span, trace, or session level - AWS SigV4 — built-in SigV4 signing for AWS-hosted OpenSearch and Data Prepper endpoints
- Zero lock-in — remove a decorator and your code still works; everything is standard OTEL
Requirements
- Python: 3.10, 3.11, 3.12, or 3.13
- OpenTelemetry SDK: ≥1.20.0, <2
Installation
pip install opensearch-genai-sdk-py
The core package includes the OTEL SDK and exporters. Auto-instrumentation of LLM libraries is opt-in — install only the providers you use:
# Single provider
pip install opensearch-genai-sdk-py[openai]
pip install opensearch-genai-sdk-py[anthropic]
pip install opensearch-genai-sdk-py[bedrock]
pip install opensearch-genai-sdk-py[langchain]
# Multiple providers
pip install "opensearch-genai-sdk-py[openai,anthropic]"
# All instrumentors at once
pip install opensearch-genai-sdk-py[instrumentors]
# AWS SigV4 signing for OpenSearch Ingestion / OpenSearch Service
pip install opensearch-genai-sdk-py[aws]
# Everything
pip install opensearch-genai-sdk-py[all]
Available extras: openai, anthropic, cohere, mistral, groq, ollama, google, bedrock, langchain, llamaindex, instrumentors (all of the above), aws, all
Quick Start
from opensearch_genai_sdk_py import register, workflow, agent, tool, score
# 1. Initialize tracing (one line)
register(endpoint="http://localhost:4318/v1/traces")
# 2. Decorate your functions
@tool("get_weather")
def get_weather(city: str) -> dict:
"""Fetch weather data for a city."""
return {"city": city, "temp": 22, "condition": "sunny"}
@agent("weather_assistant")
def assistant(query: str) -> str:
data = get_weather("Paris")
return f"{data['condition']}, {data['temp']}C"
@workflow("weather_query")
def run(query: str) -> str:
return assistant(query)
result = run("What's the weather?")
# 3. Submit scores (after workflow completes)
score(name="relevance", value=0.95, trace_id="...", source="llm-judge")
Architecture
┌─────────────────────────────────────────────────────┐
│ Your Application │
│ │
│ @workflow ─→ @agent ─→ @tool score() │
│ │ │ │ │ │
│ └────────────┴─────────┴────────┘ │
│ │ │
│ opensearch-genai-sdk-py │
├─────────────────────────────────────────────────────┤
│ register() │
│ ┌─────────────────────────────────────────────┐ │
│ │ TracerProvider │ │
│ │ ├── Resource (service.name) │ │
│ │ ├── BatchSpanProcessor │ │
│ │ │ └── OTLPSpanExporter (HTTP or gRPC) │ │
│ │ │ └── SigV4 signing (AWS endpoints) │ │
│ │ └── Auto-instrumentation │ │
│ │ ├── openai, anthropic, bedrock, ... │ │
│ │ ├── langchain, llamaindex, haystack │ │
│ │ └── chromadb, pinecone, qdrant, ... │ │
│ └─────────────────────────────────────────────┘ │
└──────────────────────┬──────────────────────────────┘
│ OTLP (HTTP/gRPC)
▼
┌─────────────────┐
│ Data Prepper / │
│ OTEL Collector │
└────────┬────────┘
│
▼
┌─────────────────┐
│ OpenSearch │
│ ├── traces │
│ └── scores │
└─────────────────┘
API Reference
register()
Configures the OTEL tracing pipeline. Call once at startup.
register(
endpoint="https://pipeline.us-east-1.osis.amazonaws.com/v1/traces",
service_name="my-app",
auth="auto", # "auto"/"none" = plain (default) | "sigv4" = AWS SigV4
batch=True, # BatchSpanProcessor (True) or Simple (False)
auto_instrument=True, # discover installed instrumentor packages
)
Endpoint formats:
| URL scheme | Transport |
|---|---|
http:// / https:// |
HTTP (default) |
grpc:// |
gRPC (insecure) |
grpcs:// |
gRPC (TLS) |
Auth:
auth="auto"(default) — auto-detects AWS endpoints (*.amazonaws.com) and enables SigV4; uses plain HTTP for everything else.auth="sigv4"— always use SigV4 (requirespip install opensearch-genai-sdk-py[aws]).auth="none"— always plain HTTP, no signing.
Decorators
Four decorators for tracing application logic. Each creates an OTEL span with gen_ai.* semantic convention attributes.
| Decorator | Use for | Operation name | Span name format |
|---|---|---|---|
@workflow("name") |
Top-level orchestration | invoke_agent |
name |
@task("name") |
Units of work | invoke_agent |
name |
@agent("name") |
Autonomous agent logic | invoke_agent |
invoke_agent name |
@tool("name") |
Tool/function calls | execute_tool |
execute_tool name |
All decorators accept name (defaults to function's __qualname__) and version.
Attributes set automatically:
| Attribute | Set by |
|---|---|
gen_ai.operation.name |
All decorators |
gen_ai.agent.name / gen_ai.tool.name |
All decorators |
gen_ai.input.messages / gen_ai.output.messages |
@workflow, @task, @agent |
gen_ai.tool.call.arguments / gen_ai.tool.call.result |
@tool |
gen_ai.tool.type |
@tool (always "function") |
gen_ai.tool.description |
@tool (from docstring, if present) |
gen_ai.agent.version |
All decorators (when version is set) |
Supported function types: sync, async, generators, async generators. Errors are captured as span status + exception events.
@agent("research_agent", version=2)
async def research(query: str) -> str:
"""Agents create invoke_agent spans with gen_ai.agent.* attributes."""
result = await search_tool(query)
return summarize(result)
@tool("search")
def search_tool(query: str) -> list:
"""Docstring becomes gen_ai.tool.description. Input/output use gen_ai.tool.call.* attributes."""
return api.search(query)
score()
Submits evaluation scores as OTEL spans. Use any evaluation framework you prefer (autoevals, RAGAS, custom) and submit the results through score().
Three scoring levels:
# Span-level: score a specific LLM call or tool execution
score(
name="accuracy",
value=0.95,
trace_id="abc123",
span_id="def456",
explanation="Weather data matches ground truth",
source="heuristic",
)
# Trace-level: score an entire workflow
score(
name="relevance",
value=0.92,
trace_id="abc123",
explanation="Response addresses the user's query",
source="llm-judge",
)
# Session-level: score across multiple traces in a conversation
score(
name="user_satisfaction",
value=0.88,
conversation_id="session-123",
label="satisfied",
source="human",
)
Parameters:
| Parameter | Type | Description |
|---|---|---|
name |
str |
Metric name (e.g., "relevance", "factuality") |
value |
float |
Numeric score |
trace_id |
str |
Trace being scored (span/trace-level) |
span_id |
str |
Span being scored (span-level) |
conversation_id |
str |
Session being scored (session-level) |
label |
str |
Human-readable label ("pass", "relevant") |
explanation |
str |
Evaluator justification (truncated to 500 chars) |
response_id |
str |
LLM completion ID for correlation |
source |
str |
Score origin: "sdk", "human", "llm-judge", "heuristic" |
metadata |
dict |
Arbitrary key-value metadata |
Scores are emitted as gen_ai.evaluation.result spans with gen_ai.evaluation.* attributes, following the OTEL GenAI semantic conventions.
Auto-Instrumented Libraries
register() automatically discovers and activates any installed instrumentor packages via OTEL entry points. No code changes needed — install the extras for the providers you use and their calls are traced automatically.
| Category | Extras / packages |
|---|---|
| LLM providers | [openai], [anthropic], [cohere], [mistral], [groq], [ollama] |
| Cloud AI | [bedrock], [google] (Vertex AI + Generative AI) |
| Frameworks | [langchain], [llamaindex] |
| All of the above | [instrumentors] |
Additional instrumentors (Together, Replicate, Writer, Voyage AI, Aleph Alpha, SageMaker, watsonx, Haystack, CrewAI, Agno, MCP, Transformers, ChromaDB, Pinecone, Qdrant, Weaviate, Milvus, LanceDB, Marqo) are included in [instrumentors] but do not have individual extras.
Configuration
| Environment Variable | Description | Default |
|---|---|---|
OPENSEARCH_OTEL_ENDPOINT |
OTLP endpoint URL | http://localhost:21890/opentelemetry/v1/traces |
OTEL_SERVICE_NAME |
Service name for spans | "default" |
OPENSEARCH_PROJECT |
Project/service name (fallback) | "default" |
AWS_DEFAULT_REGION |
AWS region for SigV4 | auto-detected |
License
Apache-2.0
Metadata
Release files for opensearch-genai-sdk-py 0.2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| opensearch_genai_sdk_py-0.2.5.tar.gz | 26.1 kB | With provenance | Details for opensearch_genai_sdk_py-0.2.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| opensearch_genai_sdk_py-0.2.5-py3-none-any.whl | Python 3 | none | any | Details for opensearch_genai_sdk_py-0.2.5-py3-none-any.whl |
Total release size: 46.5 kB
Release files / opensearch_genai_sdk_py-0.2.5.tar.gz
| Download URL | opensearch_genai_sdk_py-0.2.5.tar.gz |
|---|---|
| Size | 26.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bf2f86c29d8a5d998b11822da6dceeee176af95f52efa2c279b13aaffbfc788b
|
|
BLAKE2b-256 checksum How to use checksums |
3e60ebf38cff08b27513b60dedc69f8d703f576aa12beda51e57ad94fb5f3738
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 27, 2026.
Transparency logRelease files / opensearch_genai_sdk_py-0.2.5-py3-none-any.whl
| Download URL | opensearch_genai_sdk_py-0.2.5-py3-none-any.whl |
|---|---|
| Size | 20.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ae4565f08432a535d2a35ca1deb41c1169af656da5b42955b05490f01335312b
|
|
BLAKE2b-256 checksum How to use checksums |
2b0d7e3bc1974360b44a1ef5e450bb1671cebd87db0f686c56a757ff52542e7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 27, 2026.
Transparency logSecurity for opensearch-genai-sdk-py 0.2.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for opensearch_genai_sdk_py-0.2.5.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.