From 1bbd91e2696413c0659a7af104bcb41fc6a15086 Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Thu, 22 Jan 2026 13:50:42 +0000 Subject: [PATCH 1/4] Fix ChatHistory storage by service table (#826) --- agent-framework/user-guide/agents/agent-types/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agent-framework/user-guide/agents/agent-types/index.md b/agent-framework/user-guide/agents/agent-types/index.md index 7f375a9e..37381e55 100644 --- a/agent-framework/user-guide/agents/agent-types/index.md +++ b/agent-framework/user-guide/agents/agent-types/index.md @@ -44,11 +44,11 @@ var agent = new ChatClientAgent(chatClient, instructions: "You are a helpful ass To make creating these agents even easier, Agent Framework provides helpers for many popular services. For more information, see the documentation for each service. -| Underlying inference service | Description | Service chat history storage support | Custom chat history storage support | -|------------------------------|-------------|--------------------------------------|-------------------------------------| +| Underlying inference service | Description | Service chat history storage supported | InMemory/Custom chat history storage supported | +|------------------------------|-------------|----------------------------------------|------------------------------------------------| |[Azure AI Foundry Agent](./azure-ai-foundry-agent.md)|An agent that uses the Azure AI Foundry Agents Service as its backend.|Yes|No| |[Azure AI Foundry Models ChatCompletion](./azure-ai-foundry-models-chat-completion-agent.md)|An agent that uses any of the models deployed in the Azure AI Foundry Service as its backend via ChatCompletion.|No|Yes| -|[Azure AI Foundry Models Responses](./azure-ai-foundry-models-responses-agent.md)|An agent that uses any of the models deployed in the Azure AI Foundry Service as its backend via Responses.|No|Yes| +|[Azure AI Foundry Models Responses](./azure-ai-foundry-models-responses-agent.md)|An agent that uses any of the models deployed in the Azure AI Foundry Service as its backend via Responses.|Yes|Yes| |[Azure OpenAI ChatCompletion](./azure-openai-chat-completion-agent.md)|An agent that uses the Azure OpenAI ChatCompletion service.|No|Yes| |[Azure OpenAI Responses](./azure-openai-responses-agent.md)|An agent that uses the Azure OpenAI Responses service.|Yes|Yes| |[OpenAI ChatCompletion](./openai-chat-completion-agent.md)|An agent that uses the OpenAI ChatCompletion service.|No|Yes| From f99085eb00191483c5fcab2fe412a60f93d55ee5 Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Tue, 27 Jan 2026 12:40:10 +0000 Subject: [PATCH 2/4] Rename ChatMessageStore to ChatHistoryProvider (#829) --- .../third-party-chat-history-storage.md | 36 ++++++++-------- .../user-guide/agents/agent-memory.md | 42 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/agent-framework/tutorials/agents/third-party-chat-history-storage.md b/agent-framework/tutorials/agents/third-party-chat-history-storage.md index 525f7e9a..7a14e9aa 100644 --- a/agent-framework/tutorials/agents/third-party-chat-history-storage.md +++ b/agent-framework/tutorials/agents/third-party-chat-history-storage.md @@ -1,6 +1,6 @@ --- title: Storing Chat History in 3rd Party Storage -description: How to store agent chat history in external storage using a custom ChatMessageStore. +description: How to store agent chat history in external storage zone_pivot_groups: programming-languages author: westey-m ms.topic: tutorial @@ -13,7 +13,7 @@ ms.service: agent-framework ::: zone pivot="programming-language-csharp" -This tutorial shows how to store agent chat history in external storage by implementing a custom `ChatMessageStore` and using it with a `ChatClientAgent`. +This tutorial shows how to store agent chat history in external storage by implementing a custom `ChatHistoryProvider` and using it with a `ChatClientAgent`. By default, when using `ChatClientAgent`, chat history is stored either in memory in the `AgentThread` object or the underlying inference service, if the service supports it. @@ -39,9 +39,9 @@ In addition, you'll use the in-memory vector store to store chat messages. dotnet add package Microsoft.SemanticKernel.Connectors.InMemory --prerelease ``` -## Create a custom ChatMessage Store +## Create a custom ChatHistoryProvider -To create a custom `ChatMessageStore`, you need to implement the abstract `ChatMessageStore` class and provide implementations for the required methods. +To create a custom `ChatHistoryProvider`, you need to implement the abstract `ChatHistoryProvider` class and provide implementations for the required methods. ### Message storage and retrieval methods @@ -56,13 +56,13 @@ Any chat history reduction logic, such as summarization or trimming, should be d ### Serialization -`ChatMessageStore` instances are created and attached to an `AgentThread` when the thread is created, and when a thread is resumed from a serialized state. +`ChatHistoryProvider` instances are created and attached to an `AgentThread` when the thread is created, and when a thread is resumed from a serialized state. -While the actual messages making up the chat history are stored externally, the `ChatMessageStore` instance might need to store keys or other state to identify the chat history in the external store. +While the actual messages making up the chat history are stored externally, the `ChatHistoryProvider` instance might need to store keys or other state to identify the chat history in the external store. -To allow persisting threads, you need to implement the `Serialize` method of the `ChatMessageStore` class. This method should return a `JsonElement` containing the state needed to restore the store later. When deserializing, the agent framework will pass this serialized state to the ChatMessageStoreFactory, allowing you to use it to recreate the store. +To allow persisting threads, you need to implement the `Serialize` method of the `ChatHistoryProvider` class. This method should return a `JsonElement` containing the state needed to restore the provider later. When deserializing, the agent framework will pass this serialized state to the ChatHistoryProviderFactory, allowing you to use it to recreate the provider. -### Sample ChatMessageStore implementation +### Sample ChatHistoryProvider implementation The following sample implementation stores chat messages in a vector store. @@ -87,11 +87,11 @@ using Microsoft.Extensions.AI; using Microsoft.Extensions.VectorData; using Microsoft.SemanticKernel.Connectors.InMemory; -internal sealed class VectorChatMessageStore : ChatMessageStore +internal sealed class VectorChatHistoryProvider : ChatHistoryProvider { private readonly VectorStore _vectorStore; - public VectorChatMessageStore( + public VectorChatHistoryProvider( VectorStore vectorStore, JsonElement serializedStoreState, JsonSerializerOptions? jsonSerializerOptions = null) @@ -185,13 +185,13 @@ internal sealed class VectorChatMessageStore : ChatMessageStore } ``` -## Using the custom ChatMessageStore with a ChatClientAgent +## Using the custom ChatHistoryProvider with a ChatClientAgent -To use the custom `ChatMessageStore`, you need to provide a `ChatMessageStoreFactory` when creating the agent. This factory allows the agent to create a new instance of the desired `ChatMessageStore` for each thread. +To use the custom `ChatHistoryProvider`, you need to provide a `ChatHistoryProviderFactory` when creating the agent. This factory allows the agent to create a new instance of the desired `ChatHistoryProvider` for each thread. -When creating a `ChatClientAgent` it is possible to provide a `ChatClientAgentOptions` object that allows providing the `ChatMessageStoreFactory` in addition to all other agent options. +When creating a `ChatClientAgent` it is possible to provide a `ChatClientAgentOptions` object that allows providing the `ChatHistoryProviderFactory` in addition to all other agent options. -The factory is an async function that receives a context object and a cancellation token, and returns a `ValueTask`. +The factory is an async function that receives a context object and a cancellation token, and returns a `ValueTask`. ```csharp using Azure.AI.OpenAI; @@ -210,11 +210,11 @@ AIAgent agent = new AzureOpenAIClient( { Name = "Joker", ChatOptions = new() { Instructions = "You are good at telling jokes." }, - ChatMessageStoreFactory = (ctx, ct) => new ValueTask( - // Create a new chat message store for this agent that stores the messages in a vector store. - // Each thread must get its own copy of the VectorChatMessageStore, since the store + ChatHistoryProviderFactory = (ctx, ct) => new ValueTask( + // Create a new chat history provider for this agent that stores the messages in a vector store. + // Each thread must get its own copy of the VectorChatHistoryProvider, since the provider // also contains the id that the thread is stored under. - new VectorChatMessageStore( + new VectorChatHistoryProvider( vectorStore, ctx.SerializedState, ctx.JsonSerializerOptions)) diff --git a/agent-framework/user-guide/agents/agent-memory.md b/agent-framework/user-guide/agents/agent-memory.md index f0e99887..9bee58ac 100644 --- a/agent-framework/user-guide/agents/agent-memory.md +++ b/agent-framework/user-guide/agents/agent-memory.md @@ -21,7 +21,7 @@ Various chat history storage options are supported by Agent Framework. The avail The two main supported scenarios are: -- **In-memory storage**: Agent is built on a service that doesn't support in-service storage of chat history (for example, OpenAI Chat Completion). By default, Agent Framework stores the full chat history in-memory in the `AgentThread` object, but developers can provide a custom `ChatMessageStore` implementation to store chat history in a third-party store if required. +- **In-memory storage**: Agent is built on a service that doesn't support in-service storage of chat history (for example, OpenAI Chat Completion). By default, Agent Framework stores the full chat history in-memory in the `AgentThread` object, but developers can provide a custom `ChatHistoryProvider` implementation to store chat history in a third-party store if required. - **In-service storage**: Agent is built on a service that requires in-service storage of chat history (for example, Azure AI Foundry Persistent Agents). Agent Framework stores the ID of the remote chat history in the `AgentThread` object, and no other chat history storage options are supported. ### In-memory chat history storage @@ -49,17 +49,17 @@ IList? messages = thread.GetService>(); #### Chat history reduction with in-memory storage -The built-in `InMemoryChatMessageStore` that's used by default when the underlying service does not support in-service storage, +The built-in `InMemoryChatHistoryProvider` that's used by default when the underlying service does not support in-service storage, can be configured with a reducer to manage the size of the chat history. This is useful to avoid exceeding the context size limits of the underlying service. -The `InMemoryChatMessageStore` can take an optional `Microsoft.Extensions.AI.IChatReducer` implementation to reduce the size of the chat history. +The `InMemoryChatHistoryProvider` can take an optional `Microsoft.Extensions.AI.IChatReducer` implementation to reduce the size of the chat history. It also allows you to configure the event during which the reducer is invoked, either after a message is added to the chat history or before the chat history is returned for the next invocation. -To configure the `InMemoryChatMessageStore` with a reducer, you can provide a factory to construct a new `InMemoryChatMessageStore` -for each new `AgentThread` and pass it a reducer of your choice. The `InMemoryChatMessageStore` can also be passed an optional trigger event -which can be set to either `InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded` or `InMemoryChatMessageStore.ChatReducerTriggerEvent.BeforeMessagesRetrieval`. +To configure the `InMemoryChatHistoryProvider` with a reducer, you can provide a factory to construct a new `InMemoryChatHistoryProvider` +for each new `AgentThread` and pass it a reducer of your choice. The `InMemoryChatHistoryProvider` can also be passed an optional trigger event +which can be set to either `InMemoryChatHistoryProvider.ChatReducerTriggerEvent.AfterMessageAdded` or `InMemoryChatHistoryProvider.ChatReducerTriggerEvent.BeforeMessagesRetrieval`. The factory is an async function that receives a context object and a cancellation token. @@ -70,17 +70,17 @@ AIAgent agent = new OpenAIClient("") { Name = JokerName, ChatOptions = new() { Instructions = JokerInstructions }, - ChatMessageStoreFactory = (ctx, ct) => new ValueTask( - new InMemoryChatMessageStore( + ChatHistoryProviderFactory = (ctx, ct) => new ValueTask( + new InMemoryChatHistoryProvider( new MessageCountingChatReducer(2), ctx.SerializedState, ctx.JsonSerializerOptions, - InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded)) + InMemoryChatHistoryProvider.ChatReducerTriggerEvent.AfterMessageAdded)) }); ``` > [!NOTE] -> This feature is only supported when using the `InMemoryChatMessageStore`. When a service has in-service chat history storage, it is up to the service itself to manage the size of the chat history. Similarly, when using 3rd party storage (see below), it is up to the 3rd party storage solution to manage the chat history size. If you provide a `ChatMessageStoreFactory` for a message store but you use a service with built-in chat history storage, the factory will not be used. +> This feature is only supported when using the `InMemoryChatHistoryProvider`. When a service has in-service chat history storage, it is up to the service itself to manage the size of the chat history. Similarly, when using 3rd party storage (see below), it is up to the 3rd party storage solution to manage the chat history size. If you provide a `ChatHistoryProviderFactory` for a chat history provider but you use a service with built-in chat history storage, the factory will not be used. ### Inference service chat history storage @@ -102,16 +102,16 @@ Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread) ### Third-party chat history storage -When using a service that does not support in-service storage of chat history, Agent Framework allows developers to replace the default in-memory storage of chat history with third-party chat history storage. The developer is required to provide a subclass of the base abstract `ChatMessageStore` class. +When using a service that does not support in-service storage of chat history, Agent Framework allows developers to replace the default in-memory storage of chat history with third-party chat history storage. The developer is required to provide a subclass of the base abstract `ChatHistoryProvider` class. -The `ChatMessageStore` class defines the interface for storing and retrieving chat messages. Developers must implement the `InvokedAsync` and `InvokingAsync` methods to add messages to the remote store as they are generated, and retrieve messages from the remote store before invoking the underlying service. +The `ChatHistoryProvider` class defines the interface for storing and retrieving chat messages. Developers must implement the `InvokedAsync` and `InvokingAsync` methods to add messages to the remote store as they are generated, and retrieve messages from the remote store before invoking the underlying service. -The agent will use all messages returned by `InvokingAsync` when processing a user query. It is up to the implementer of `ChatMessageStore` to ensure that the size of the chat history does not exceed the context window of the underlying service. +The agent will use all messages returned by `InvokingAsync` when processing a user query. It is up to the implementer of `ChatHistoryProvider` to ensure that the size of the chat history does not exceed the context window of the underlying service. -When implementing a custom `ChatMessageStore` which stores chat history in a remote store, the chat history for that thread should be stored under a key that is unique to that thread. The `ChatMessageStore` implementation should generate this key and keep it in its state. `ChatMessageStore` has a `Serialize` method that can be overridden to serialize its state when the thread is serialized. The `ChatMessageStore` should also provide a constructor that takes a as input to support deserialization of its state. +When implementing a custom `ChatHistoryProvider` which stores chat history in a remote store, the chat history for that thread should be stored under a key that is unique to that thread. The `ChatHistoryProvider` implementation should generate this key and keep it in its state. `ChatHistoryProvider` has a `Serialize` method that can be overridden to serialize its state when the thread is serialized. The `ChatHistoryProvider` should also provide a constructor that takes a as input to support deserialization of its state. -To supply a custom `ChatMessageStore` to a `ChatClientAgent`, you can use the `ChatMessageStoreFactory` option when creating the agent. -Here is an example showing how to pass the custom implementation of `ChatMessageStore` to a `ChatClientAgent` that is based on Azure OpenAI Chat Completion. +To supply a custom `ChatHistoryProvider` to a `ChatClientAgent`, you can use the `ChatHistoryProviderFactory` option when creating the agent. +Here is an example showing how to pass the custom implementation of `ChatHistoryProvider` to a `ChatClientAgent` that is based on Azure OpenAI Chat Completion. The factory is an async function that receives a context object and a cancellation token. @@ -124,11 +124,11 @@ AIAgent agent = new AzureOpenAIClient( { Name = JokerName, ChatOptions = new() { Instructions = JokerInstructions }, - ChatMessageStoreFactory = (ctx, ct) => new ValueTask( - // Create a new chat message store for this agent that stores the messages in a custom store. - // Each thread must get its own copy of the CustomMessageStore, since the store + ChatHistoryProviderFactory = (ctx, ct) => new ValueTask( + // Create a new chat history provider for this agent that stores the messages in a custom store. + // Each thread must get its own copy of the CustomChatHistoryProvider, since the provider // also contains the ID that the thread is stored under. - new CustomMessageStore( + new CustomChatHistoryProvider( vectorStore, ctx.SerializedState, ctx.JsonSerializerOptions)) @@ -153,7 +153,7 @@ It is important to be able to persist an `AgentThread` object between agent invo Even if the chat history is stored in a remote store, the `AgentThread` object still contains an ID referencing the remote chat history. Losing the `AgentThread` state will therefore result in also losing the ID of the remote chat history. -The `AgentThread` as well as any objects attached to it, all therefore provide the `Serialize` method to serialize their state. The `AIAgent` also provides a `DeserializeThreadAsync` method that re-creates a thread from the serialized state. The `DeserializeThreadAsync` method re-creates the thread with the `ChatMessageStore` and `AIContextProvider` configured on the agent. +The `AgentThread` as well as any objects attached to it, all therefore provide the `Serialize` method to serialize their state. The `AIAgent` also provides a `DeserializeThreadAsync` method that re-creates a thread from the serialized state. The `DeserializeThreadAsync` method re-creates the thread with the `ChatHistoryProvider` and `AIContextProvider` configured on the agent. ```csharp // Serialize the thread state to a JsonElement, so it can be stored for later use. From d3a166c927958a46221ccc865c43bb14fb346427 Mon Sep 17 00:00:00 2001 From: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com> Date: Tue, 27 Jan 2026 10:01:03 -0800 Subject: [PATCH 3/4] Added page for GitHub Copilot SDK (#828) * Added page for GitHub Copilot SDK * Small fix --- .../user-guide/agents/agent-types/TOC.yml | 2 + .../agent-types/github-copilot-agent.md | 396 ++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 agent-framework/user-guide/agents/agent-types/github-copilot-agent.md diff --git a/agent-framework/user-guide/agents/agent-types/TOC.yml b/agent-framework/user-guide/agents/agent-types/TOC.yml index 3a1f6a21..26348797 100644 --- a/agent-framework/user-guide/agents/agent-types/TOC.yml +++ b/agent-framework/user-guide/agents/agent-types/TOC.yml @@ -26,6 +26,8 @@ href: durable-agent/create-durable-agent.md - name: Durable Agent Features href: durable-agent/features.md +- name: GitHub Copilot Agents + href: github-copilot-agent.md - name: A2A Agents href: a2a-agent.md - name: Custom Agents diff --git a/agent-framework/user-guide/agents/agent-types/github-copilot-agent.md b/agent-framework/user-guide/agents/agent-types/github-copilot-agent.md new file mode 100644 index 00000000..c46a07d5 --- /dev/null +++ b/agent-framework/user-guide/agents/agent-types/github-copilot-agent.md @@ -0,0 +1,396 @@ +--- +title: GitHub Copilot Agents +description: Learn how to use Microsoft Agent Framework with the GitHub Copilot SDK. +zone_pivot_groups: programming-languages +author: dmytrostruk +ms.topic: tutorial +ms.author: dmytrostruk +ms.date: 01/26/2026 +ms.service: agent-framework +--- + +# GitHub Copilot Agents + +Microsoft Agent Framework supports creating agents that use the [GitHub Copilot SDK](https://github.com/github/copilot-sdk) as their backend. GitHub Copilot agents provide access to powerful coding-oriented AI capabilities, including shell command execution, file operations, URL fetching, and Model Context Protocol (MCP) server integration. + +> [!IMPORTANT] +> GitHub Copilot agents require the GitHub Copilot CLI to be installed and authenticated. For security, it is recommended to run agents with shell or file permissions in a containerized environment (Docker/Dev Container). + +::: zone pivot="programming-language-csharp" + +## Getting Started + +Add the required NuGet packages to your project. + +```dotnetcli +dotnet add package Microsoft.Agents.AI.GithubCopilot --prerelease +``` + +## Create a GitHub Copilot Agent + +As a first step, create a `CopilotClient` and start it. Then use the `AsAIAgent` extension method to create an agent. + +```csharp +using GitHub.Copilot.SDK; +using Microsoft.Agents.AI; + +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +AIAgent agent = copilotClient.AsAIAgent(); + +Console.WriteLine(await agent.RunAsync("What is Microsoft Agent Framework?")); +``` + +### With Tools and Instructions + +You can provide function tools and custom instructions when creating the agent: + +```csharp +using GitHub.Copilot.SDK; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +AIFunction weatherTool = AIFunctionFactory.Create((string location) => +{ + return $"The weather in {location} is sunny with a high of 25C."; +}, "GetWeather", "Get the weather for a given location."); + +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +AIAgent agent = copilotClient.AsAIAgent( + tools: [weatherTool], + instructions: "You are a helpful weather agent."); + +Console.WriteLine(await agent.RunAsync("What's the weather like in Seattle?")); +``` + +## Agent Features + +### Streaming Responses + +Get responses as they are generated: + +```csharp +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +AIAgent agent = copilotClient.AsAIAgent(); + +await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me a short story.")) +{ + Console.Write(update); +} + +Console.WriteLine(); +``` + +### Session Management + +Maintain conversation context across multiple interactions using sessions: + +```csharp +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +await using GithubCopilotAgent agent = new( + copilotClient, + instructions: "You are a helpful assistant. Keep your answers short."); + +AgentSession session = await agent.GetNewSessionAsync(); + +// First turn +await agent.RunAsync("My name is Alice.", session); + +// Second turn - agent remembers the context +AgentResponse response = await agent.RunAsync("What is my name?", session); +Console.WriteLine(response); // Should mention "Alice" +``` + +### Permissions + +By default, the agent cannot execute shell commands, read/write files, or fetch URLs. To enable these capabilities, provide a permission handler via `SessionConfig`: + +```csharp +static Task PromptPermission( + PermissionRequest request, PermissionInvocation invocation) +{ + Console.WriteLine($"\n[Permission Request: {request.Kind}]"); + Console.Write("Approve? (y/n): "); + + string? input = Console.ReadLine()?.Trim().ToUpperInvariant(); + string kind = input is "Y" or "YES" ? "approved" : "denied-interactively-by-user"; + + return Task.FromResult(new PermissionRequestResult { Kind = kind }); +} + +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +SessionConfig sessionConfig = new() +{ + OnPermissionRequest = PromptPermission, +}; + +AIAgent agent = copilotClient.AsAIAgent(sessionConfig); + +Console.WriteLine(await agent.RunAsync("List all files in the current directory")); +``` + +### MCP Servers + +Connect to local (stdio) or remote (HTTP) MCP servers for extended capabilities: + +```csharp +await using CopilotClient copilotClient = new(); +await copilotClient.StartAsync(); + +SessionConfig sessionConfig = new() +{ + OnPermissionRequest = PromptPermission, + McpServers = new Dictionary + { + // Local stdio server + ["filesystem"] = new McpLocalServerConfig + { + Type = "stdio", + Command = "npx", + Args = ["-y", "@modelcontextprotocol/server-filesystem", "."], + Tools = ["*"], + }, + // Remote HTTP server + ["microsoft-learn"] = new McpRemoteServerConfig + { + Type = "http", + Url = "https://learn.microsoft.com/api/mcp", + Tools = ["*"], + }, + }, +}; + +AIAgent agent = copilotClient.AsAIAgent(sessionConfig); + +Console.WriteLine(await agent.RunAsync("Search Microsoft Learn for 'Azure Functions' and summarize the top result")); +``` + +## Using the Agent + +The agent is a standard `AIAgent` and supports all standard `AIAgent` operations. + +For more information on how to run and interact with agents, see the [Agent getting started tutorials](../../../tutorials/overview.md). + +::: zone-end +::: zone pivot="programming-language-python" + +## Prerequisites + +Install the Microsoft Agent Framework GitHub Copilot package. + +```bash +pip install agent-framework-github-copilot --pre +``` + +## Configuration + +The agent can be optionally configured using the following environment variables: + +| Variable | Description | +|----------|-------------| +| `GITHUB_COPILOT_CLI_PATH` | Path to the Copilot CLI executable | +| `GITHUB_COPILOT_MODEL` | Model to use (e.g., `gpt-5`, `claude-sonnet-4`) | +| `GITHUB_COPILOT_TIMEOUT` | Request timeout in seconds | +| `GITHUB_COPILOT_LOG_LEVEL` | CLI log level | + +## Getting Started + +Import the required classes from Agent Framework: + +```python +import asyncio +from agent_framework.github import GithubCopilotAgent, GithubCopilotOptions +``` + +## Create a GitHub Copilot Agent + +### Basic Agent Creation + +The simplest way to create a GitHub Copilot agent: + +```python +async def basic_example(): + agent = GithubCopilotAgent( + default_options={"instructions": "You are a helpful assistant."}, + ) + + async with agent: + result = await agent.run("What is Microsoft Agent Framework?") + print(result) +``` + +### With Explicit Configuration + +You can provide explicit configuration through `default_options`: + +```python +async def explicit_config_example(): + agent = GithubCopilotAgent( + default_options={ + "instructions": "You are a helpful assistant.", + "model": "gpt-5", + "timeout": 120, + }, + ) + + async with agent: + result = await agent.run("What can you do?") + print(result) +``` + +## Agent Features + +### Function Tools + +Equip your agent with custom functions: + +```python +from typing import Annotated +from pydantic import Field + +def get_weather( + location: Annotated[str, Field(description="The location to get the weather for.")], +) -> str: + """Get the weather for a given location.""" + return f"The weather in {location} is sunny with a high of 25C." + +async def tools_example(): + agent = GithubCopilotAgent( + default_options={"instructions": "You are a helpful weather agent."}, + tools=[get_weather], + ) + + async with agent: + result = await agent.run("What's the weather like in Seattle?") + print(result) +``` + +### Streaming Responses + +Get responses as they are generated for better user experience: + +```python +async def streaming_example(): + agent = GithubCopilotAgent( + default_options={"instructions": "You are a helpful assistant."}, + ) + + async with agent: + print("Agent: ", end="", flush=True) + async for chunk in agent.run_stream("Tell me a short story."): + if chunk.text: + print(chunk.text, end="", flush=True) + print() +``` + +### Thread Management + +Maintain conversation context across multiple interactions: + +```python +async def thread_example(): + agent = GithubCopilotAgent( + default_options={"instructions": "You are a helpful assistant."}, + ) + + async with agent: + thread = agent.get_new_thread() + + # First interaction + result1 = await agent.run("My name is Alice.", thread=thread) + print(f"Agent: {result1}") + + # Second interaction - agent remembers the context + result2 = await agent.run("What's my name?", thread=thread) + print(f"Agent: {result2}") # Should remember "Alice" +``` + +### Permissions + +By default, the agent cannot execute shell commands, read/write files, or fetch URLs. To enable these capabilities, provide a permission handler: + +```python +from copilot.types import PermissionRequest, PermissionRequestResult + +def prompt_permission( + request: PermissionRequest, context: dict[str, str] +) -> PermissionRequestResult: + kind = request.get("kind", "unknown") + print(f"\n[Permission Request: {kind}]") + + response = input("Approve? (y/n): ").strip().lower() + if response in ("y", "yes"): + return PermissionRequestResult(kind="approved") + return PermissionRequestResult(kind="denied-interactively-by-user") + +async def permissions_example(): + agent = GithubCopilotAgent( + default_options={ + "instructions": "You are a helpful assistant that can execute shell commands.", + "on_permission_request": prompt_permission, + }, + ) + + async with agent: + result = await agent.run("List the Python files in the current directory") + print(result) +``` + +### MCP Servers + +Connect to local (stdio) or remote (HTTP) MCP servers for extended capabilities: + +```python +from copilot.types import MCPServerConfig + +async def mcp_example(): + mcp_servers: dict[str, MCPServerConfig] = { + # Local stdio server + "filesystem": { + "type": "stdio", + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-filesystem", "."], + "tools": ["*"], + }, + # Remote HTTP server + "microsoft-learn": { + "type": "http", + "url": "https://learn.microsoft.com/api/mcp", + "tools": ["*"], + }, + } + + agent = GithubCopilotAgent( + default_options={ + "instructions": "You are a helpful assistant with access to the filesystem and Microsoft Learn.", + "on_permission_request": prompt_permission, + "mcp_servers": mcp_servers, + }, + ) + + async with agent: + result = await agent.run("Search Microsoft Learn for 'Azure Functions' and summarize the top result") + print(result) +``` + +## Using the Agent + +The agent is a standard `BaseAgent` and supports all standard agent operations. + +For more information on how to run and interact with agents, see the [Agent getting started tutorials](../../../tutorials/overview.md). + +::: zone-end + +## Next steps + +> [!div class="nextstepaction"] +> [Custom Agents](./custom-agent.md) From 4b89a4759f4d3a201248fa3630575c6b440cfe02 Mon Sep 17 00:00:00 2001 From: Eduard van Valkenburg Date: Tue, 27 Jan 2026 20:02:24 +0100 Subject: [PATCH 4/4] updated filtering section (#827) --- .../inmemory-connector.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/inmemory-connector.md b/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/inmemory-connector.md index 51086da7..db9be4df 100644 --- a/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/inmemory-connector.md +++ b/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/inmemory-connector.md @@ -104,6 +104,12 @@ var collection = new InMemoryCollection("skhotels"); ## Overview +> [!WARNING] +> The In-Memory Vector Store has support for custom filters that can be expressed as Python lambda functions, these functions are +> executed in the same process as the main application, and therefore can execute arbitrary code. +> We filter for certain allowed operations, but you should not let filters be set by untrusted sources, including by LLM inputs. +> See the [Filtering](#filtering) section for more details. + The In-Memory Vector Store connector is a Vector Store implementation provided by Semantic Kernel that uses no external database and stores data in memory. This Vector Store is useful for prototyping scenarios or where high-speed in-memory operations are required. @@ -149,6 +155,53 @@ from semantic_kernel.connectors.in_memory import InMemoryCollection vector_collection = InMemoryCollection(record_type=DataModel, collection_name="collection_name") ``` +### Filtering + +> [!WARNING] +> The In-Memory Vector Store has support for custom filters that can be expressed as Python lambda functions, these functions are +> executed in the same process as the main application, and therefore can execute arbitrary code. +> We filter for certain allowed operations, but you should not let filters be set by untrusted sources, including by LLM inputs. + +The In-Memory connector uses an allowlist approach for filter security. Only the following operations are permitted in filter expressions: + +#### Allowed operations + +| Category | Allowed Operations | +|----------|-------------------| +| **Comparisons** | `==`, `!=`, `<`, `<=`, `>`, `>=`, `in`, `not in`, `is`, `is not` | +| **Boolean operations** | `and`, `or`, `not` | +| **Data access** | Attribute access (e.g., `x.field`), subscript access (e.g., `x['field']`), slicing | +| **Literals** | Constants, lists, tuples, sets, dictionaries | +| **Basic arithmetic** | `+`, `-`, `*`, `/`, `%`, `//` | + +#### Allowed functions + +The following built-in functions and methods can be used in filter expressions: + +- **Type conversion**: `str`, `int`, `float`, `bool` +- **Aggregation**: `len`, `abs`, `min`, `max`, `sum`, `any`, `all` +- **String methods**: `lower`, `upper`, `strip`, `startswith`, `endswith`, `contains` +- **Dictionary methods**: `get`, `keys`, `values`, `items` + +#### Examples + +```python +# Simple equality filter +results = await collection.search(vector, filter="lambda x: x.category == 'electronics'") + +# Numeric comparison +results = await collection.search(vector, filter="lambda x: x.price < 100") + +# Boolean combination +results = await collection.search(vector, filter="lambda x: x.in_stock and x.rating >= 4.0") + +# String method +results = await collection.search(vector, filter="lambda x: x.name.startswith('A')") + +# Membership test +results = await collection.search(vector, filter="lambda x: x.status in ['active', 'pending']") +``` + ::: zone-end ::: zone pivot="programming-language-java"