deepeval.integrations
Contributor reference for the framework integrations. Each integration plugs deepeval's tracing / evaluation into a third-party framework using one of four mechanisms.
Note:
deepeval.openai,deepeval.anthropic, anddeepeval.openai_agentslive at the top level of thedeepevalpackage, not under this folder. They're listed here so the matrix is complete.
Integration matrix
Capability columns:
- Bare — calling the framework directly without an enclosing
@observe/with trace(...)produces a trace in Confident AI. Each integration auto-creates a trace on first activity (callback fire, OTel root span, internal@observewrap on the native client, etc.). @observe/with trace(...)— when wrapped, the integration's spans flow into deepeval's native trace context:update_current_trace(...)/update_current_span(...)work anywhere in the call stack, single REST POST per trace, no UUID-reconciliation needed.evals_iterator— works insidedataset.evals_iterator(...), both end-to-end (metrics=[...]on the iterator) and component-level (@observe(metrics=[...])on a span). For OTel-mode integrations,ContextAwareSpanProcessorflips to REST routing automatically whentrace_manager.is_evaluatingis True so spans flow throughtrace_managerinstead of OTLP.deepeval test run— works under the pytest tracing-eval entry point (@assert_test,@generate_trace_json,@assert_trace_json).
| Integration | Mode | Entry point | Bare | @observe / with trace() |
evals_iterator |
deepeval test run |
Source |
|---|---|---|---|---|---|---|---|
| OpenAI | Native client wrapper | from deepeval.openai import OpenAI |
Yes | Yes | Yes | Yes | deepeval/openai/ |
| Anthropic | Native client wrapper | from deepeval.anthropic import Anthropic |
Yes | Yes | Yes | Yes | deepeval/anthropic/ |
| LangChain | Callback handler | CallbackHandler() |
Yes | Yes | Yes | Yes | deepeval/integrations/langchain/ |
| LangGraph | Callback handler (LangChain's) | CallbackHandler() |
Yes | Yes | Yes | Yes | deepeval/integrations/langchain/ |
| LlamaIndex | Event handler | instrument_llama_index() |
Yes | Yes | Yes | Yes | deepeval/integrations/llama_index/ |
| CrewAI | Event listener + wrapper classes | instrument_crewai() |
Yes | Yes | Yes | Yes | deepeval/integrations/crewai/ |
| OpenAI Agents | Trace processor + agent wrapper | add_trace_processor(DeepEvalTracingProcessor()) |
Yes | Yes | Yes | Yes | deepeval/openai_agents/ |
| AgentCore | OpenTelemetry | instrument_agentcore() |
Yes | Yes | Yes | Yes | deepeval/integrations/agentcore/ |
| Strands | OpenTelemetry | instrument_strands() |
Yes | Yes | Yes | Yes | deepeval/integrations/strands/ |
| Google ADK | OpenTelemetry (via OpenInference) | instrument_google_adk() |
Yes | Yes | Yes | Yes | deepeval/integrations/google_adk/ |
| Pydantic AI | OpenTelemetry | DeepEvalInstrumentationSettings(...) |
Yes | Yes | Yes | Yes | deepeval/integrations/pydantic_ai/ |
Every cell is Yes because of the recent OTel POC migrations: native-client / callback-handler / event-listener / trace-processor integrations were already feature-complete via direct
trace_manageraccess, and the four OTel-mode integrations (Pydantic AI, AgentCore, Google ADK, Strands) now follow the same SpanInterceptor +ContextAwareSpanProcessorpattern1 so their spans behave identically across all four surfaces. New integrations should target the same parity.
Mode reference
- Native client wrapper — drop-in replacement for the vendor SDK's client class (e.g.
deepeval.openai.OpenAIinstead ofopenai.OpenAI). Spans are built directly viatrace_manager. Lowest friction, but only covers calls that go through that client. - Callback handler / event listener — registers with the framework's own callback or event API (LangChain
BaseCallbackHandler, LlamaIndexBaseEventHandler, CrewAIBaseEventListener, etc.). Spans are built directly viatrace_manager. Covers all calls the framework dispatches through that surface — no need to swap clients. - Trace processor — for frameworks that already have their own tracing pipeline (OpenAI Agents SDK), we plug into it as a processor and translate events into deepeval spans.
- OpenTelemetry — registers an OTel
SpanProcessoragainst the globalTracerProvider. The framework (or a community-maintained instrumentor likeopeninference-instrumentation-google-adk) emits OTel spans; deepeval translates them into Confident span attributes and ships them via OTLP.
Transport reference
- REST —
trace_managerposts the full trace toapi.confident-ai.com/v1/tracesonce per trace. - OTLP —
BatchSpanProcessorflushes OTel spans tootel.confident-ai.com/v1/traceson a timer / queue threshold.
OpenInference (generic OTel backend for community instrumentors)
deepeval/integrations/openinference/ is the SpanInterceptor + processor wiring shared by Google ADK and any other community-maintained OpenInference instrumentor. It sets up the TracerProvider, registers OpenInferenceSpanInterceptor (translates OpenInference semantic-convention attributes — openinference.span.kind, llm.input_messages.{idx}, llm.output_messages.{idx}, tool.name, llm.token_count.* — into confident.span.*), and routes spans through ContextAwareSpanProcessor (REST or OTLP).
It is exposed at the top level as deepeval.instrument(...) so users can pair it with any OpenInference instrumentor directly:
import deepeval
from openinference.instrumentation.google_adk import GoogleADKInstrumentor
deepeval.instrument(name="my-app", environment="development")
GoogleADKInstrumentor().instrument()
instrument_google_adk(...) is just a convenience wrapper that calls GoogleADKInstrumentor().instrument() then deepeval.instrument(...) for you.
AgentCore, Strands, and Pydantic AI do NOT delegate here — they have their own SpanInterceptors (AgentCoreSpanInterceptor, StrandsSpanInterceptor, PydanticAISpanInterceptor). AgentCore and Strands both read OTel GenAI semconv (gen_ai.*) attributes — Strands emits these natively, and AgentCore picks them up from the Strands runtime AWS Bedrock typically runs under, plus Traceloop / AWS Bedrock fallbacks; Pydantic AI uses its own logfire-shaped attrs. All four interceptors share the same processor wiring and the same ContextAwareSpanProcessor for routing.
Mixing OTel-mode with @observe
When an OTel-mode integration runs inside an active @observe / with trace(...) context, the OTel span interceptor synchronizes the trace UUID (current_trace_context.uuid = OTel trace_id) so both transports land on the same trace server-side.
For all OTel-mode integrations above, ContextAwareSpanProcessor automatically routes the OTel spans through ConfidentSpanExporter (REST) when a deepeval trace context is active or an evaluation is running — so a mixed trace produces a single REST POST and update_current_trace(...) / update_current_span(...) from anywhere in the call stack land on the right span. Pydantic AI is the reference implementation; AgentCore, Strands, and Google ADK (the latter via the shared openinference/ backend) follow the same pattern.
-
Each OTel-mode
SpanInterceptorreads trace-level metadata fromcurrent_trace_contextper span (instead of baking it atinstrument_*()time) and pushes aBaseSpanplaceholder ontocurrent_span_contextfor each OTel span's lifetime soupdate_current_span(...)from anywhere lands inconfident.span.*attributes aton_end. TheContextAwareSpanProcessor(deepeval/tracing/otel/context_aware_processor.py) routes spans to REST when a deepeval trace context is active or an evaluation is running, OTLP otherwise. ↩︎