Skip to content

Commit d30dc16

Browse files
committed
Tool server name.
1 parent b6f7324 commit d30dc16

File tree

7 files changed

+54
-8
lines changed

7 files changed

+54
-8
lines changed

src/Observability/Runtime/DTOs/Builders/ExecuteToolDataBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ private static void AddToolDetails(
8989
Dictionary<string, object?> attributes,
9090
ToolCallDetails toolCallDetails)
9191
{
92-
var (toolName, arguments, toolCallId, description, toolType, endpoint) = toolCallDetails;
92+
var (toolName, arguments, toolCallId, description, toolType, endpoint, toolServerName) = toolCallDetails;
9393
AddIfNotNull(attributes, OpenTelemetryConstants.GenAiToolNameKey, toolName);
9494
AddIfNotNull(attributes, OpenTelemetryConstants.GenAiToolArgumentsKey, arguments);
9595
AddIfNotNull(attributes, OpenTelemetryConstants.GenAiToolCallIdKey, toolCallId);
9696
AddIfNotNull(attributes, OpenTelemetryConstants.GenAiToolDescriptionKey, description);
9797
AddIfNotNull(attributes, OpenTelemetryConstants.GenAiToolTypeKey, toolType);
98+
AddIfNotNull(attributes, OpenTelemetryConstants.GenAiToolServerNameKey, toolServerName);
9899
if (endpoint != null)
99100
{
100101
AddIfNotNull(attributes, OpenTelemetryConstants.ServerAddressKey, endpoint.Host);

src/Observability/Runtime/Tracing/Contracts/ToolCallDetails.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@ public sealed class ToolCallDetails : IEquatable<ToolCallDetails>
2020
/// <param name="description">Optional description of the tool call.</param>
2121
/// <param name="toolType">Optional type classification for the tool.</param>
2222
/// <param name="endpoint">Optional endpoint for remote tool execution.</param>
23+
/// <param name="toolServerName">Optional server name for the tool.</param>
2324
public ToolCallDetails(
2425
string toolName,
2526
string? arguments,
2627
string? toolCallId = null,
2728
string? description = null,
2829
string? toolType = null,
29-
Uri? endpoint = null)
30+
Uri? endpoint = null,
31+
string? toolServerName = null)
3032
{
3133
ToolName = toolName;
3234
Arguments = arguments;
3335
ToolCallId = toolCallId;
3436
Description = description;
3537
ToolType = toolType;
3638
Endpoint = endpoint;
39+
ToolServerName = toolServerName;
3740
}
3841

3942
/// <summary>
@@ -66,6 +69,11 @@ public ToolCallDetails(
6669
/// </summary>
6770
public Uri? Endpoint { get; }
6871

72+
/// <summary>
73+
/// Gets the server name associated with the tool, when provided.
74+
/// </summary>
75+
public string? ToolServerName { get; }
76+
6977
/// <summary>
7078
/// Deconstructs this instance into individual tool call components.
7179
/// </summary>
@@ -75,14 +83,16 @@ public ToolCallDetails(
7583
/// <param name="description">Receives the human-readable description.</param>
7684
/// <param name="toolType">Receives the type hint.</param>
7785
/// <param name="endpoint">Receives the endpoint.</param>
78-
public void Deconstruct(out string toolName, out string? arguments, out string? toolCallId, out string? description, out string? toolType, out Uri? endpoint)
86+
/// <param name="toolServerName">Receives the tool server name.</param>
87+
public void Deconstruct(out string toolName, out string? arguments, out string? toolCallId, out string? description, out string? toolType, out Uri? endpoint, out string? toolServerName)
7988
{
8089
toolName = ToolName;
8190
arguments = Arguments;
8291
toolCallId = ToolCallId;
8392
description = Description;
8493
toolType = ToolType;
8594
endpoint = Endpoint;
95+
toolServerName = ToolServerName;
8696
}
8797

8898
/// <inheritdoc/>
@@ -98,7 +108,8 @@ public bool Equals(ToolCallDetails? other)
98108
string.Equals(ToolCallId, other.ToolCallId, StringComparison.Ordinal) &&
99109
string.Equals(Description, other.Description, StringComparison.Ordinal) &&
100110
string.Equals(ToolType, other.ToolType, StringComparison.Ordinal) &&
101-
EqualityComparer<Uri?>.Default.Equals(Endpoint, other.Endpoint);
111+
EqualityComparer<Uri?>.Default.Equals(Endpoint, other.Endpoint) &&
112+
string.Equals(ToolServerName, other.ToolServerName, StringComparison.Ordinal);
102113
}
103114

104115
/// <inheritdoc/>
@@ -119,6 +130,7 @@ public override int GetHashCode()
119130
hash = (hash * 31) + (Description != null ? StringComparer.Ordinal.GetHashCode(Description) : 0);
120131
hash = (hash * 31) + (ToolType != null ? StringComparer.Ordinal.GetHashCode(ToolType) : 0);
121132
hash = (hash * 31) + EqualityComparer<Uri?>.Default.GetHashCode(Endpoint);
133+
hash = (hash * 31) + (ToolServerName != null ? StringComparer.Ordinal.GetHashCode(ToolServerName) : 0);
122134
return hash;
123135
}
124136
}

