Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dotnet/src/Agents/AzureAI/AzureAIAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync
new AzureAIAgentInvokeOptions() { AdditionalInstructions = mergedAdditionalInstructions } :
new AzureAIAgentInvokeOptions(options) { AdditionalInstructions = mergedAdditionalInstructions };

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, messages);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, kernel, messages);
List<ChatMessageContent>? chatMessageContents = activity is not null ? [] : null;

await foreach (var result in InternalInvokeAsync().ConfigureAwait(false))
Expand Down Expand Up @@ -264,7 +264,7 @@ public async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> In
new AzureAIAgentInvokeOptions() { AdditionalInstructions = mergedAdditionalInstructions } :
new AzureAIAgentInvokeOptions(options) { AdditionalInstructions = mergedAdditionalInstructions };

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, messages);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, kernel, messages);
List<StreamingChatMessageContent>? streamedContents = activity is not null ? [] : null;

// Invoke the Agent with the thread that we already added our message to, and with
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/AzureAI/AzureAIChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ protected override async Task ReceiveAsync(IEnumerable<ChatMessageContent> histo
CancellationToken cancellationToken)
{
return ActivityExtensions.RunWithActivityAsync(
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, []),
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, agent.Kernel, []),
() => AgentThreadActions.InvokeAsync(agent, client, threadId, invocationOptions: null, this.Logger, agent.Kernel, agent.Arguments, cancellationToken),
cancellationToken);
}
Expand All @@ -54,7 +54,7 @@ protected override async Task ReceiveAsync(IEnumerable<ChatMessageContent> histo
protected override IAsyncEnumerable<StreamingChatMessageContent> InvokeStreamingAsync(AzureAIAgent agent, IList<ChatMessageContent> messages, CancellationToken cancellationToken = default)
{
return ActivityExtensions.RunWithActivityAsync(
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, messages),
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, agent.Kernel, messages),
() => AgentThreadActions.InvokeStreamingAsync(agent, client, threadId, messages, invocationOptions: null, this.Logger, agent.Kernel, agent.Arguments, cancellationToken),
cancellationToken);
}
Expand Down
8 changes: 4 additions & 4 deletions dotnet/src/Agents/Bedrock/BedrockAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public override async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> In
};
});

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, messages);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, this.Kernel, messages);

// Invoke the agent
var invokeResults = this.InvokeInternalAsync(invokeAgentRequest, options?.KernelArguments, cancellationToken);
Expand Down Expand Up @@ -211,7 +211,7 @@ public async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync
invokeAgentRequest.SessionId = bedrockThread.Id;
invokeAgentRequest = this.ConfigureAgentRequest(options, () => invokeAgentRequest);

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, []);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, this.Kernel, []);
List<ChatMessageContent>? chatMessageContents = activity is not null ? [] : null;

// Invoke the agent
Expand Down Expand Up @@ -297,7 +297,7 @@ public override async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageCon
};
});

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, []);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, this.Kernel, []);
List<StreamingChatMessageContent>? streamedContents = activity is not null ? [] : null;

// Invoke the agent
Expand Down Expand Up @@ -365,7 +365,7 @@ public async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> In
invokeAgentRequest.SessionId = bedrockThread.Id;
invokeAgentRequest = this.ConfigureAgentRequest(options, () => invokeAgentRequest);

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, []);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, this.Kernel, []);
List<StreamingChatMessageContent>? streamedContents = activity is not null ? [] : null;

var invokeResults = this.InvokeStreamingInternalAsync(invokeAgentRequest, bedrockThread, options?.KernelArguments, cancellationToken);
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/Core/ChatCompletionAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ private async IAsyncEnumerable<ChatMessageContent> InternalInvokeAsync(

this.Logger.LogAgentChatServiceInvokingAgent(nameof(InvokeAsync), this.Id, agentName, serviceType);

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, agentName, this.Description, chat);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, agentName, this.Description, kernel, chat);

IReadOnlyList<ChatMessageContent> messages =
await chatCompletionService.GetChatMessageContentsAsync(
Expand Down Expand Up @@ -402,7 +402,7 @@ private async IAsyncEnumerable<StreamingChatMessageContent> InternalInvokeStream

this.Logger.LogAgentChatServiceInvokingAgent(nameof(InvokeAsync), this.Id, agentName, serviceType);

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, agentName, this.Description, chat);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, agentName, this.Description, kernel, chat);

IAsyncEnumerable<StreamingChatMessageContent> messages =
chatCompletionService.GetStreamingChatMessageContentsAsync(
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/OpenAI/OpenAIAssistantAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public async IAsyncEnumerable<AgentResponseItem<ChatMessageContent>> InvokeAsync
kernel.Plugins.AddFromAIContext(providersContext, "Tools");
#pragma warning restore SKEXP0110, SKEXP0130 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, messages);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, kernel, messages);
List<ChatMessageContent>? chatMessageContents = activity is not null ? [] : null;

// Notify the thread of new messages and return them to the caller.
Expand Down Expand Up @@ -267,7 +267,7 @@ public async IAsyncEnumerable<AgentResponseItem<StreamingChatMessageContent>> In
});

#pragma warning disable SKEXP0001 // ModelDiagnostics is marked experimental.
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, messages);
using var activity = ModelDiagnostics.StartAgentInvocationActivity(this.Id, this.GetDisplayName(), this.Description, kernel, messages);
List<StreamingChatMessageContent>? streamedContents = activity is not null ? [] : null;

