Semantic Kernel (Python)
Microsoft Semantic Kernel for Python emits native
OpenTelemetry spans, metrics, and logs to the global OpenTelemetry providers. Because
logfire.configure() sets those global providers, SK’s telemetry flows to Logfire
automatically once you enable SK’s experimental GenAI diagnostics with an environment variable.
pip install logfire semantic-kernel
Set the diagnostics flag in your terminal before starting the script. The SENSITIVE variant records prompts
and completions; use SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS=true instead for metadata only.
export SEMANTICKERNEL_EXPERIMENTAL_GENAI_ENABLE_OTEL_DIAGNOSTICS_SENSITIVE=true
Then call logfire.configure() before creating the agent:
import asyncio
from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.functions import kernel_function
import logfire
# Sets the global OTel tracer + meter provider exporting to Logfire.
logfire.configure(service_name='semantic-kernel-agent')
class WeatherPlugin:
@kernel_function(description='Get the weather for a city')
def get_weather(self, city: str) -> str:
return f'The weather in {city} is sunny, 21C.'
async def main() -> None:
agent = ChatCompletionAgent(
service=OpenAIChatCompletion(ai_model_id='gpt-4o-mini'), # uses OPENAI_API_KEY
name='weather_agent',
instructions='Use the weather plugin before answering.',
function_choice_behavior=FunctionChoiceBehavior.Required(),
plugins=[WeatherPlugin()],
)
response = await agent.get_response(messages="What's the weather in Paris?")
print(response.message.content)
if __name__ == '__main__':
asyncio.run(main())
You’ll see an invoke_agent span in Live and Agents, with child chat.completions and function-invocation
spans. With the SENSITIVE flag enabled, the conversation is also available in the agent-run detail. Semantic
Kernel runs also appear in the specialized Agents view; the
support matrix shows which columns each view populates.
Keep your prompts in Prompt Management and fetch them at runtime:
pip install 'logfire[variables]'
import asyncio
from pydantic import BaseModel
from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.functions import kernel_function
import logfire
logfire.configure()
class WeatherPlugin:
@kernel_function(description='Get the weather for a city')
def get_weather(self, city: str) -> str:
return f'The weather in {city} is sunny, 21C.'
class WeatherInputs(BaseModel):
city: str
prompt_var = logfire.template_var(
name='prompt__weather_instructions',
type=str,
default='Use the weather plugin to answer questions about {{city}}.',
inputs_type=WeatherInputs,
)
with prompt_var.get(WeatherInputs(city='Paris'), label='production') as resolved:
prompt = resolved.value
async def main():
agent = ChatCompletionAgent(
service=OpenAIChatCompletion(ai_model_id='gpt-4o-mini'),
name='weather_agent',
instructions=prompt,
function_choice_behavior=FunctionChoiceBehavior.Required(),
plugins=[WeatherPlugin()],
)
response = await agent.get_response(messages="What's the weather in Paris?")
print(response.message.content)
if __name__ == '__main__':
asyncio.run(main())
See Use Prompts in Your Application for the full workflow.