diff --git a/langfuse/api/__init__.py b/langfuse/api/__init__.py
index 3dd6de4e4..ce613a95d 100644
--- a/langfuse/api/__init__.py
+++ b/langfuse/api/__init__.py
@@ -136,6 +136,14 @@
OptionalObservationBody,
OrganizationProject,
OrganizationProjectsResponse,
+ OtelAttribute,
+ OtelAttributeValue,
+ OtelResource,
+ OtelResourceSpan,
+ OtelScope,
+ OtelScopeSpan,
+ OtelSpan,
+ OtelTraceResponse,
PaginatedAnnotationQueueItems,
PaginatedAnnotationQueues,
PaginatedDatasetItems,
@@ -153,6 +161,7 @@
Prompt,
PromptMeta,
PromptMetaListResponse,
+ PromptType,
Prompt_Chat,
Prompt_Text,
ResourceMeta,
@@ -221,6 +230,7 @@
metrics,
models,
observations,
+ opentelemetry,
organizations,
projects,
prompt_version,
@@ -370,6 +380,14 @@
"OptionalObservationBody",
"OrganizationProject",
"OrganizationProjectsResponse",
+ "OtelAttribute",
+ "OtelAttributeValue",
+ "OtelResource",
+ "OtelResourceSpan",
+ "OtelScope",
+ "OtelScopeSpan",
+ "OtelSpan",
+ "OtelTraceResponse",
"PaginatedAnnotationQueueItems",
"PaginatedAnnotationQueues",
"PaginatedDatasetItems",
@@ -387,6 +405,7 @@
"Prompt",
"PromptMeta",
"PromptMetaListResponse",
+ "PromptType",
"Prompt_Chat",
"Prompt_Text",
"ResourceMeta",
@@ -455,6 +474,7 @@
"metrics",
"models",
"observations",
+ "opentelemetry",
"organizations",
"projects",
"prompt_version",
diff --git a/langfuse/api/client.py b/langfuse/api/client.py
index 619e649fa..646279b5a 100644
--- a/langfuse/api/client.py
+++ b/langfuse/api/client.py
@@ -30,6 +30,10 @@
from .resources.metrics.client import AsyncMetricsClient, MetricsClient
from .resources.models.client import AsyncModelsClient, ModelsClient
from .resources.observations.client import AsyncObservationsClient, ObservationsClient
+from .resources.opentelemetry.client import (
+ AsyncOpentelemetryClient,
+ OpentelemetryClient,
+)
from .resources.organizations.client import (
AsyncOrganizationsClient,
OrganizationsClient,
@@ -136,6 +140,7 @@ def __init__(
self.metrics = MetricsClient(client_wrapper=self._client_wrapper)
self.models = ModelsClient(client_wrapper=self._client_wrapper)
self.observations = ObservationsClient(client_wrapper=self._client_wrapper)
+ self.opentelemetry = OpentelemetryClient(client_wrapper=self._client_wrapper)
self.organizations = OrganizationsClient(client_wrapper=self._client_wrapper)
self.projects = ProjectsClient(client_wrapper=self._client_wrapper)
self.prompt_version = PromptVersionClient(client_wrapper=self._client_wrapper)
@@ -240,6 +245,9 @@ def __init__(
self.metrics = AsyncMetricsClient(client_wrapper=self._client_wrapper)
self.models = AsyncModelsClient(client_wrapper=self._client_wrapper)
self.observations = AsyncObservationsClient(client_wrapper=self._client_wrapper)
+ self.opentelemetry = AsyncOpentelemetryClient(
+ client_wrapper=self._client_wrapper
+ )
self.organizations = AsyncOrganizationsClient(
client_wrapper=self._client_wrapper
)
diff --git a/langfuse/api/reference.md b/langfuse/api/reference.md
index f2e9baa07..199c9421b 100644
--- a/langfuse/api/reference.md
+++ b/langfuse/api/reference.md
@@ -2442,7 +2442,7 @@ client.health.health()
**Legacy endpoint for batch ingestion for Langfuse Observability.**
--> Please use the OpenTelemetry endpoint (`/api/public/otel`). Learn more: https://langfuse.com/integrations/native/opentelemetry
+-> Please use the OpenTelemetry endpoint (`/api/public/otel/v1/traces`). Learn more: https://langfuse.com/integrations/native/opentelemetry
Within each batch, there can be multiple events.
Each event has a type, an id, a timestamp, metadata and a body.
@@ -3604,6 +3604,184 @@ client.observations.get_many()
-
+**filter:** `typing.Optional[str]`
+
+JSON string containing an array of filter conditions. When provided, this takes precedence over legacy filter parameters (userId, name, sessionId, tags, version, release, environment, fromTimestamp, toTimestamp).
+Each filter condition has the following structure:
+```json
+[
+ {
+ "type": string, // Required. One of: "datetime", "string", "number", "stringOptions", "categoryOptions", "arrayOptions", "stringObject", "numberObject", "boolean", "null"
+ "column": string, // Required. Column to filter on
+ "operator": string, // Required. Operator based on type:
+ // - datetime: ">", "<", ">=", "<="
+ // - string: "=", "contains", "does not contain", "starts with", "ends with"
+ // - stringOptions: "any of", "none of"
+ // - categoryOptions: "any of", "none of"
+ // - arrayOptions: "any of", "none of", "all of"
+ // - number: "=", ">", "<", ">=", "<="
+ // - stringObject: "=", "contains", "does not contain", "starts with", "ends with"
+ // - numberObject: "=", ">", "<", ">=", "<="
+ // - boolean: "=", "<>"
+ // - null: "is null", "is not null"
+ "value": any, // Required (except for null type). Value to compare against. Type depends on filter type
+ "key": string // Required only for stringObject, numberObject, and categoryOptions types when filtering on nested fields like metadata
+ }
+]
+```
+
+
+
+
+
+-
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
+
+
+
+
+
+
+
+
+
+
+
+## Opentelemetry
+client.opentelemetry.export_traces(...)
+
+-
+
+#### 📝 Description
+
+
+-
+
+
+-
+
+**OpenTelemetry Traces Ingestion Endpoint**
+
+This endpoint implements the OTLP/HTTP specification for trace ingestion, providing native OpenTelemetry integration for Langfuse Observability.
+
+**Supported Formats:**
+- Binary Protobuf: `Content-Type: application/x-protobuf`
+- JSON Protobuf: `Content-Type: application/json`
+- Supports gzip compression via `Content-Encoding: gzip` header
+
+**Specification Compliance:**
+- Conforms to [OTLP/HTTP Trace Export](https://opentelemetry.io/docs/specs/otlp/#otlphttp)
+- Implements `ExportTraceServiceRequest` message format
+
+**Documentation:**
+- Integration guide: https://langfuse.com/integrations/native/opentelemetry
+- Data model: https://langfuse.com/docs/observability/data-model
+
+
+
+
+
+#### 🔌 Usage
+
+
+-
+
+
+-
+
+```python
+from langfuse import (
+ OtelAttribute,
+ OtelAttributeValue,
+ OtelResource,
+ OtelResourceSpan,
+ OtelScope,
+ OtelScopeSpan,
+ OtelSpan,
+)
+from langfuse.client import FernLangfuse
+
+client = FernLangfuse(
+ x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME",
+ x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION",
+ x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY",
+ username="YOUR_USERNAME",
+ password="YOUR_PASSWORD",
+ base_url="https://yourhost.com/path/to/api",
+)
+client.opentelemetry.export_traces(
+ resource_spans=[
+ OtelResourceSpan(
+ resource=OtelResource(
+ attributes=[
+ OtelAttribute(
+ key="service.name",
+ value=OtelAttributeValue(
+ string_value="my-service",
+ ),
+ ),
+ OtelAttribute(
+ key="service.version",
+ value=OtelAttributeValue(
+ string_value="1.0.0",
+ ),
+ ),
+ ],
+ ),
+ scope_spans=[
+ OtelScopeSpan(
+ scope=OtelScope(
+ name="langfuse-sdk",
+ version="2.60.3",
+ ),
+ spans=[
+ OtelSpan(
+ trace_id="0123456789abcdef0123456789abcdef",
+ span_id="0123456789abcdef",
+ name="my-operation",
+ kind=1,
+ start_time_unix_nano="1747872000000000000",
+ end_time_unix_nano="1747872001000000000",
+ attributes=[
+ OtelAttribute(
+ key="langfuse.observation.type",
+ value=OtelAttributeValue(
+ string_value="generation",
+ ),
+ )
+ ],
+ status={},
+ )
+ ],
+ )
+ ],
+ )
+ ],
+)
+
+```
+
+
+
+
+
+#### ⚙️ Parameters
+
+
+-
+
+
+-
+
+**resource_spans:** `typing.Sequence[OtelResourceSpan]` — Array of resource spans containing trace data as defined in the OTLP specification
+
+
+
+
+
+-
+
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
diff --git a/langfuse/api/resources/__init__.py b/langfuse/api/resources/__init__.py
index ae77cad9d..49e7a40ee 100644
--- a/langfuse/api/resources/__init__.py
+++ b/langfuse/api/resources/__init__.py
@@ -15,6 +15,7 @@
metrics,
models,
observations,
+ opentelemetry,
organizations,
projects,
prompt_version,
@@ -175,6 +176,16 @@
from .metrics import MetricsResponse
from .models import CreateModelRequest, PaginatedModels
from .observations import Observations, ObservationsViews
+from .opentelemetry import (
+ OtelAttribute,
+ OtelAttributeValue,
+ OtelResource,
+ OtelResourceSpan,
+ OtelScope,
+ OtelScopeSpan,
+ OtelSpan,
+ OtelTraceResponse,
+)
from .organizations import (
DeleteMembershipRequest,
MembershipDeletionResponse,
@@ -210,6 +221,7 @@
Prompt,
PromptMeta,
PromptMetaListResponse,
+ PromptType,
Prompt_Chat,
Prompt_Text,
TextPrompt,
@@ -389,6 +401,14 @@
"OptionalObservationBody",
"OrganizationProject",
"OrganizationProjectsResponse",
+ "OtelAttribute",
+ "OtelAttributeValue",
+ "OtelResource",
+ "OtelResourceSpan",
+ "OtelScope",
+ "OtelScopeSpan",
+ "OtelSpan",
+ "OtelTraceResponse",
"PaginatedAnnotationQueueItems",
"PaginatedAnnotationQueues",
"PaginatedDatasetItems",
@@ -406,6 +426,7 @@
"Prompt",
"PromptMeta",
"PromptMetaListResponse",
+ "PromptType",
"Prompt_Chat",
"Prompt_Text",
"ResourceMeta",
@@ -474,6 +495,7 @@
"metrics",
"models",
"observations",
+ "opentelemetry",
"organizations",
"projects",
"prompt_version",
diff --git a/langfuse/api/resources/ingestion/client.py b/langfuse/api/resources/ingestion/client.py
index d5aa2f952..c009c507b 100644
--- a/langfuse/api/resources/ingestion/client.py
+++ b/langfuse/api/resources/ingestion/client.py
@@ -33,7 +33,7 @@ def batch(
"""
**Legacy endpoint for batch ingestion for Langfuse Observability.**
- -> Please use the OpenTelemetry endpoint (`/api/public/otel`). Learn more: https://langfuse.com/integrations/native/opentelemetry
+ -> Please use the OpenTelemetry endpoint (`/api/public/otel/v1/traces`). Learn more: https://langfuse.com/integrations/native/opentelemetry
Within each batch, there can be multiple events.
Each event has a type, an id, a timestamp, metadata and a body.
@@ -151,7 +151,7 @@ async def batch(
"""
**Legacy endpoint for batch ingestion for Langfuse Observability.**
- -> Please use the OpenTelemetry endpoint (`/api/public/otel`). Learn more: https://langfuse.com/integrations/native/opentelemetry
+ -> Please use the OpenTelemetry endpoint (`/api/public/otel/v1/traces`). Learn more: https://langfuse.com/integrations/native/opentelemetry
Within each batch, there can be multiple events.
Each event has a type, an id, a timestamp, metadata and a body.
diff --git a/langfuse/api/resources/observations/client.py b/langfuse/api/resources/observations/client.py
index b21981bb4..22c923399 100644
--- a/langfuse/api/resources/observations/client.py
+++ b/langfuse/api/resources/observations/client.py
@@ -107,6 +107,7 @@ def get_many(
from_start_time: typing.Optional[dt.datetime] = None,
to_start_time: typing.Optional[dt.datetime] = None,
version: typing.Optional[str] = None,
+ filter: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> ObservationsViews:
"""
@@ -145,6 +146,31 @@ def get_many(
version : typing.Optional[str]
Optional filter to only include observations with a certain version.
+ filter : typing.Optional[str]
+ JSON string containing an array of filter conditions. When provided, this takes precedence over legacy filter parameters (userId, name, sessionId, tags, version, release, environment, fromTimestamp, toTimestamp).
+ Each filter condition has the following structure:
+ ```json
+ [
+ {
+ "type": string, // Required. One of: "datetime", "string", "number", "stringOptions", "categoryOptions", "arrayOptions", "stringObject", "numberObject", "boolean", "null"
+ "column": string, // Required. Column to filter on
+ "operator": string, // Required. Operator based on type:
+ // - datetime: ">", "<", ">=", "<="
+ // - string: "=", "contains", "does not contain", "starts with", "ends with"
+ // - stringOptions: "any of", "none of"
+ // - categoryOptions: "any of", "none of"
+ // - arrayOptions: "any of", "none of", "all of"
+ // - number: "=", ">", "<", ">=", "<="
+ // - stringObject: "=", "contains", "does not contain", "starts with", "ends with"
+ // - numberObject: "=", ">", "<", ">=", "<="
+ // - boolean: "=", "<>"
+ // - null: "is null", "is not null"
+ "value": any, // Required (except for null type). Value to compare against. Type depends on filter type
+ "key": string // Required only for stringObject, numberObject, and categoryOptions types when filtering on nested fields like metadata
+ }
+ ]
+ ```
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -186,6 +212,7 @@ def get_many(
if to_start_time is not None
else None,
"version": version,
+ "filter": filter,
},
request_options=request_options,
)
@@ -311,6 +338,7 @@ async def get_many(
from_start_time: typing.Optional[dt.datetime] = None,
to_start_time: typing.Optional[dt.datetime] = None,
version: typing.Optional[str] = None,
+ filter: typing.Optional[str] = None,
request_options: typing.Optional[RequestOptions] = None,
) -> ObservationsViews:
"""
@@ -349,6 +377,31 @@ async def get_many(
version : typing.Optional[str]
Optional filter to only include observations with a certain version.
+ filter : typing.Optional[str]
+ JSON string containing an array of filter conditions. When provided, this takes precedence over legacy filter parameters (userId, name, sessionId, tags, version, release, environment, fromTimestamp, toTimestamp).
+ Each filter condition has the following structure:
+ ```json
+ [
+ {
+ "type": string, // Required. One of: "datetime", "string", "number", "stringOptions", "categoryOptions", "arrayOptions", "stringObject", "numberObject", "boolean", "null"
+ "column": string, // Required. Column to filter on
+ "operator": string, // Required. Operator based on type:
+ // - datetime: ">", "<", ">=", "<="
+ // - string: "=", "contains", "does not contain", "starts with", "ends with"
+ // - stringOptions: "any of", "none of"
+ // - categoryOptions: "any of", "none of"
+ // - arrayOptions: "any of", "none of", "all of"
+ // - number: "=", ">", "<", ">=", "<="
+ // - stringObject: "=", "contains", "does not contain", "starts with", "ends with"
+ // - numberObject: "=", ">", "<", ">=", "<="
+ // - boolean: "=", "<>"
+ // - null: "is null", "is not null"
+ "value": any, // Required (except for null type). Value to compare against. Type depends on filter type
+ "key": string // Required only for stringObject, numberObject, and categoryOptions types when filtering on nested fields like metadata
+ }
+ ]
+ ```
+
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
@@ -398,6 +451,7 @@ async def main() -> None:
if to_start_time is not None
else None,
"version": version,
+ "filter": filter,
},
request_options=request_options,
)
diff --git a/langfuse/api/resources/opentelemetry/__init__.py b/langfuse/api/resources/opentelemetry/__init__.py
new file mode 100644
index 000000000..bada2052f
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/__init__.py
@@ -0,0 +1,23 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from .types import (
+ OtelAttribute,
+ OtelAttributeValue,
+ OtelResource,
+ OtelResourceSpan,
+ OtelScope,
+ OtelScopeSpan,
+ OtelSpan,
+ OtelTraceResponse,
+)
+
+__all__ = [
+ "OtelAttribute",
+ "OtelAttributeValue",
+ "OtelResource",
+ "OtelResourceSpan",
+ "OtelScope",
+ "OtelScopeSpan",
+ "OtelSpan",
+ "OtelTraceResponse",
+]
diff --git a/langfuse/api/resources/opentelemetry/client.py b/langfuse/api/resources/opentelemetry/client.py
new file mode 100644
index 000000000..de17949d4
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/client.py
@@ -0,0 +1,317 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from ...core.api_error import ApiError
+from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ...core.pydantic_utilities import pydantic_v1
+from ...core.request_options import RequestOptions
+from ..commons.errors.access_denied_error import AccessDeniedError
+from ..commons.errors.error import Error
+from ..commons.errors.method_not_allowed_error import MethodNotAllowedError
+from ..commons.errors.not_found_error import NotFoundError
+from ..commons.errors.unauthorized_error import UnauthorizedError
+from .types.otel_resource_span import OtelResourceSpan
+from .types.otel_trace_response import OtelTraceResponse
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class OpentelemetryClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def export_traces(
+ self,
+ *,
+ resource_spans: typing.Sequence[OtelResourceSpan],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> OtelTraceResponse:
+ """
+ **OpenTelemetry Traces Ingestion Endpoint**
+
+ This endpoint implements the OTLP/HTTP specification for trace ingestion, providing native OpenTelemetry integration for Langfuse Observability.
+
+ **Supported Formats:**
+ - Binary Protobuf: `Content-Type: application/x-protobuf`
+ - JSON Protobuf: `Content-Type: application/json`
+ - Supports gzip compression via `Content-Encoding: gzip` header
+
+ **Specification Compliance:**
+ - Conforms to [OTLP/HTTP Trace Export](https://opentelemetry.io/docs/specs/otlp/#otlphttp)
+ - Implements `ExportTraceServiceRequest` message format
+
+ **Documentation:**
+ - Integration guide: https://langfuse.com/integrations/native/opentelemetry
+ - Data model: https://langfuse.com/docs/observability/data-model
+
+ Parameters
+ ----------
+ resource_spans : typing.Sequence[OtelResourceSpan]
+ Array of resource spans containing trace data as defined in the OTLP specification
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ OtelTraceResponse
+
+ Examples
+ --------
+ from langfuse import (
+ OtelAttribute,
+ OtelAttributeValue,
+ OtelResource,
+ OtelResourceSpan,
+ OtelScope,
+ OtelScopeSpan,
+ OtelSpan,
+ )
+ from langfuse.client import FernLangfuse
+
+ client = FernLangfuse(
+ x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME",
+ x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION",
+ x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY",
+ username="YOUR_USERNAME",
+ password="YOUR_PASSWORD",
+ base_url="https://yourhost.com/path/to/api",
+ )
+ client.opentelemetry.export_traces(
+ resource_spans=[
+ OtelResourceSpan(
+ resource=OtelResource(
+ attributes=[
+ OtelAttribute(
+ key="service.name",
+ value=OtelAttributeValue(
+ string_value="my-service",
+ ),
+ ),
+ OtelAttribute(
+ key="service.version",
+ value=OtelAttributeValue(
+ string_value="1.0.0",
+ ),
+ ),
+ ],
+ ),
+ scope_spans=[
+ OtelScopeSpan(
+ scope=OtelScope(
+ name="langfuse-sdk",
+ version="2.60.3",
+ ),
+ spans=[
+ OtelSpan(
+ trace_id="0123456789abcdef0123456789abcdef",
+ span_id="0123456789abcdef",
+ name="my-operation",
+ kind=1,
+ start_time_unix_nano="1747872000000000000",
+ end_time_unix_nano="1747872001000000000",
+ attributes=[
+ OtelAttribute(
+ key="langfuse.observation.type",
+ value=OtelAttributeValue(
+ string_value="generation",
+ ),
+ )
+ ],
+ status={},
+ )
+ ],
+ )
+ ],
+ )
+ ],
+ )
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "api/public/otel/v1/traces",
+ method="POST",
+ json={"resourceSpans": resource_spans},
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return pydantic_v1.parse_obj_as(OtelTraceResponse, _response.json()) # type: ignore
+ if _response.status_code == 400:
+ raise Error(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ if _response.status_code == 403:
+ raise AccessDeniedError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ if _response.status_code == 405:
+ raise MethodNotAllowedError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ if _response.status_code == 404:
+ raise NotFoundError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, body=_response.text)
+ raise ApiError(status_code=_response.status_code, body=_response_json)
+
+
+class AsyncOpentelemetryClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def export_traces(
+ self,
+ *,
+ resource_spans: typing.Sequence[OtelResourceSpan],
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> OtelTraceResponse:
+ """
+ **OpenTelemetry Traces Ingestion Endpoint**
+
+ This endpoint implements the OTLP/HTTP specification for trace ingestion, providing native OpenTelemetry integration for Langfuse Observability.
+
+ **Supported Formats:**
+ - Binary Protobuf: `Content-Type: application/x-protobuf`
+ - JSON Protobuf: `Content-Type: application/json`
+ - Supports gzip compression via `Content-Encoding: gzip` header
+
+ **Specification Compliance:**
+ - Conforms to [OTLP/HTTP Trace Export](https://opentelemetry.io/docs/specs/otlp/#otlphttp)
+ - Implements `ExportTraceServiceRequest` message format
+
+ **Documentation:**
+ - Integration guide: https://langfuse.com/integrations/native/opentelemetry
+ - Data model: https://langfuse.com/docs/observability/data-model
+
+ Parameters
+ ----------
+ resource_spans : typing.Sequence[OtelResourceSpan]
+ Array of resource spans containing trace data as defined in the OTLP specification
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ OtelTraceResponse
+
+ Examples
+ --------
+ import asyncio
+
+ from langfuse import (
+ OtelAttribute,
+ OtelAttributeValue,
+ OtelResource,
+ OtelResourceSpan,
+ OtelScope,
+ OtelScopeSpan,
+ OtelSpan,
+ )
+ from langfuse.client import AsyncFernLangfuse
+
+ client = AsyncFernLangfuse(
+ x_langfuse_sdk_name="YOUR_X_LANGFUSE_SDK_NAME",
+ x_langfuse_sdk_version="YOUR_X_LANGFUSE_SDK_VERSION",
+ x_langfuse_public_key="YOUR_X_LANGFUSE_PUBLIC_KEY",
+ username="YOUR_USERNAME",
+ password="YOUR_PASSWORD",
+ base_url="https://yourhost.com/path/to/api",
+ )
+
+
+ async def main() -> None:
+ await client.opentelemetry.export_traces(
+ resource_spans=[
+ OtelResourceSpan(
+ resource=OtelResource(
+ attributes=[
+ OtelAttribute(
+ key="service.name",
+ value=OtelAttributeValue(
+ string_value="my-service",
+ ),
+ ),
+ OtelAttribute(
+ key="service.version",
+ value=OtelAttributeValue(
+ string_value="1.0.0",
+ ),
+ ),
+ ],
+ ),
+ scope_spans=[
+ OtelScopeSpan(
+ scope=OtelScope(
+ name="langfuse-sdk",
+ version="2.60.3",
+ ),
+ spans=[
+ OtelSpan(
+ trace_id="0123456789abcdef0123456789abcdef",
+ span_id="0123456789abcdef",
+ name="my-operation",
+ kind=1,
+ start_time_unix_nano="1747872000000000000",
+ end_time_unix_nano="1747872001000000000",
+ attributes=[
+ OtelAttribute(
+ key="langfuse.observation.type",
+ value=OtelAttributeValue(
+ string_value="generation",
+ ),
+ )
+ ],
+ status={},
+ )
+ ],
+ )
+ ],
+ )
+ ],
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "api/public/otel/v1/traces",
+ method="POST",
+ json={"resourceSpans": resource_spans},
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return pydantic_v1.parse_obj_as(OtelTraceResponse, _response.json()) # type: ignore
+ if _response.status_code == 400:
+ raise Error(pydantic_v1.parse_obj_as(typing.Any, _response.json())) # type: ignore
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ if _response.status_code == 403:
+ raise AccessDeniedError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ if _response.status_code == 405:
+ raise MethodNotAllowedError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ if _response.status_code == 404:
+ raise NotFoundError(
+ pydantic_v1.parse_obj_as(typing.Any, _response.json())
+ ) # type: ignore
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, body=_response.text)
+ raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/langfuse/api/resources/opentelemetry/types/__init__.py b/langfuse/api/resources/opentelemetry/types/__init__.py
new file mode 100644
index 000000000..4ca603db6
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/__init__.py
@@ -0,0 +1,21 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from .otel_attribute import OtelAttribute
+from .otel_attribute_value import OtelAttributeValue
+from .otel_resource import OtelResource
+from .otel_resource_span import OtelResourceSpan
+from .otel_scope import OtelScope
+from .otel_scope_span import OtelScopeSpan
+from .otel_span import OtelSpan
+from .otel_trace_response import OtelTraceResponse
+
+__all__ = [
+ "OtelAttribute",
+ "OtelAttributeValue",
+ "OtelResource",
+ "OtelResourceSpan",
+ "OtelScope",
+ "OtelScopeSpan",
+ "OtelSpan",
+ "OtelTraceResponse",
+]
diff --git a/langfuse/api/resources/opentelemetry/types/otel_attribute.py b/langfuse/api/resources/opentelemetry/types/otel_attribute.py
new file mode 100644
index 000000000..91b9e2b70
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_attribute.py
@@ -0,0 +1,55 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .otel_attribute_value import OtelAttributeValue
+
+
+class OtelAttribute(pydantic_v1.BaseModel):
+ """
+ Key-value attribute pair for resources, scopes, or spans
+ """
+
+ key: typing.Optional[str] = pydantic_v1.Field(default=None)
+ """
+ Attribute key (e.g., "service.name", "langfuse.observation.type")
+ """
+
+ value: typing.Optional[OtelAttributeValue] = pydantic_v1.Field(default=None)
+ """
+ Attribute value
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_attribute_value.py b/langfuse/api/resources/opentelemetry/types/otel_attribute_value.py
new file mode 100644
index 000000000..51f026495
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_attribute_value.py
@@ -0,0 +1,72 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+
+
+class OtelAttributeValue(pydantic_v1.BaseModel):
+ """
+ Attribute value wrapper supporting different value types
+ """
+
+ string_value: typing.Optional[str] = pydantic_v1.Field(
+ alias="stringValue", default=None
+ )
+ """
+ String value
+ """
+
+ int_value: typing.Optional[int] = pydantic_v1.Field(alias="intValue", default=None)
+ """
+ Integer value
+ """
+
+ double_value: typing.Optional[float] = pydantic_v1.Field(
+ alias="doubleValue", default=None
+ )
+ """
+ Double value
+ """
+
+ bool_value: typing.Optional[bool] = pydantic_v1.Field(
+ alias="boolValue", default=None
+ )
+ """
+ Boolean value
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ allow_population_by_field_name = True
+ populate_by_name = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_resource.py b/langfuse/api/resources/opentelemetry/types/otel_resource.py
new file mode 100644
index 000000000..0d76d5a15
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_resource.py
@@ -0,0 +1,52 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .otel_attribute import OtelAttribute
+
+
+class OtelResource(pydantic_v1.BaseModel):
+ """
+ Resource attributes identifying the source of telemetry
+ """
+
+ attributes: typing.Optional[typing.List[OtelAttribute]] = pydantic_v1.Field(
+ default=None
+ )
+ """
+ Resource attributes like service.name, service.version, etc.
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_resource_span.py b/langfuse/api/resources/opentelemetry/types/otel_resource_span.py
new file mode 100644
index 000000000..e270ba7d8
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_resource_span.py
@@ -0,0 +1,60 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .otel_resource import OtelResource
+from .otel_scope_span import OtelScopeSpan
+
+
+class OtelResourceSpan(pydantic_v1.BaseModel):
+ """
+ Represents a collection of spans from a single resource as per OTLP specification
+ """
+
+ resource: typing.Optional[OtelResource] = pydantic_v1.Field(default=None)
+ """
+ Resource information
+ """
+
+ scope_spans: typing.Optional[typing.List[OtelScopeSpan]] = pydantic_v1.Field(
+ alias="scopeSpans", default=None
+ )
+ """
+ Array of scope spans
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ allow_population_by_field_name = True
+ populate_by_name = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_scope.py b/langfuse/api/resources/opentelemetry/types/otel_scope.py
new file mode 100644
index 000000000..71e9b75b8
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_scope.py
@@ -0,0 +1,62 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .otel_attribute import OtelAttribute
+
+
+class OtelScope(pydantic_v1.BaseModel):
+ """
+ Instrumentation scope information
+ """
+
+ name: typing.Optional[str] = pydantic_v1.Field(default=None)
+ """
+ Instrumentation scope name
+ """
+
+ version: typing.Optional[str] = pydantic_v1.Field(default=None)
+ """
+ Instrumentation scope version
+ """
+
+ attributes: typing.Optional[typing.List[OtelAttribute]] = pydantic_v1.Field(
+ default=None
+ )
+ """
+ Additional scope attributes
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_scope_span.py b/langfuse/api/resources/opentelemetry/types/otel_scope_span.py
new file mode 100644
index 000000000..854951a60
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_scope_span.py
@@ -0,0 +1,56 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .otel_scope import OtelScope
+from .otel_span import OtelSpan
+
+
+class OtelScopeSpan(pydantic_v1.BaseModel):
+ """
+ Collection of spans from a single instrumentation scope
+ """
+
+ scope: typing.Optional[OtelScope] = pydantic_v1.Field(default=None)
+ """
+ Instrumentation scope information
+ """
+
+ spans: typing.Optional[typing.List[OtelSpan]] = pydantic_v1.Field(default=None)
+ """
+ Array of spans
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_span.py b/langfuse/api/resources/opentelemetry/types/otel_span.py
new file mode 100644
index 000000000..08b7be7fb
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_span.py
@@ -0,0 +1,104 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .otel_attribute import OtelAttribute
+
+
+class OtelSpan(pydantic_v1.BaseModel):
+ """
+ Individual span representing a unit of work or operation
+ """
+
+ trace_id: typing.Optional[typing.Any] = pydantic_v1.Field(
+ alias="traceId", default=None
+ )
+ """
+ Trace ID (16 bytes, hex-encoded string in JSON or Buffer in binary)
+ """
+
+ span_id: typing.Optional[typing.Any] = pydantic_v1.Field(
+ alias="spanId", default=None
+ )
+ """
+ Span ID (8 bytes, hex-encoded string in JSON or Buffer in binary)
+ """
+
+ parent_span_id: typing.Optional[typing.Any] = pydantic_v1.Field(
+ alias="parentSpanId", default=None
+ )
+ """
+ Parent span ID if this is a child span
+ """
+
+ name: typing.Optional[str] = pydantic_v1.Field(default=None)
+ """
+ Span name describing the operation
+ """
+
+ kind: typing.Optional[int] = pydantic_v1.Field(default=None)
+ """
+ Span kind (1=INTERNAL, 2=SERVER, 3=CLIENT, 4=PRODUCER, 5=CONSUMER)
+ """
+
+ start_time_unix_nano: typing.Optional[typing.Any] = pydantic_v1.Field(
+ alias="startTimeUnixNano", default=None
+ )
+ """
+ Start time in nanoseconds since Unix epoch
+ """
+
+ end_time_unix_nano: typing.Optional[typing.Any] = pydantic_v1.Field(
+ alias="endTimeUnixNano", default=None
+ )
+ """
+ End time in nanoseconds since Unix epoch
+ """
+
+ attributes: typing.Optional[typing.List[OtelAttribute]] = pydantic_v1.Field(
+ default=None
+ )
+ """
+ Span attributes including Langfuse-specific attributes (langfuse.observation.*)
+ """
+
+ status: typing.Optional[typing.Any] = pydantic_v1.Field(default=None)
+ """
+ Span status object
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ allow_population_by_field_name = True
+ populate_by_name = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/opentelemetry/types/otel_trace_response.py b/langfuse/api/resources/opentelemetry/types/otel_trace_response.py
new file mode 100644
index 000000000..ef9897f06
--- /dev/null
+++ b/langfuse/api/resources/opentelemetry/types/otel_trace_response.py
@@ -0,0 +1,44 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+from ....core.datetime_utils import serialize_datetime
+from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+
+
+class OtelTraceResponse(pydantic_v1.BaseModel):
+ """
+ Response from trace export request. Empty object indicates success.
+ """
+
+ def json(self, **kwargs: typing.Any) -> str:
+ kwargs_with_defaults: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ return super().json(**kwargs_with_defaults)
+
+ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
+ kwargs_with_defaults_exclude_unset: typing.Any = {
+ "by_alias": True,
+ "exclude_unset": True,
+ **kwargs,
+ }
+ kwargs_with_defaults_exclude_none: typing.Any = {
+ "by_alias": True,
+ "exclude_none": True,
+ **kwargs,
+ }
+
+ return deep_union_pydantic_dicts(
+ super().dict(**kwargs_with_defaults_exclude_unset),
+ super().dict(**kwargs_with_defaults_exclude_none),
+ )
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic_v1.Extra.allow
+ json_encoders = {dt.datetime: serialize_datetime}
diff --git a/langfuse/api/resources/prompts/__init__.py b/langfuse/api/resources/prompts/__init__.py
index 77c27486d..ea2f2f56a 100644
--- a/langfuse/api/resources/prompts/__init__.py
+++ b/langfuse/api/resources/prompts/__init__.py
@@ -16,6 +16,7 @@
Prompt,
PromptMeta,
PromptMetaListResponse,
+ PromptType,
Prompt_Chat,
Prompt_Text,
TextPrompt,
@@ -37,6 +38,7 @@
"Prompt",
"PromptMeta",
"PromptMetaListResponse",
+ "PromptType",
"Prompt_Chat",
"Prompt_Text",
"TextPrompt",
diff --git a/langfuse/api/resources/prompts/types/__init__.py b/langfuse/api/resources/prompts/types/__init__.py
index 3067f9f04..6678ec262 100644
--- a/langfuse/api/resources/prompts/types/__init__.py
+++ b/langfuse/api/resources/prompts/types/__init__.py
@@ -19,6 +19,7 @@
from .prompt import Prompt, Prompt_Chat, Prompt_Text
from .prompt_meta import PromptMeta
from .prompt_meta_list_response import PromptMetaListResponse
+from .prompt_type import PromptType
from .text_prompt import TextPrompt
__all__ = [
@@ -37,6 +38,7 @@
"Prompt",
"PromptMeta",
"PromptMetaListResponse",
+ "PromptType",
"Prompt_Chat",
"Prompt_Text",
"TextPrompt",
diff --git a/langfuse/api/resources/prompts/types/prompt_meta.py b/langfuse/api/resources/prompts/types/prompt_meta.py
index bbb028fb2..35f8a06cf 100644
--- a/langfuse/api/resources/prompts/types/prompt_meta.py
+++ b/langfuse/api/resources/prompts/types/prompt_meta.py
@@ -5,10 +5,16 @@
from ....core.datetime_utils import serialize_datetime
from ....core.pydantic_utilities import deep_union_pydantic_dicts, pydantic_v1
+from .prompt_type import PromptType
class PromptMeta(pydantic_v1.BaseModel):
name: str
+ type: PromptType = pydantic_v1.Field()
+ """
+ Indicates whether the prompt is a text or chat prompt.
+ """
+
versions: typing.List[int]
labels: typing.List[str]
tags: typing.List[str]
diff --git a/langfuse/api/resources/prompts/types/prompt_type.py b/langfuse/api/resources/prompts/types/prompt_type.py
new file mode 100644
index 000000000..958d544a6
--- /dev/null
+++ b/langfuse/api/resources/prompts/types/prompt_type.py
@@ -0,0 +1,19 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import enum
+import typing
+
+T_Result = typing.TypeVar("T_Result")
+
+
+class PromptType(str, enum.Enum):
+ CHAT = "chat"
+ TEXT = "text"
+
+ def visit(
+ self, chat: typing.Callable[[], T_Result], text: typing.Callable[[], T_Result]
+ ) -> T_Result:
+ if self is PromptType.CHAT:
+ return chat()
+ if self is PromptType.TEXT:
+ return text()