ChatHistory newMessagesReceiver = [];
Expand Down
4 changes: 2 additions & 2 deletions dotnet/src/Agents/OpenAI/OpenAIAssistantChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected override async Task ReceiveAsync(IEnumerable<ChatMessageContent> histo
CancellationToken cancellationToken)
{
return ActivityExtensions.RunWithActivityAsync(
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, []),
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, agent.Kernel, []),
() => AssistantThreadActions.InvokeAsync(agent, this._client, this._threadId, invocationOptions: null, providersAdditionalInstructions: null, this.Logger, agent.Kernel, agent.Arguments, cancellationToken),
cancellationToken);
}
Expand All @@ -59,7 +59,7 @@ protected override async Task ReceiveAsync(IEnumerable<ChatMessageContent> histo
protected override IAsyncEnumerable<StreamingChatMessageContent> InvokeStreamingAsync(OpenAIAssistantAgent agent, IList<ChatMessageContent> messages, CancellationToken cancellationToken = default)
{
return ActivityExtensions.RunWithActivityAsync(
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, messages),
() => ModelDiagnostics.StartAgentInvocationActivity(agent.Id, agent.GetDisplayName(), agent.Description, agent.Kernel, messages),
() => AssistantThreadActions.InvokeStreamingAsync(agent, this._client, this._threadId, messages, invocationOptions: null, providersAdditionalInstructions: null, this.Logger, agent.Kernel, agent.Arguments, cancellationToken),
cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ internal static class ModelDiagnostics
string agentId,
string agentName,
string? agentDescription,
Kernel? kernel,
ICollection<ChatMessageContent> messages)
{
if (!IsModelDiagnosticsEnabled())
Expand All @@ -169,6 +170,12 @@ internal static class ModelDiagnostics
activity?.SetTag(ModelDiagnosticsTags.AgentDescription, agentDescription);
}

if (kernel is not null && kernel.Plugins.Count > 0)
{
var toolDefinitions = kernel.Plugins.GetFunctionsMetadata().Select(m => ToGenAIconventionsFormat(m));
activity?.SetTag(ModelDiagnosticsTags.AgentToolDefinitions, JsonSerializer.Serialize(toolDefinitions));
}

if (IsSensitiveEventsEnabled())
{
activity?.SetTag(
Expand Down Expand Up @@ -391,6 +398,49 @@ private static void ToGenAIConventionsFormat(ChatMessageContentItemCollection ch
sb.Append(']');
}

private static string ToGenAIconventionsFormat(KernelFunctionMetadata metadata)
{
var sb = new StringBuilder();

sb.Append("{\"type\": \"function\", \"name\": \"");
sb.Append(metadata.Name);
sb.Append("\", \"description\": \"");
sb.Append(metadata.Description);
sb.Append("\", \"parameters\": ");
ToGenAIconventionsFormat(metadata.Parameters, sb);
sb.Append('}');

return sb.ToString();
}

private static void ToGenAIconventionsFormat(IEnumerable<KernelParameterMetadata> parameters, StringBuilder? sb = null)
{
var properties = new Dictionary<string, KernelJsonSchema>();
var required = new List<string>();

foreach (var param in parameters)
{
if (param.Schema is not null)
{
properties[param.Name] = param.Schema;
}
if (param.IsRequired)
{
required.Add(param.Name);
}
}

var parametersJson = JsonSerializer.Serialize(new
{
type = "object",
properties,
required,
});

sb ??= new StringBuilder();
sb.Append(parametersJson);
}

/// <summary>
/// Convert a chat model response to a string aligned with the OTel GenAI Semantic Conventions format
/// </summary>
Expand Down Expand Up @@ -614,8 +664,9 @@ private static class ModelDiagnosticsTags
public const string AgentId = "gen_ai.agent.id";
public const string AgentName = "gen_ai.agent.name";
public const string AgentDescription = "gen_ai.agent.description";
public const string AgentInvocationInput = "gen_ai.agent.invocation_input";
public const string AgentInvocationOutput = "gen_ai.agent.invocation_output";
public const string AgentInvocationInput = "gen_ai.input.messages";
public const string AgentInvocationOutput = "gen_ai.output.messages";
public const string AgentToolDefinitions = "gen_ai.tool.definitions";

// Activity events
public const string EventName = "gen_ai.event.content";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,19 @@ def _start_as_current_span(agent: Agent):
if agent.description:
attributes[gen_ai_attributes.AGENT_DESCRIPTION] = agent.description

if agent.kernel.plugins:
# This will only capture the tools that are available in the kernel at the time of agent creation.
# If the agent is invoked with another kernel instance, the tools in that kernel will not be captured.
from semantic_kernel.connectors.ai.function_calling_utils import (
kernel_function_metadata_to_function_call_format,
)

tool_definitions = [
kernel_function_metadata_to_function_call_format(metadata)
for metadata in agent.kernel.get_full_list_of_function_metadata()
]
attributes[gen_ai_attributes.AGENT_TOOL_DEFINITIONS] = json.dumps(tool_definitions)

return tracer.start_as_current_span(f"{OPERATION_NAME} {agent.name}", attributes=attributes)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
AGENT_ID = "gen_ai.agent.id"
AGENT_NAME = "gen_ai.agent.name"
AGENT_DESCRIPTION = "gen_ai.agent.description"
AGENT_INVOCATION_INPUT = "gen_ai.agent.invocation_input"
AGENT_INVOCATION_OUTPUT = "gen_ai.agent.invocation_output"
AGENT_INVOCATION_INPUT = "gen_ai.input.messages"
AGENT_INVOCATION_OUTPUT = "gen_ai.output.messages"
AGENT_TOOL_DEFINITIONS = "gen_ai.tool.definitions"
ERROR_TYPE = "error.type"
Loading