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
3 changes: 2 additions & 1 deletion eng/Packages.Data.props
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@
<PackageReference Update="OpenAI" Version="[2.7.0,3.0)" />
<!-- Foundry libs depend on OpenAI; float SCM with upstream version -->
<PackageReference Update="System.ClientModel" Version="*" />
<PackageReference Update="System.Text.Json" Version="10.0.0" />
</ItemGroup>

<ItemGroup Condition="$(MSBuildProjectName.StartsWith('Azure.AI.AgentServer'))">
Expand Down Expand Up @@ -501,4 +502,4 @@
<UnbrandedGeneratorVersion>1.0.0-alpha.20251203.1</UnbrandedGeneratorVersion>
<AzureGeneratorVersion>1.0.0-alpha.20251125.3</AzureGeneratorVersion>
</PropertyGroup>
</Project>
</Project>
64 changes: 64 additions & 0 deletions sdk/ai/Azure.AI.Projects.OpenAI/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Develop Agents using the Azure AI Foundry platform, leveraging an extensive ecos
- [MCP tool with project connection](#mcp-tool-with-project-connection)
- [OpenAPI tool](#openapi-tool)
- [OpenAPI tool with project connection](#openapi-tool-project-connection)
- [SharePoint tool](#sharepoint-tool)
- [Tracing](#tracing)
- [Tracing to Azure Monitor](#tracing-to-azure-monitor)
- [Tracing to Console](#tracing-to-console)
Expand Down Expand Up @@ -1092,6 +1093,68 @@ OpenAIResponse response = await responseClient.CreateResponseAsync(
Console.WriteLine(response.GetOutputText());
```

## SharePoint tool
`SharepointAgentTool` allows Agent to access SharePoint pages to get the data context. Use the SharePoint connection name as it is shown in the connections section of Microsoft Foundry to get the connection. Get the connection ID to initialize the `SharePointGroundingToolOptions`, which will be used to create `SharepointAgentTool`.

```C# Snippet:Sample_CreateAgent_Sharepoint_Async
AIProjectConnection sharepointConnection = await projectClient.Connections.GetConnectionAsync(sharepointConnectionName);
SharePointGroundingToolOptions sharepointToolOption = new()
{
ProjectConnections = { new ToolProjectConnection(projectConnectionId: sharepointConnection.Id) }
};
PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
{
Instructions = "You are a helpful assistant.",
Tools = { new SharepointAgentTool(sharepointToolOption), }
};
AgentVersion agentVersion = await projectClient.Agents.CreateAgentVersionAsync(
agentName: "myAgent",
options: new(agentDefinition));
```

Create the response and make sure we are always using tool.

```C# Snippet:Sample_CreateResponse_Sharepoint_Async
ProjectResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);
ResponseCreationOptions responseOptions = new()
{
ToolChoice = ResponseToolChoice.CreateRequiredChoice()
};
OpenAIResponse response = await responseClient.CreateResponseAsync("What is Contoso whistleblower policy", options: responseOptions);
```

SharePoint tool can create the reference to the page, grounding the data. We will create the `GetFormattedAnnotation` method to get the URI annotation.

```C# Snippet:Sample_FormatReference_Sharepoint
private static string GetFormattedAnnotation(OpenAIResponse response)
{
foreach (ResponseItem item in response.OutputItems)
{
if (item is MessageResponseItem messageItem)
{
foreach (ResponseContentPart content in messageItem.Content)
{
foreach (ResponseMessageAnnotation annotation in content.OutputTextAnnotations)
{
if (annotation is UriCitationMessageAnnotation uriAnnotation)
{
return $" [{uriAnnotation.Title}]({uriAnnotation.Uri})";
}
}
}
}
}
return "";
}
```

Print the Agent output and add the annotation at the end.

```C# Snippet:Sample_WaitForResponse_Sharepoint
Assert.That(response.Status, Is.EqualTo(ResponseStatus.Completed));
Console.WriteLine($"{response.GetOutputText()}{GetFormattedAnnotation(response)}");
```

## Tracing
**Note:** The tracing functionality is currently in preview with limited scope. Only agent creation operations generate dedicated gen_ai traces currently. As a preview feature, the trace structure including spans, attributes, and events may change in future releases.

Expand Down Expand Up @@ -1131,6 +1194,7 @@ var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddAzureMonitorTraceExporter().Build();
```


### Tracing to Console

For tracing to console from your application, install the OpenTelemetry.Exporter.Console with [NuGet](https://www.nuget.org/ ):
Expand Down
115 changes: 115 additions & 0 deletions sdk/ai/Azure.AI.Projects.OpenAI/samples/Sample24_Sharepoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Sample for use of an Agent with SharePoint in Azure.AI.Projets.OpenAI.

To enable your Agent to access SharePoint, use `SharepointAgentTool`.

1. First, create an agent client and read the environment variables, which will be used in the next steps.

```C# Snippet:Sample_CreateAgentClient_Sharepoint
var projectEndpoint = System.Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
var modelDeploymentName = System.Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
var sharepointConnectionName = System.Environment.GetEnvironmentVariable("SHAREPOINT_CONNECTION_NAME");
AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: new DefaultAzureCredential());
```

2. Use the SharePoint connection name as it is shown in the connections section of Microsoft Foundry to get the connection. Get the connection ID to initialize the `SharePointGroundingToolOptions`, which will be used to create `SharepointAgentTool`. We will use this tool to create an Agent.

Synchronous sample:
```C# Snippet:Sample_CreateAgent_Sharepoint_Sync
AIProjectConnection sharepointConnection = projectClient.Connections.GetConnection(sharepointConnectionName);
SharePointGroundingToolOptions sharepointToolOption = new()
{
ProjectConnections = { new ToolProjectConnection(projectConnectionId: sharepointConnection.Id) }
};
PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
{
Instructions = "You are a helpful assistant.",
Tools = { new SharepointAgentTool(sharepointToolOption), }
};
AgentVersion agentVersion = projectClient.Agents.CreateAgentVersion(
agentName: "myAgent",
options: new(agentDefinition));
```

Asynchronous sample:
```C# Snippet:Sample_CreateAgent_Sharepoint_Async
AIProjectConnection sharepointConnection = await projectClient.Connections.GetConnectionAsync(sharepointConnectionName);
SharePointGroundingToolOptions sharepointToolOption = new()
{
ProjectConnections = { new ToolProjectConnection(projectConnectionId: sharepointConnection.Id) }
};
PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
{
Instructions = "You are a helpful assistant.",
Tools = { new SharepointAgentTool(sharepointToolOption), }
};
AgentVersion agentVersion = await projectClient.Agents.CreateAgentVersionAsync(
agentName: "myAgent",
options: new(agentDefinition));
```

3. Create the response and make sure we are always using tool.

Synchronous sample:
```C# Snippet:Sample_CreateResponse_Sharepoint_Sync
ProjectResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);
ResponseCreationOptions responseOptions = new()
{
ToolChoice = ResponseToolChoice.CreateRequiredChoice()
};
OpenAIResponse response = responseClient.CreateResponse("What is Contoso whistleblower policy", options: responseOptions);
```

Asynchronous sample:
```C# Snippet:Sample_CreateResponse_Sharepoint_Async
ProjectResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);
ResponseCreationOptions responseOptions = new()
{
ToolChoice = ResponseToolChoice.CreateRequiredChoice()
};
OpenAIResponse response = await responseClient.CreateResponseAsync("What is Contoso whistleblower policy", options: responseOptions);
```

4. SharePoint tool can create the reference to the page, grounding the data. We will create the `GetFormattedAnnotation` method to get the URI annotation.

```C# Snippet:Sample_FormatReference_Sharepoint
private static string GetFormattedAnnotation(OpenAIResponse response)
{
foreach (ResponseItem item in response.OutputItems)
{
if (item is MessageResponseItem messageItem)
{
foreach (ResponseContentPart content in messageItem.Content)
{
foreach (ResponseMessageAnnotation annotation in content.OutputTextAnnotations)
{
if (annotation is UriCitationMessageAnnotation uriAnnotation)
{
return $" [{uriAnnotation.Title}]({uriAnnotation.Uri})";
}
}
}
}
}
return "";
}
```

5. Print the Agent output and add the annotation at the end.

```C# Snippet:Sample_WaitForResponse_Sharepoint
Assert.That(response.Status, Is.EqualTo(ResponseStatus.Completed));
Console.WriteLine($"{response.GetOutputText()}{GetFormattedAnnotation(response)}");
```


6. Clean up resources by deleting thread and agent.

Synchronous sample:
```C# Snippet:Sample_Cleanup_Sharepoint_Sync
projectClient.Agents.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
```

Asynchronous sample:
```C# Snippet:Sample_Cleanup_Sharepoint_Async
await projectClient.Agents.DeleteAgentVersionAsync(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
```
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class ProjectsOpenAITestEnvironment : TestEnvironment
public string CUSTOM_BING_CONNECTION_NAME => GetRecordedVariable("CUSTOM_BING_CONNECTION_NAME");
public string BING_CUSTOM_SEARCH_INSTANCE_NAME => GetRecordedVariable("BING_CUSTOM_SEARCH_INSTANCE_NAME");
public string MCP_PROJECT_CONNECTION_NAME => GetRecordedOptionalVariable("MCP_PROJECT_CONNECTION_NAME");
public string SHAREPOINT_CONNECTION_NAME => GetRecordedOptionalVariable("SHAREPOINT_CONNECTION_NAME");
public string WrappedGetRecordedVariable(string key, bool isSecret = true)
{
try
Expand Down
139 changes: 139 additions & 0 deletions sdk/ai/Azure.AI.Projects.OpenAI/tests/Samples/Sample_Sharepoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading.Tasks;
using Azure.Identity;
using Microsoft.ClientModel.TestFramework;
using NUnit.Framework;
using OpenAI.Responses;

namespace Azure.AI.Projects.OpenAI.Tests.Samples;

public class Sample_Sharepoint : ProjectsOpenAITestBase
{
[Test]
[AsyncOnly]
public async Task SharepointAsync()
{
IgnoreSampleMayBe();
#region Snippet:Sample_CreateAgentClient_Sharepoint
#if SNIPPET
var projectEndpoint = System.Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
var modelDeploymentName = System.Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
var sharepointConnectionName = System.Environment.GetEnvironmentVariable("SHAREPOINT_CONNECTION_NAME");
#else
var projectEndpoint = TestEnvironment.PROJECT_ENDPOINT;
var modelDeploymentName = TestEnvironment.MODELDEPLOYMENTNAME;
var sharepointConnectionName = TestEnvironment.SHAREPOINT_CONNECTION_NAME;
#endif
AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: new DefaultAzureCredential());

#endregion
#region Snippet:Sample_CreateAgent_Sharepoint_Async
AIProjectConnection sharepointConnection = await projectClient.Connections.GetConnectionAsync(sharepointConnectionName);
SharePointGroundingToolOptions sharepointToolOption = new()
{
ProjectConnections = { new ToolProjectConnection(projectConnectionId: sharepointConnection.Id) }
};
PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
{
Instructions = "You are a helpful assistant.",
Tools = { new SharepointAgentTool(sharepointToolOption), }
};
AgentVersion agentVersion = await projectClient.Agents.CreateAgentVersionAsync(
agentName: "myAgent",
options: new(agentDefinition));
#endregion
#region Snippet:Sample_CreateResponse_Sharepoint_Async
ProjectResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);
ResponseCreationOptions responseOptions = new()
{
ToolChoice = ResponseToolChoice.CreateRequiredChoice()
};
OpenAIResponse response = await responseClient.CreateResponseAsync("What is Contoso whistleblower policy", options: responseOptions);
#endregion

#region Snippet:Sample_WaitForResponse_Sharepoint
Assert.That(response.Status, Is.EqualTo(ResponseStatus.Completed));
Console.WriteLine($"{response.GetOutputText()}{GetFormattedAnnotation(response)}");
#endregion

#region Snippet:Sample_Cleanup_Sharepoint_Async
await projectClient.Agents.DeleteAgentVersionAsync(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
#endregion
}

[Test]
[SyncOnly]
public void Sharepoint()
{
IgnoreSampleMayBe();
#if SNIPPET
var projectEndpoint = System.Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
var modelDeploymentName = System.Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
var sharepointConnectionName = System.Environment.GetEnvironmentVariable("SHAREPOINT_CONNECTION_NAME");
#else
var projectEndpoint = TestEnvironment.PROJECT_ENDPOINT;
var modelDeploymentName = TestEnvironment.MODELDEPLOYMENTNAME;
var sharepointConnectionName = TestEnvironment.SHAREPOINT_CONNECTION_NAME;
#endif
AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: new DefaultAzureCredential());

#region Snippet:Sample_CreateAgent_Sharepoint_Sync
AIProjectConnection sharepointConnection = projectClient.Connections.GetConnection(sharepointConnectionName);
SharePointGroundingToolOptions sharepointToolOption = new()
{
ProjectConnections = { new ToolProjectConnection(projectConnectionId: sharepointConnection.Id) }
};
PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
{
Instructions = "You are a helpful assistant.",
Tools = { new SharepointAgentTool(sharepointToolOption), }
};
AgentVersion agentVersion = projectClient.Agents.CreateAgentVersion(
agentName: "myAgent",
options: new(agentDefinition));
#endregion
#region Snippet:Sample_CreateResponse_Sharepoint_Sync
ProjectResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);
ResponseCreationOptions responseOptions = new()
{
ToolChoice = ResponseToolChoice.CreateRequiredChoice()
};
OpenAIResponse response = responseClient.CreateResponse("What is Contoso whistleblower policy", options: responseOptions);
#endregion

Assert.That(response.Status, Is.EqualTo(ResponseStatus.Completed));
Console.WriteLine($"{response.GetOutputText()}{GetFormattedAnnotation(response)}");

#region Snippet:Sample_Cleanup_Sharepoint_Sync
projectClient.Agents.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
#endregion
}

#region Snippet:Sample_FormatReference_Sharepoint
private static string GetFormattedAnnotation(OpenAIResponse response)
{
foreach (ResponseItem item in response.OutputItems)
{
if (item is MessageResponseItem messageItem)
{
foreach (ResponseContentPart content in messageItem.Content)
{
foreach (ResponseMessageAnnotation annotation in content.OutputTextAnnotations)
{
if (annotation is UriCitationMessageAnnotation uriAnnotation)
{
return $" [{uriAnnotation.Title}]({uriAnnotation.Uri})";
}
}
}
}
}
return "";
}
#endregion
public Sample_Sharepoint(bool isAsync) : base(isAsync)
{ }
}
Loading
Loading