traceAI-semantic-kernel
Future AGI tracing for Semantic Kernel for Python, built on Semantic Kernel's own OpenTelemetry diagnostics.
Experimental upstream diagnostics. Python only. This is not the Java package (
java/traceai-java-semantic-kernel), not .NET Semantic Kernel, and not Microsoft Agent Framework (usetraceAI-agent-frameworkfor that). Semantic Kernel marks its GenAI diagnostics@experimental, so the span names and keys below can change in a future Semantic Kernel release.
Connector support
Use this adapter with Semantic Kernel's OpenAIChatCompletion or Azure OpenAI's AzureChatCompletion. Both use Semantic Kernel's shared model diagnostics, including streaming. Agent and tool spans come from Semantic Kernel's native diagnostics; this package maps them rather than adding a second tracing layer.
Azure AI Inference is not supported by this adapter.
AzureAIInferenceChatCompletionis a different connector fromAzureChatCompletion. Its model calls use Azure SDK tracing and create fresh diagnostics settings per call.instrument()does not enable those settings, route the Azure SDK's tracer, or apply this adapter's content and privacy controls to Azure SDK spans. Do not turn on theSEMANTICKERNEL_EXPERIMENTAL_GENAI_*flags as a workaround: Azure SDK content recording can remain enabled even withsensitive=FalseorFI_HIDE_INPUTS/FI_HIDE_OUTPUTS. If your deployment is Azure OpenAI, useAzureChatCompletion; that is not a replacement for an Azure AI Inference endpoint.
Other connectors are not a blanket support promise: this adapter only configures Semantic Kernel's shared diagnostics and processes spans whose instrumentation scope is semantic_kernel or semantic_kernel.*. It does not configure separate provider SDKs or add missing model or retrieval spans.
What it does
SemanticKernelInstrumentor().instrument():
- Turns on Semantic Kernel's shared GenAI diagnostics in process. You do not export
SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS. The shared diagnostics modules build theirModelDiagnosticSettingsobjects when imported, so setting the environment variable afterwards does not update those instances;instrument()sets their fields instead. Calling it before or after you build the kernel both work. This does not enable the separate Azure AI Inference path described above. - Points Semantic Kernel's module-level tracers at the tracer provider you pass. Semantic Kernel creates them from the global provider, and
fi_instrumentation.register()does not set the global provider by default. - Installs a mapping-only span processor ahead of the exporter: span kind, provider alias, total tokens, session, content default.
It does not wrap Kernel.invoke, KernelFunction.invoke or any connector method, opens no spans of its own, and does not depend on wrapt. Semantic Kernel creates every span you see.
Install
pip install traceAI-semantic-kernel
semantic-kernel (MIT) is a dependency floor only (>=1.38.0,<2); it is not vendored.
Use
export FI_API_KEY="YOUR_API_KEY"
export FI_SECRET_KEY="YOUR_SECRET_KEY"
from fi_instrumentation import register, using_session
from fi_instrumentation.fi_types import ProjectType
from traceai_semantic_kernel import SemanticKernelInstrumentor
trace_provider = register(project_type=ProjectType.OBSERVE, project_name="my-sk-app")
# Enables native diagnostics in process. Does not wrap Kernel.invoke.
SemanticKernelInstrumentor().instrument(tracer_provider=trace_provider, sensitive=False)
# ... build your Kernel / ChatCompletionAgent as usual ...
with using_session("conversation-123"): # Semantic Kernel emits no thread id; set the session yourself
response = await agent.get_response("What is the weather in Paris?")
trace_provider.force_flush() # short scripts: the batch exporter sends in the background
instrument() is process-wide and idempotent: calling it twice, or on two instances, installs one processor. uninstrument() restores Semantic Kernel's switches and tracers and removes the processor. If you also put a SemanticKernelSpanProcessor on the provider yourself, instrument() does not take it over: it adds its own (with a warning), and uninstrument() removes and shuts down only that one. Use one or the other.
A runnable example with a mocked model (no model key) is in examples/basic_agent.py.
Ordering and other instrumentors
- Call
instrument()after anyadd_span_processor()of your own on the providerregister()returned.fi_instrumentation'sTracerProvider.add_span_processortreats the processor chainregister()set up as a replaceable default: its first call shuts down and empties the whole chain before adding yours (fi_instrumentation/otel.py,TracerProvider.add_span_processor; existingfi_instrumentationbehaviour). That also removes this package's processor, whileinstrument()still reports instrumented and Semantic Kernel keeps emitting, so spans export without span kinds, session copy orTraceConfighiding. If you must add a processor later, calluninstrument()and theninstrument()again (covered bytest_later_add_span_processor_drops_ours_until_reinstrumented). - Do not also enable a client-level instrumentor for the same model calls (
traceAI-openai,traceAI-anthropic,traceAI-litellm, ...). Semantic Kernel already putsgen_ai.usage.input_tokens/gen_ai.usage.output_tokenson itschatspan, and this package keeps them there. A client instrumentor adds a secondLLMspan for the same request with the same tokens, and the processor only touches Semantic Kernel spans, so Observe's trace and session token sums count every model call twice. Use one or the other: this package for the Semantic Kernel tree, or the client instrumentor alone.
Sensitive content
These controls apply only to Semantic Kernel-scoped spans. They do not filter spans or logs emitted independently by Azure SDKs or other instrumentors.
Warning.
sensitive=Trueturns on Semantic Kernel's sensitive diagnostics. Semantic Kernel then puts agent input and output messages, tool-call arguments and tool results on spans, this package adds model-call prompts and completions to thechatspans, and all of it is copied toinput.value/output.value. Leavesensitive=False(the default) unless you want that text stored in Future AGI.
- With
sensitive=False,instrument()forces Semantic Kernel's sensitive switch off even if your environment or.envturned it on (a warning is logged), and the processor removesgen_ai.input.messages,gen_ai.output.messages,gen_ai.tool.call.arguments,gen_ai.tool.call.result,input.valueandoutput.valuefrom Semantic Kernel spans. - With
sensitive=True,TraceConfigand its environment variables still apply.instrument(config=TraceConfig(hide_inputs=True))orFI_HIDE_INPUTS=truedrops tool arguments, agent and model-call input messages,input.valueandinput.mime_type;hide_outputs/FI_HIDE_OUTPUTS=truedrops tool results, agent and model-call output messages,output.valueandoutput.mime_type. The keys are removed, not replaced with__REDACTED__. Withoutconfig, aTraceConfig()is built from the environment wheninstrument()runs. OtherTraceConfigfields (hide_input_messages,hide_output_messages,hide_input_text,hide_output_text, image and embedding limits,pii_redaction,hide_llm_invocation_parameters) are not applied by this package. Aconfigthat is not aTraceConfigraisesTypeError. - Model-call (
chat) messages: Semantic Kernel writes them only to Pythonlogging(model_diagnostics/decorators.py_set_completion_input/_set_completion_response), not to the span. Withsensitive=True,instrument()puts a proxy in front of that module'sloggerthat also appends each message to the currentchatspan asgen_ai.input.messages/gen_ai.output.messages(JSON lists of Semantic Kernel's message dicts), anduninstrument()puts the original back. The proxy passes every call on to the real logger unchanged, so the records still reach whatever handlers your Python logging has at INFO. Withsensitive=Falseno proxy is installed. - Errors: Semantic Kernel records the exception on the span (type, message and a stack trace with local file paths). The processor always removes
exception.stacktrace. Withsensitive=Falseit also removesexception.messageand cuts the ERROR status description down to the exception type (RuntimeError), because messages often echo tool arguments or model output.exception.type,error.typeand the ERROR status stay. Withsensitive=Truethe message is kept.
Spans and attributes
Spans Semantic Kernel 1.44.1 emits once diagnostics are on, and what the processor adds:
| Span name | Source (installed semantic_kernel/) |
Kind set (fi.span.kind and gen_ai.span.kind) |
|---|---|---|
chat <model> / text_completions <model> |
utils/telemetry/model_diagnostics/decorators.py 37-38, 322-364 |
LLM |
invoke_agent <agent name> |
utils/telemetry/agent_diagnostics/decorators.py 35, 174-205 |
AGENT |
execute_tool <plugin>-<function> the model asked for: it carries gen_ai.tool.call.id (kernel.py 468-471) or runs as a direct child of AutoFunctionInvocationLoop (connectors that send no tool call id, such as Ollama) |
functions/kernel_function.py 264, model_diagnostics/function_tracer.py 54-65 |
TOOL |
execute_tool <plugin>-<function> with neither (you invoked the function, e.g. kernel.invoke / kernel.invoke_prompt, or a function your tool calls) |
same | CHAIN |
AutoFunctionInvocationLoop |
connectors/ai/chat_completion_client_base.py 137, 256, 410-424 |
CHAIN |
Typical tree for an agent that calls one tool:
invoke_agent Assistant AGENT
└─ AutoFunctionInvocationLoop CHAIN
├─ chat gpt-4o-mini LLM (finish_reason tool_calls)
├─ execute_tool Weather-get_weather TOOL
└─ chat gpt-4o-mini LLM (finish_reason stop)
| Future AGI field | Key | Where it comes from |
|---|---|---|
| Span kind | fi.span.kind, gen_ai.span.kind |
Set by the processor (table above). fi-collector reads fi.span.kind first. |
| Model | gen_ai.request.model |
Semantic Kernel, passed through. No gen_ai.response.model upstream. |
| Provider | gen_ai.provider.name |
Copied from Semantic Kernel's gen_ai.system when absent. gen_ai.system is kept. |
| Input / output tokens | gen_ai.usage.input_tokens, gen_ai.usage.output_tokens |
Semantic Kernel, on chat spans only (decorators.py 421-427). Streaming included (the OpenAI connector requests include_usage). |
| Total tokens | gen_ai.usage.total_tokens |
Derived on LLM spans when both parts exist. |
| Token/cost on other spans | semantic_kernel.usage.* |
Any promoted token/cost key on a non-LLM Semantic Kernel span is moved here so Observe's trace-wide sums count each Semantic Kernel model call once. Semantic Kernel 1.44.1 puts none there; this is a guard. It does not cover spans from a client-level instrumentor (see "Ordering and other instrumentors"). |
| Cost | none | Not emitted. Not invented. |
| Session | session.id |
From gen_ai.conversation.id when present (Semantic Kernel 1.44.1 emits none), or from using_session / using_attributes, which the processor copies onto Semantic Kernel spans at start. |
| User | user.id |
Only from using_attributes(user_id=...). |
| Tool | gen_ai.tool.name, gen_ai.tool.call.id, gen_ai.tool.description |
Semantic Kernel, passed through. |
| Tool arguments / result | gen_ai.tool.call.arguments, gen_ai.tool.call.result → input.value, output.value |
sensitive=True only (kernel_function.py 268-269, 283-288). |
| Agent | gen_ai.agent.id, gen_ai.agent.name, gen_ai.agent.description, gen_ai.tool.definitions |
Semantic Kernel, passed through. |
| Agent messages | gen_ai.input.messages, gen_ai.output.messages → input.value, output.value |
sensitive=True only (agent_diagnostics/decorators.py 208-227). Input is captured only when the messages are passed positionally (decorators.py 75). |
| Model-call messages | gen_ai.input.messages, gen_ai.output.messages → input.value, output.value on chat / text_completions spans |
sensitive=True only. Recorded from Semantic Kernel's model-diagnostics log records (see "Sensitive content"); streaming included. A single completion is put on output.value as its message object (not a one-item list), which Observe's chat view shows as the assistant reply. |
| Errors | error.type, span status |
Semantic Kernel sets ERROR status on model, agent and tool failures. The processor sets ERROR only if error.type is present and the status is unset; it never clears a status. |
| Other | server.address, gen_ai.response.id, gen_ai.response.finish_reason (singular), gen_ai.request.* sampling keys, sk.available_functions |
Semantic Kernel, passed through. |
Not available: retrieval spans (memory/vector connectors were not inspected), cache and reasoning token counts, cost, a thread or conversation id from Semantic Kernel itself.
Failure behavior
- Collector down or slow: the OTLP exporter logs and drops; your kernel call returns normally (covered by
test_collector_down_never_breaks_the_kernel). - The processor swallows its own exceptions and never raises into the OpenTelemetry SDK.
instrument()does not raise into your startup when a Semantic Kernel module it expects cannot be imported (the diagnostics are experimental upstream and may move in a later release). It logs a WARNING naming the module, skips it, and instruments the rest. A provider that is not an OpenTelemetry SDKTracerProvider(for example the globalProxyTracerProviderbefore any provider is set) gets a WARNING and nothing is changed.uninstrument()is safe in both cases.- A full batch queue (default 2048) drops spans inside OpenTelemetry; the agent does not see it.
- If a stream is abandoned mid-way, Semantic Kernel owns the span end; this package does not open a second span to close it.
Compatibility
Requires Python 3.10–3.13 and semantic-kernel>=1.38.0,<2. Earlier Semantic Kernel releases use different diagnostic operation names and agent attributes. The diagnostics are experimental upstream; review this adapter's compatibility before upgrading Semantic Kernel.
If you install with uv, use uv pip install --prerelease=allow traceAI-semantic-kernel: Semantic Kernel requires the pre-release azure-ai-agents dependency.
Metadata
Release files for traceAI-semantic-kernel 0.1.1
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 |
|---|---|---|---|---|
| traceai_semantic_kernel-0.1.1.tar.gz | 21.9 kB | Without provenance | Details for traceai_semantic_kernel-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| traceai_semantic_kernel-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for traceai_semantic_kernel-0.1.1-py3-none-any.whl |
Total release size: 42.0 kB
Release files / traceai_semantic_kernel-0.1.1.tar.gz
| Download URL | traceai_semantic_kernel-0.1.1.tar.gz |
|---|---|
| Size | 21.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
28eecd767aa7d4ba5649b98d251cd164ce0fd89cb2bd66c2986b0303834b4219
|
|
BLAKE2b-256 checksum How to use checksums |
1283226957989b0bfa9570ca666ce54fda1bfcf48f41b42c64cb94dce700772f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / traceai_semantic_kernel-0.1.1-py3-none-any.whl
| Download URL | traceai_semantic_kernel-0.1.1-py3-none-any.whl |
|---|---|
| Size | 20.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
117467f53e6c719656a924aef90cea0861a7b585b91d962e6266662ae2f33bab
|
|
BLAKE2b-256 checksum How to use checksums |
3dbca7072c60445632b96020582c0c7cd233681007920cd720c6391d866131f2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for traceAI-semantic-kernel 0.1.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.