src/Observability/Runtime/Tracing/Scopes/ExecuteToolScope.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,13 @@ private ExecuteToolScope(ToolCallDetails details, AgentDetails agentDetails, Ten
5656
conversationId: conversationId,
5757
sourceMetadata: sourceMetadata)
5858
{
59-
var (toolName, arguments, toolCallId, description, toolType, endpoint) = details;
59+
var (toolName, arguments, toolCallId, description, toolType, endpoint, toolServerName) = details;
6060
SetTagMaybe(OpenTelemetryConstants.GenAiToolNameKey, toolName);
6161
SetTagMaybe(OpenTelemetryConstants.GenAiToolArgumentsKey, arguments);
6262
SetTagMaybe(OpenTelemetryConstants.GenAiToolTypeKey, toolType);
6363
SetTagMaybe(OpenTelemetryConstants.GenAiToolCallIdKey, toolCallId);
6464
SetTagMaybe(OpenTelemetryConstants.GenAiToolDescriptionKey, description);
65+
SetTagMaybe(OpenTelemetryConstants.GenAiToolServerNameKey, toolServerName);
6566
SetTagMaybe(OpenTelemetryConstants.ThreatDiagnosticsSummaryKey, threatDiagnosticsSummary?.ToJson());
6667

6768
if (endpoint !=null)

src/Observability/Runtime/Tracing/Scopes/OpenTelemetryConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ public enum OperationNames
134134
/// The GenAI tool type key.
135135
/// </summary>
136136
public const string GenAiToolTypeKey = "gen_ai.tool.type";
137+
138+
/// <summary>
139+
/// The GenAI tool server name key.
140+
/// </summary>
141+
public const string GenAiToolServerNameKey = "gen_ai.tool.server.name";
137142
#endregion
138143

139144
/// <summary>

src/Tests/Microsoft.Agents.A365.Observability.Runtime.IntegrationTests/Agent365ExporterE2ETests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ public async Task AddTracing_And_ExecuteToolScope_ExporterMakesExpectedRequest()
144144
toolCallId: "call-456",
145145
description: "Test tool call description",
146146
toolType: "custom-type",
147-
endpoint: endpoint);
147+
endpoint: endpoint,
148+
toolServerName: "test-tool-server");
148149

149150
var expectedThreatDiagnosticsSummary = new ThreatDiagnosticsSummary(
150151
blockAction: false,
@@ -190,6 +191,7 @@ public async Task AddTracing_And_ExecuteToolScope_ExporterMakesExpectedRequest()
190191
this.GetAttribute(attributes, "gen_ai.tool.call.id").Should().Be(toolCallDetails.ToolCallId);
191192
this.GetAttribute(attributes, "gen_ai.tool.description").Should().Be(toolCallDetails.Description);
192193
this.GetAttribute(attributes, "gen_ai.tool.type").Should().Be(toolCallDetails.ToolType);
194+
this.GetAttribute(attributes, "gen_ai.tool.server.name").Should().Be(toolCallDetails.ToolServerName);
193195
this.GetAttribute(attributes, "server.address").Should().Be(endpoint.Host);
194196
this.GetAttribute(attributes, "server.port").Should().Be(endpoint.Port.ToString());
195197
this.GetAttribute(attributes, "gen_ai.event.content").Should().Be("Tool response content");

src/Tests/Microsoft.Agents.A365.Observability.Runtime.Tests/DTOs/Builders/ExecuteToolDataBuilderTests.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void Build_WithFullToolDetails_IncludesAllToolAttributes()
5151
{
5252
// Arrange
5353
var endpoint = new Uri("https://example.com:7071");
54-
var toolDetails = new ToolCallDetails("toolB", "{b:2}", "call-123", "Test tool", "function", endpoint);
54+
var toolDetails = new ToolCallDetails("toolB", "{b:2}", "call-123", "Test tool", "function", endpoint, "my-tool-server");
5555
var agent = new AgentDetails("agent-2", "AgentTwo", "Desc", agentAUID: "auid", agentUPN: "[email protected]", agentBlueprintId: "bp-1");
5656
var tenant = new TenantDetails(Guid.NewGuid());
5757
var conversationId = "conv-full";
@@ -64,6 +64,7 @@ public void Build_WithFullToolDetails_IncludesAllToolAttributes()
6464
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolCallIdKey).WhoseValue.Should().Be("call-123");
6565
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolDescriptionKey).WhoseValue.Should().Be("Test tool");
6666
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolTypeKey).WhoseValue.Should().Be("function");
67+
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolServerNameKey).WhoseValue.Should().Be("my-tool-server");
6768
attrs.Should().ContainKey(OpenTelemetryConstants.ServerAddressKey).WhoseValue.Should().Be("example.com");
6869
attrs.Should().ContainKey(OpenTelemetryConstants.ServerPortKey).WhoseValue.Should().Be(7071);
6970
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiAgentAUIDKey).WhoseValue.Should().Be("auid");
@@ -153,6 +154,7 @@ public void Build_WithNullOptionalParameters_OmitsThoseAttributes()
153154
data.Attributes.Should().NotContainKey(OpenTelemetryConstants.GenAiToolCallIdKey);
154155
data.Attributes.Should().NotContainKey(OpenTelemetryConstants.GenAiToolDescriptionKey);
155156
data.Attributes.Should().NotContainKey(OpenTelemetryConstants.GenAiToolTypeKey);
157+
data.Attributes.Should().NotContainKey(OpenTelemetryConstants.GenAiToolServerNameKey);
156158
data.Attributes.Should().ContainKey(OpenTelemetryConstants.GenAiConversationIdKey).WhoseValue.Should().Be(conversationId);
157159
data.Attributes.Should().NotContainKey(OpenTelemetryConstants.GenAiEventContent);
158160
}
@@ -201,7 +203,7 @@ public void Build_WithAllParameters_SetsAllExpectedAttributes()
201203
{
202204
// Arrange
203205
var endpoint = new Uri("https://example.org:6060");
204-
var toolDetails = new ToolCallDetails("toolJ", "{x:1}", "call-999", "Full tool", "extension", endpoint);
206+
var toolDetails = new ToolCallDetails("toolJ", "{x:1}", "call-999", "Full tool", "extension", endpoint, "full-tool-server");
205207
var agent = new AgentDetails("agent-10", "AgentTen", "Desc", agentAUID: "auid10", agentUPN: "[email protected]", agentBlueprintId: "bp-10");
206208
var tenant = new TenantDetails(Guid.NewGuid());
207209
var conversationId = "conv-all";
@@ -228,6 +230,7 @@ public void Build_WithAllParameters_SetsAllExpectedAttributes()
228230
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolCallIdKey);
229231
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolDescriptionKey);
230232
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolTypeKey);
233+
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiToolServerNameKey).WhoseValue.Should().Be("full-tool-server");
231234
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiConversationIdKey);
232235
attrs.Should().ContainKey(OpenTelemetryConstants.GenAiEventContent);
233236
data.StartTime.Should().Be(start);

src/Tests/Microsoft.Agents.A365.Observability.Runtime.Tests/Tracing/Scopes/ExecuteToolScopeTest.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,26 @@ public void RecordThreatDiagnosticsSummary_SetsTagCorrectly()
207207
tagValue.Should().Contain("\"reason\":\"Blocked due to policy violation.\"");
208208
tagValue.Should().Contain("data-loss-prevention");
209209
}
210+
211+
[TestMethod]
212+
public void Start_ToolServerName_IsSetCorrectly()
213+
{
214+
// Arrange
215+
const string expectedToolServerName = "test-tool-server";
216+
var toolCallDetails = new ToolCallDetails(
217+
toolName: "TestTool",
218+
arguments: "args",
219+
toolServerName: expectedToolServerName);
220+
var agentDetails = Util.GetAgentDetails();
221+
var tenantDetails = Util.GetTenantDetails();
222+
223+
// Act
224+
var activity = ListenForActivity(() =>
225+
{
226+
using var scope = ExecuteToolScope.Start(toolCallDetails, agentDetails, tenantDetails);
227+
});
228+
229+
// Assert
230+
activity.ShouldHaveTag(OpenTelemetryConstants.GenAiToolServerNameKey, expectedToolServerName);
231+
}
210232
}

0 commit comments

Comments
 (0)