From f3b25b049761b1c473f74c441234a66c76bd2799 Mon Sep 17 00:00:00 2001 From: Jack Gerrits Date: Thu, 30 Jan 2025 18:25:37 -0500 Subject: [PATCH 1/5] Create documentation site for 0.4 dotnet --- .github/workflows/docs.yml | 22 ++- docs/dotnet/.gitignore | 12 ++ docs/dotnet/README.md | 13 ++ docs/dotnet/core/differences-from-python.md | 8 + docs/dotnet/core/index.md | 7 + docs/dotnet/core/installation.md | 22 +++ docs/dotnet/core/protobuf-message-types.md | 58 ++++++ docs/dotnet/core/toc.yml | 10 ++ docs/dotnet/core/tutorial.md | 165 ++++++++++++++++++ docs/dotnet/docfx.json | 78 +++++++++ docs/dotnet/images/favicon.ico | Bin 0 -> 15406 bytes docs/dotnet/images/logo.svg | 4 + docs/dotnet/index.md | 40 +++++ docs/dotnet/template/public/main.css | 4 + docs/dotnet/template/public/main.js | 9 + docs/dotnet/toc.yml | 8 + .../core-user-guide/defining-message-types.md | 30 ---- .../core-user-guide/differences-python.md | 46 ----- .../core-user-guide/getting-started.md | 143 --------------- .../core-user-guide/installation.md | 33 ---- dotnet/samples/GettingStarted/Checker.cs | 4 +- dotnet/samples/GettingStarted/CountMessage.cs | 4 +- dotnet/samples/GettingStarted/CountUpdate.cs | 4 +- dotnet/samples/GettingStarted/Modifier.cs | 5 +- dotnet/samples/GettingStarted/Program.cs | 11 +- dotnet/samples/Hello/HelloAgent/HelloAgent.cs | 2 +- 26 files changed, 481 insertions(+), 261 deletions(-) create mode 100644 docs/dotnet/.gitignore create mode 100644 docs/dotnet/README.md create mode 100644 docs/dotnet/core/differences-from-python.md create mode 100644 docs/dotnet/core/index.md create mode 100644 docs/dotnet/core/installation.md create mode 100644 docs/dotnet/core/protobuf-message-types.md create mode 100644 docs/dotnet/core/toc.yml create mode 100644 docs/dotnet/core/tutorial.md create mode 100644 docs/dotnet/docfx.json create mode 100644 docs/dotnet/images/favicon.ico create mode 100644 docs/dotnet/images/logo.svg create mode 100644 docs/dotnet/index.md create mode 100644 docs/dotnet/template/public/main.css create mode 100644 docs/dotnet/template/public/main.js create mode 100644 docs/dotnet/toc.yml delete mode 100644 docs/dotnet/user-guide/core-user-guide/defining-message-types.md delete mode 100644 docs/dotnet/user-guide/core-user-guide/differences-python.md delete mode 100644 docs/dotnet/user-guide/core-user-guide/getting-started.md delete mode 100644 docs/dotnet/user-guide/core-user-guide/installation.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 31b52899a4f9..248ce495925f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -185,12 +185,32 @@ jobs: path: "website/artifact" name: "02-docs" + build-04-dotnet: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + lfs: true + - name: Setup .NET 8.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + global-json-file: dotnet/global.json + - run: | + mkdir -p ./build/dotnet/dev/ + docfx build docfx.json --output ./build/dotnet/dev/ + working-directory: ./docs/dotnet + - uses: actions/upload-artifact@v4 + with: + path: "./docs/dotnet/build" + name: "dotnet-dev-docs" + deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest - needs: [build-02, build-04, gen-redirects, gen-component-schema] + needs: [build-02, build-04, build-04-dotnet, gen-redirects, gen-component-schema] if: ${{ needs.build-02.result == 'success' && needs.build-04.result == 'success' && needs.gen-redirects.result == 'success' && github.ref == 'refs/heads/main' }} steps: - uses: actions/download-artifact@v4 diff --git a/docs/dotnet/.gitignore b/docs/dotnet/.gitignore new file mode 100644 index 000000000000..8d5bc9f4490d --- /dev/null +++ b/docs/dotnet/.gitignore @@ -0,0 +1,12 @@ +############### +# folder # +############### +/**/DROP/ +/**/TEMP/ +/**/packages/ +/**/bin/ +/**/obj/ + +# build artifacts for web +_site/ +api/ diff --git a/docs/dotnet/README.md b/docs/dotnet/README.md new file mode 100644 index 000000000000..fd587ad2807d --- /dev/null +++ b/docs/dotnet/README.md @@ -0,0 +1,13 @@ +## How to build and run the website + +### Prerequisites +- dotnet 7.0 or later + +### Build +Firstly, go to autogen/dotnet folder and run the following command to build the website: +```bash +dotnet tool restore +dotnet tool run docfx website/docfx.json --serve +``` + +After the command is executed, you can open your browser and navigate to `http://localhost:8080` to view the website. \ No newline at end of file diff --git a/docs/dotnet/core/differences-from-python.md b/docs/dotnet/core/differences-from-python.md new file mode 100644 index 000000000000..3fbe49c3e0ff --- /dev/null +++ b/docs/dotnet/core/differences-from-python.md @@ -0,0 +1,8 @@ +# Differences from Python + +## Publishing to a topic that an agent is also subscribed to + +> [!NOTE] +> TLDR; Default behavior is identical. + +When an agent publishes a message to a topic to which it also listens, the message will not be received by the agent that sent it. This is also the behavior in the Python runtime. However to support previous usage, in @Microsoft.AutoGen.Core.InProcessRuntime, you can set the @Microsoft.AutoGen.Core.InProcessRuntime.DeliverToSelf property to true in the TopicSubscription attribute to allow an agent to receive messages it sends. diff --git a/docs/dotnet/core/index.md b/docs/dotnet/core/index.md new file mode 100644 index 000000000000..cc5b03ea3054 --- /dev/null +++ b/docs/dotnet/core/index.md @@ -0,0 +1,7 @@ +# AutoGen Core + +AutoGen Core for .NET follows the same concepts and conventions of its Python counterpart. In fact, in order to understand the concepts in the .NET version, we recommend reading the Python documentation first. Unless otherwise stated, the concepts in the Python version map to .NET. + +Any important differences between the language versions are documented in the [Differences from Python](./differences-from-python.md) section. For things that only affect a given language, such as dependency injection or host builder patterns, these will not be specified in the differences document. + +For .NET we are starting with the core functionality and will be expanding support progressively. So far the core abstractions of Agent and Runtime are available. The InProcessRuntime is the only runtime available at this time. We will be expanding to cross language support in upcoming releases. diff --git a/docs/dotnet/core/installation.md b/docs/dotnet/core/installation.md new file mode 100644 index 000000000000..a2c980544f08 --- /dev/null +++ b/docs/dotnet/core/installation.md @@ -0,0 +1,22 @@ +# Installation + +Install via `.NET cli` + +```sh +dotnet add package Microsoft.AutoGen.Contracts --version 0.4.0-dev.1 +dotnet add package Microsoft.AutoGen.Core --version 0.4.0-dev.1 +``` + +Or, install via `Package Manager` + +```pwsh +PM> NuGet\Install-Package Microsoft.AutoGen.Contracts -Version 0.4.0-dev.1 +PM> NuGet\Install-Package Microsoft.AutoGen.Core -Version 0.4.0-dev.1 +``` + +Or, add via `` + +```xml + + +``` diff --git a/docs/dotnet/core/protobuf-message-types.md b/docs/dotnet/core/protobuf-message-types.md new file mode 100644 index 000000000000..57e499d731cf --- /dev/null +++ b/docs/dotnet/core/protobuf-message-types.md @@ -0,0 +1,58 @@ +# Using Protocol Buffers to Define Message Types + +For a message to be sent using a runtime other than the @Microsoft.AutoGen.Core.InProcessRuntime, it must be defined as a Protocol Buffers message. This is because the message is serialized and deserialized using Protocol Buffers. This requirement may be relaxed in future by allowing for converters, custom serialization, or other mechanisms. + +## How to include Protocol Buffers in a .NET project + +The .proto file which defines the message types must be included in the project, which will automatically generate the C# classes for the messages. + +1. Include `Grpc.Tools` package in your `.csproj` file: + +```xml + +``` + +2. Create an include a `.proto` file in the project: + +```xml + + + +``` + +3. define your messages as specified in the [Protocol Buffers Language Guide](https://protobuf.dev/programming-guides/proto3/) + +```proto +syntax = "proto3"; + +package HelloAgents; + +option csharp_namespace = "MyAgentsProtocol"; + +message TextMessage { + string Source = 1; + string Content = 2; +} +``` + +4. Code against the generated class for handling, sending and publishing messages: + +```csharp +using Microsoft.AutoGen.Contracts; +using Microsoft.AutoGen.Core; +using MyAgentsProtocol; + +[TypeSubscription("default")] +public class Checker( + AgentId id, + IAgentRuntime runtime, + ) : + BaseAgent(id, runtime, "MyAgent", null), + IHandle +{ + public async ValueTask HandleAsync(TextMessage item, MessageContext messageContext) + { + Console.WriteLine($"Received message from {item.Source}: {item.Content}"); + } +} +``` diff --git a/docs/dotnet/core/toc.yml b/docs/dotnet/core/toc.yml new file mode 100644 index 000000000000..cc0156551bcc --- /dev/null +++ b/docs/dotnet/core/toc.yml @@ -0,0 +1,10 @@ +- name: Overview + href: index.md +- name: Installation + href: installation.md +- name: Tutorial + href: tutorial.md +- name: Differences from Python + href: differences-from-python.md +- name: Protobuf message types + href: protobuf-message-types.md \ No newline at end of file diff --git a/docs/dotnet/core/tutorial.md b/docs/dotnet/core/tutorial.md new file mode 100644 index 000000000000..179bcdcbd786 --- /dev/null +++ b/docs/dotnet/core/tutorial.md @@ -0,0 +1,165 @@ +# Tutorial + +> [!TIP] +> If you'd prefer to just see the code the entire sample is available as a [project here](https://github.com/microsoft/autogen/tree/main/dotnet/samples/GettingStarted). + +In this tutorial we are going to define two agents, `Modifier` and `Checker`, that will count down from 10 to 1. The `Modifier` agent will modify the count and the `Checker` agent will check the count and stop the application when the count reaches 1. + +## Defining the message types + +The first thing we need to do is to define the messages that will be passed between the agents, we're simply going to define them as classes. + +We're going to use `CountMessage` to pass the current count and `CountUpdate` to pass the updated count. + +[!code-csharp[](../../../dotnet/samples/GettingStarted/CountMessage.cs#snippet_CountMessage)] +[!code-csharp[](../../../dotnet/samples/GettingStarted/CountUpdate.cs#snippet_CountUpdate)] + +By separating out the message types into strongly typed classes, we can build a workflow where agents react to certain types and produce certain types. + +## Creating the agents + +### Inherit from `BaseAgent` + +In AutoGen an agent is a class that can receive and send messages. The agent defines its own logic of what to do with the messages it receives. To define an agent, create a class that inherits from @Microsoft.AutoGen.Core.BaseAgent, like so: + +```csharp +using Microsoft.AutoGen.Contracts; +using Microsoft.AutoGen.Core; + +public class Modifier( + AgentId id, + IAgentRuntime runtime, + ) : + BaseAgent(id, runtime, "MyAgent", null), +{ +} +``` + +We will see how to pass arguments to an agent when it is constructed, but for now you just need to know that @Microsoft.AutoGen.Contracts.AgentId and @Microsoft.AutoGen.Core.IAgentRuntime will always be passed to the constructor, and those should be forwarded to the base class constructor. The other two arguments are a description of the agent and an optional logger. + +Learn more about what an Agent ID is [here](https://microsoft.github.io/autogen/stable/user-guide/core-user-guide/core-concepts/agent-identity-and-lifecycle.html#agent-id). + +### Create a handler + +Now, we want `Modifier` to receive `CountMessage` and produce `CountUpdate` after it modifies the count. To do this, we need to implement the `IHandle` interface: + +```csharp +public class Modifier( + // ... + ) : + BaseAgent(...), + IHandle +{ + + public async ValueTask HandleAsync(CountMessage item, MessageContext messageContext) + { + // ... + } +} +``` + +### Add a subscription + +We've defined a function that will be called when a `CountMessage` is delivered to this agent, but there is still one step before the message will actually be delivered to the agent. The agent must subscribe to the topic to the message is published to. We can do this by adding the `TypeSubscription` attribute to the class: + +```csharp +[TypeSubscription("default")] +public class Modifier( + // ... +``` + +Learn more about topics and subscriptions [here](https://microsoft.github.io/autogen/stable/user-guide/core-user-guide/core-concepts/topic-and-subscription.html). + +### Publish a message + +Now that we have a handler for `CountMessage`, and we have the subscription in place we can publish a result out of the handler. + +```csharp +public async ValueTask HandleAsync(CountMessage item, MessageContext messageContext) +{ + int newValue = item.Content - 1; + Console.WriteLine($"\nModifier:\nModified {item.Content} to {newValue}"); + + CountUpdate updateMessage = new CountUpdate { NewCount = newValue }; + await this.PublishMessageAsync(updateMessage, topic: new TopicId("default")); +} +``` + +You'll notice that when we publish the message, we specify the topic to publish to. We're using a topic called `default` in this case, which is the same topic which we subscribed to. We could have used a different topic, but in this case we're keeping it simple. + +### Passing arguments to the agent + +Let's extend our agent to make what we do to the count configurable. We'll do this by passing a function to the agent that will be used to modify the count. + +```csharp +using ModifyF = System.Func; + +// ... + +[TypeSubscription("default")] +public class Modifier( + AgentId id, + IAgentRuntime runtime, + ModifyF modifyFunc // <-- Add this + ) : + BaseAgent(...), + IHandle +{ + + public async ValueTask HandleAsync(CountMessage item, MessageContext messageContext) + { + int newValue = modifyFunc(item.Content); // <-- use it here + + // ... + } +} + +``` + +### Final Modifier implementation + +Here is the final implementation of the Modifier agent: + +[!code-csharp[](../../../dotnet/samples/GettingStarted/Modifier.cs#snippet_Modifier)] + +### Checker + +We'll also define a Checker agent that will check the count and stop the application when the count reaches 1. Additionally, we'll use dependency injection to get a reference to the `IHostApplicationLifetime` service, which we can use to stop the application. + +[!code-csharp[](../../../dotnet/samples/GettingStarted/Checker.cs#snippet_Checker)] + +## Putting it all together + +Now that we have our agents defined, we can put them together in a simple application that will count down from 10 to 1. + +After includes, the first thing to do is to define the two functions for modifying and checking for completion. + +[!code-csharp[](../../../dotnet/samples/GettingStarted/Program.cs#snippet_Program_funcs)] + +Then, we create a builder and do the following things: + +- Specify that we are using the in process runtime +- Register our functions as services +- Register the agent classes we defined earlier +- Finally, build and start our app + +[!code-csharp[](../../../dotnet/samples/GettingStarted/Program.cs#snippet_Program_builder)] + +The app is now running, but we need to kick off the process with a message. We do this by publishing a `CountMessage` with an initial value of 10. +Importantly we publish this to the "default" topic which is what our agents are subscribed to. Finally, we wait for the application to stop. + +[!code-csharp[](../../../dotnet/samples/GettingStarted/Program.cs#snippet_Program_publish)] + +That's it! You should see the count down from 10 to 1 in the console. + +Here's the full code for the `Program` class: + +[!code-csharp[](../../../dotnet/samples/GettingStarted/Program.cs#snippet_Program)] + +## Things to try + +Here are some ideas to try with this sample: + +- Change the initial count +- Create a new modifier function that counts up instead. (Don't forget to change the checker too!) +- Create an agent that outputs to the console instead of the modifier or checker agent doing it themselves (hint: use a new message type) diff --git a/docs/dotnet/docfx.json b/docs/dotnet/docfx.json new file mode 100644 index 000000000000..f04b979c30e8 --- /dev/null +++ b/docs/dotnet/docfx.json @@ -0,0 +1,78 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "Contracts/Microsoft.AutoGen.Contracts.csproj", + "Core/Microsoft.AutoGen.Core.csproj" + ], + "src": "../../dotnet/src/Microsoft.Autogen/" + } + ], + "dest": "api", + "includePrivateMembers": false, + "disableGitFeatures": false, + "disableDefaultFilter": false, + "noRestore": false, + "namespaceLayout": "flattened", + "memberLayout": "samePage", + "allowCompilationErrors": false + } + ], + "build": { + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md" + ] + }, + { + "files": [ + "core/**.md", + "core/**/toc.yml", + "articles/**.md", + "articles/**/toc.yml", + "tutorial/**.md", + "tutorial/**/toc.yml", + "release_note/**.md", + "release_note/**/toc.yml", + "toc.yml", + "*.md" + ] + } + ], + "resource": [ + { + "files": [ + "images/**" + ] + } + ], + "output": "_site", + "globalMetadataFiles": [], + "fileMetadataFiles": [], + "template": [ + "default", + "modern", + "template" + ], + "globalMetadata": { + "_appTitle": "AutoGen .NET", + "_appName": "AutoGen .NET", + "_appLogoPath": "images/logo.svg", + "_appFooter": "AutoGen", + "_appFaviconPath": "images/favicon.ico", + "_gitContribute": { + "repo": "https://github.com/microsoft/autogen.git" + } + }, + "postProcessors": [ + "ExtractSearchIndex" + ], + "_enableSearch": true, + "keepFileLink": false, + "disableGitFeatures": false + } +} \ No newline at end of file diff --git a/docs/dotnet/images/favicon.ico b/docs/dotnet/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..16f7a78a7be71c0edeeceead56cbff74e37ce2b5 GIT binary patch literal 15406 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 + + + diff --git a/docs/dotnet/index.md b/docs/dotnet/index.md new file mode 100644 index 000000000000..e5c206c9a766 --- /dev/null +++ b/docs/dotnet/index.md @@ -0,0 +1,40 @@ +--- +_disableAffix: true +--- + + +
+

AutoGen .NET

+

+ A .NET framework for building AI agents and applications +

+
+ +
+
+
+
+
Core
+

An event-driven programming framework for building scalable multi-agent AI systems.

+ Get started +
+
+
+
+
+
+
AgentChat
+

A programming framework for building conversational single and multi-agent applications. Built on Core.

+ Coming soon +
+
+
+
diff --git a/docs/dotnet/template/public/main.css b/docs/dotnet/template/public/main.css new file mode 100644 index 000000000000..6f4abd6639ec --- /dev/null +++ b/docs/dotnet/template/public/main.css @@ -0,0 +1,4 @@ +.navbar-brand img { + height: 50px; + margin-right: 0.5rem; +} diff --git a/docs/dotnet/template/public/main.js b/docs/dotnet/template/public/main.js new file mode 100644 index 000000000000..df5fb0b83436 --- /dev/null +++ b/docs/dotnet/template/public/main.js @@ -0,0 +1,9 @@ +export default { + iconLinks: [ + { + icon: 'github', + href: 'https://github.com/microsoft/autogen', + title: 'GitHub' + } + ] + } \ No newline at end of file diff --git a/docs/dotnet/toc.yml b/docs/dotnet/toc.yml new file mode 100644 index 000000000000..6b6aa80b7836 --- /dev/null +++ b/docs/dotnet/toc.yml @@ -0,0 +1,8 @@ +- name: Core + href: core/ + +- name: API Reference + href: api/ + +- name: Python + href: https://microsoft.github.io/autogen/ diff --git a/docs/dotnet/user-guide/core-user-guide/defining-message-types.md b/docs/dotnet/user-guide/core-user-guide/defining-message-types.md deleted file mode 100644 index 9d7a130574b3..000000000000 --- a/docs/dotnet/user-guide/core-user-guide/defining-message-types.md +++ /dev/null @@ -1,30 +0,0 @@ -# Defining Message Types - -Messages are currently required to be Protocol Buffers. To define them, it is necessary to include the Protocol Buffers compiler, through the `Grpc.Tools` package. In your `.csproj` file, add/edit: - -```xml - -``` - -Then create an include a `.proto` file in the project: - -```xml - - - -``` - -Then define your messages as specified in the [Protocol Buffers Language Guide](https://protobuf.dev/programming-guides/proto3/) - -```proto -syntax = "proto3"; - -package HelloAgents; - -option csharp_namespace = "AgentsProtocol"; - -message TextMessage { - string Source = 1; - string Content = 2; -} -``` \ No newline at end of file diff --git a/docs/dotnet/user-guide/core-user-guide/differences-python.md b/docs/dotnet/user-guide/core-user-guide/differences-python.md deleted file mode 100644 index d5e43b9e32e9..000000000000 --- a/docs/dotnet/user-guide/core-user-guide/differences-python.md +++ /dev/null @@ -1,46 +0,0 @@ -# Differences from Python - -## Agents Self-Interact - -When an agent sends a message of a type to which it also listens: - -```csharp -[TopicSubscription("default")] -public class MyAgent( - IAgentWorker worker, - [FromKeyedServices("EventTypes")] EventTypes typeRegistry - ) : - Agent(worker, typeRegistry), - IHandle -{ - async Task SomeInternalFunctionAsync() - { - Message m; - - // ... - - await this.PublishMessageAsync(m); - } - - public async Task Handle(Message message) - { - // will receive messages sent by SomeInternalFunctionAsync() - } -} -``` - -Tracked by [#4998](https://github.com/microsoft/autogen/issues/4998) - -## 'Local' Runtime is Multithreaded - -Unlike the `single_threaded_runtime`, the InProcess (`local: true`) runtime for .NET is multi-threaded, so messages will process in arbitrary order across agents. This means that an agent may process messages sent after the termination request has been made unless checking for termination using the `IHostApplicationLifecycle` service. - -## No equivalent to 'stop_when_idle()' - -Agents need to request termination explicitly, as there is no meaningful 'idle' state. - -## All message types need to be Protocol Buffers - -See (linkto: defining-message-types.md) for instructions on defining messages - -Tracked by [#4695](https://github.com/microsoft/autogen/issues/4695) \ No newline at end of file diff --git a/docs/dotnet/user-guide/core-user-guide/getting-started.md b/docs/dotnet/user-guide/core-user-guide/getting-started.md deleted file mode 100644 index 9e91b14d1cb3..000000000000 --- a/docs/dotnet/user-guide/core-user-guide/getting-started.md +++ /dev/null @@ -1,143 +0,0 @@ -# Quick Start - -Before diving into the core APIs, let’s start with a simple example of two agents that count down from 10 to 1. - -We first define the agent classes and their respective procedures for handling messages. We create two agent classes: `Modifier` and `Checker`. The `Modifier` agent modifies a number that is given and the `Check` agent checks the value against a condition. We also define a pair of -messages in a .proto file which will be generated into the message types that will be passed -between the agents. - -```proto -syntax = "proto3"; - -package HelloAgents; - -option csharp_namespace = "Microsoft.Autogen.Samples.CountAgent.Protocol"; - -message CountMessage { - int32 Content = 1; -} - -message CountUpdate { - int32 NewCount = 1; -} -``` - -We create two messages to ensure we have tick-tock behaviour between the agents; if we used a single type, then both agents would receive the other agents' message as well as self-sent messages. (Note: this is a behaviour difference from Python; Issue#4998) - -In the project file, we add - -```xml - - - - - - - -``` - -This will ensure the message classes are available for our agents to send/receive. - -Now we will define the agents: - -```csharp -[TopicSubscription("default")] -public class Modifier( - IAgentWorker worker, - [FromKeyedServices("EventTypes")] EventTypes typeRegistry, - ModifyF modifyFunc - ) : - Agent(worker, typeRegistry), - IHandle -{ - public async Task Handle(CountMessage item) - { - // handling code - } -} -``` - -The `TopicSubscription` attribute defines the set of topics the agents will listen to. Topics (see here) are useful for separaating different logical chains of agent communications. - -The first two parameters to the constructor, `IAgentWorker` and `EventTypes` are automatically made available through dependency injection to the workers. (We do not allow direct construction of workers in Autogen.Core: see here for FAQ), and need to be passed on to the base class. - -Other parameters are also made available through dependency injection (see here). - -Agents register for messages by implementing the `IHandle` interface: - -```csharp - public async Task Handle(CountMessage item) - { - int newValue = modifyFunc(item.Content); - Console.WriteLine($"{SEPARATOR_LINE}\nModifier:\nModified {item.Content} to {newValue}"); - - CountUpdate updateMessage = new CountUpdate { NewCount = newValue }; - - await this.PublishMessageAsync(updateMessage); - } -``` - -The `Modifier` agent receives a `CountMessage` indicating the current count, modifies it using the injected `ModifyF modifyFunc`, and publishes the `CountUpdate` message. - -The `Checker` agent is defines similarly: - -```csharp -[TopicSubscription("default")] -public class Checker( - IAgentWorker worker, - [FromKeyedServices("EventTypes")] EventTypes typeRegistry, - IHostApplicationLifetime hostApplicationLifetime, - TerminationF runUntilFunc - ) : - Agent(worker, typeRegistry), - IHandle -{ - public Task Handle(CountUpdate item) - { - if (!runUntilFunc(item.NewCount)) - { - Console.WriteLine($"{SEPARATOR_LINE}\nChecker:\n{item.NewCount} passed the check, continue."); - await this.PublishMessageAsync(new CountMessage { Content = item.NewCount }); - } - else - { - Console.WriteLine($"{SEPARATOR_LINE}\nChecker:\n{item.NewCount} failed the check, stopping."); - hostApplicationLifetime.StopApplication(); - } - } -} -``` - -The `Checker` continues the count when `runUntilFunc` has not triggered by publishing a new `CountMessage` with the updated count; if termination is desired, it will request it by calling `hostApplicationLifetime.StopApplication()`. - -You might have already noticed, the agents’ logic, whether it is using model or code executor, is completely decoupled from how messages are delivered. This is the core idea: the framework provides a communication infrastructure, and the agents are responsible for their own logic. We call the communication infrastructure an Agent Runtime. - -Agent runtime is a key concept of this framework. Besides delivering messages, it also manages agents’ lifecycle. So the creation of agents are handled by the runtime. - -The following code shows how to register and run the agents using the local (InProcess) runtime: - -```csharp -// Define the counting logic -using ModifyF = System.Func; -using TerminationF = System.Func; - -ModifyF modifyFunc = (int x) => x - 1; -TerminationF runUntilFunc = (int x) => -{ - return x <= 1; -}; - -// Register the services -WebApplicationBuilder? builder = WebApplication.CreateBuilder(args); -builder.Services.AddSingleton(modifyFunc); -builder.Services.AddSingleton(runUntilFunc); - -// Send the initial count to the agents app, running on the `local` runtime, and pass through the registered services via the application `builder` -var app = await AgentsApp.PublishMessageAsync("default", new CountMessage -{ - Content = 10 -}, local: true, builder: builder).ConfigureAwait(false); - -// Run until application shutdown -await app.WaitForShutdownAsync(); -``` \ No newline at end of file diff --git a/docs/dotnet/user-guide/core-user-guide/installation.md b/docs/dotnet/user-guide/core-user-guide/installation.md deleted file mode 100644 index 270bcd659db6..000000000000 --- a/docs/dotnet/user-guide/core-user-guide/installation.md +++ /dev/null @@ -1,33 +0,0 @@ -# Installation - -## Add via `` - -``` - - -``` - - - -## These will only work after we release the package: - -## Install via `.NET cli` - -``` -> dotnet add package Microsoft.AutoGen.Contracts --version 0.4.0 -> dotnet add package Microsoft.AutoGen.Core --version 0.4.0 -``` - -## Install via `Package Manager` - -``` -PM> NuGet\Install-Package Microsoft.AutoGen.Contracts -Version 0.4.0 -PM> NuGet\Install-Package Microsoft.AutoGen.Core -Version 0.4.0 -``` - -## Add via `` - -``` - - -``` diff --git a/dotnet/samples/GettingStarted/Checker.cs b/dotnet/samples/GettingStarted/Checker.cs index 1c6f82299cd2..db3d36328bc5 100644 --- a/dotnet/samples/GettingStarted/Checker.cs +++ b/dotnet/samples/GettingStarted/Checker.cs @@ -1,12 +1,13 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Checker.cs +#region snippet_Checker using Microsoft.AutoGen.Contracts; using Microsoft.AutoGen.Core; using Microsoft.Extensions.Hosting; using TerminationF = System.Func; -namespace Samples; +namespace GettingStartedSample; [TypeSubscription("default")] public class Checker( @@ -32,3 +33,4 @@ public async ValueTask HandleAsync(CountUpdate item, MessageContext messageConte } } } +#endregion snippet_Checker diff --git a/dotnet/samples/GettingStarted/CountMessage.cs b/dotnet/samples/GettingStarted/CountMessage.cs index da006b90b3a9..f30675f8f740 100644 --- a/dotnet/samples/GettingStarted/CountMessage.cs +++ b/dotnet/samples/GettingStarted/CountMessage.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // CountMessage.cs -namespace Samples; +#region snippet_CountMessage +namespace GettingStartedSample; public class CountMessage { public int Content { get; set; } } +#endregion diff --git a/dotnet/samples/GettingStarted/CountUpdate.cs b/dotnet/samples/GettingStarted/CountUpdate.cs index 376c2581d96b..15c61c53dd33 100644 --- a/dotnet/samples/GettingStarted/CountUpdate.cs +++ b/dotnet/samples/GettingStarted/CountUpdate.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // CountUpdate.cs -namespace Samples; +#region snippet_CountUpdate +namespace GettingStartedSample; public class CountUpdate { public int NewCount { get; set; } } +#endregion diff --git a/dotnet/samples/GettingStarted/Modifier.cs b/dotnet/samples/GettingStarted/Modifier.cs index d7e622795a0c..f41fdbe52f60 100644 --- a/dotnet/samples/GettingStarted/Modifier.cs +++ b/dotnet/samples/GettingStarted/Modifier.cs @@ -1,12 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Modifier.cs - +#region snippet_Modifier using Microsoft.AutoGen.Contracts; using Microsoft.AutoGen.Core; using ModifyF = System.Func; -namespace Samples; +namespace GettingStartedSample; [TypeSubscription("default")] public class Modifier( @@ -27,3 +27,4 @@ public async ValueTask HandleAsync(CountMessage item, MessageContext messageCont await this.PublishMessageAsync(updateMessage, topic: new TopicId("default")); } } +#endregion snippet_Modifier \ No newline at end of file diff --git a/dotnet/samples/GettingStarted/Program.cs b/dotnet/samples/GettingStarted/Program.cs index c9795aba41c5..acab55d265bb 100644 --- a/dotnet/samples/GettingStarted/Program.cs +++ b/dotnet/samples/GettingStarted/Program.cs @@ -1,10 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Program.cs - +#region snippet_Program +#region snippet_Program_funcs +using GettingStartedSample; using Microsoft.AutoGen.Contracts; using Microsoft.AutoGen.Core; using Microsoft.Extensions.DependencyInjection.Extensions; -using Samples; using ModifyF = System.Func; using TerminationF = System.Func; @@ -13,7 +14,9 @@ { return x <= 1; }; +#endregion snippet_Program_funcs +#region snippet_Program_builder AgentsAppBuilder appBuilder = new AgentsAppBuilder(); appBuilder.UseInProcessRuntime(); @@ -25,7 +28,9 @@ var app = await appBuilder.BuildAsync(); await app.StartAsync(); +#endregion snippet_Program_builder +#region snippet_Program_publish // Send the initial count to the agents app, running on the `local` runtime, and pass through the registered services via the application `builder` await app.PublishMessageAsync(new CountMessage { @@ -34,3 +39,5 @@ await app.PublishMessageAsync(new CountMessage // Run until application shutdown await app.WaitForShutdownAsync(); +#endregion snippet_Program_publish +#endregion snippet_Program \ No newline at end of file diff --git a/dotnet/samples/Hello/HelloAgent/HelloAgent.cs b/dotnet/samples/Hello/HelloAgent/HelloAgent.cs index f188de2d0e93..b69591217bb5 100644 --- a/dotnet/samples/Hello/HelloAgent/HelloAgent.cs +++ b/dotnet/samples/Hello/HelloAgent/HelloAgent.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace Samples; +namespace GettingStartedSample; [TypeSubscription("HelloTopic")] public class HelloAgent( From 1635dbb7507bbd84bc9cc6dba91955b60b060be1 Mon Sep 17 00:00:00 2001 From: Jack Gerrits Date: Thu, 30 Jan 2025 18:30:27 -0500 Subject: [PATCH 2/5] external link icon --- docs/dotnet/toc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/dotnet/toc.yml b/docs/dotnet/toc.yml index 6b6aa80b7836..39272fbaeb1e 100644 --- a/docs/dotnet/toc.yml +++ b/docs/dotnet/toc.yml @@ -4,5 +4,5 @@ - name: API Reference href: api/ -- name: Python +- name: Python⤴ href: https://microsoft.github.io/autogen/ From 6749382151b628e1b9a5f8222449db7917ed07a5 Mon Sep 17 00:00:00 2001 From: Jack Gerrits Date: Thu, 30 Jan 2025 18:51:06 -0500 Subject: [PATCH 3/5] undo change --- dotnet/samples/Hello/HelloAgent/HelloAgent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/samples/Hello/HelloAgent/HelloAgent.cs b/dotnet/samples/Hello/HelloAgent/HelloAgent.cs index b69591217bb5..f188de2d0e93 100644 --- a/dotnet/samples/Hello/HelloAgent/HelloAgent.cs +++ b/dotnet/samples/Hello/HelloAgent/HelloAgent.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -namespace GettingStartedSample; +namespace Samples; [TypeSubscription("HelloTopic")] public class HelloAgent( From 58a328563383bc9a7f5aaae4e7691e95539611a7 Mon Sep 17 00:00:00 2001 From: Jack Gerrits Date: Thu, 30 Jan 2025 18:51:11 -0500 Subject: [PATCH 4/5] add clarity --- .github/workflows/docs.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 248ce495925f..a2aa8a771bbe 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -196,10 +196,42 @@ jobs: with: dotnet-version: '8.0.x' global-json-file: dotnet/global.json + - run: dotnet tool update -g docfx - run: | mkdir -p ./build/dotnet/dev/ docfx build docfx.json --output ./build/dotnet/dev/ working-directory: ./docs/dotnet + - name: insert clarity snippet to *.html + working-directory: ./docs/dotnet/build/dotnet/dev/ + shell: python + run: | + import os + clarity_script = """ + + """ + + site_folder = '.' + + for root, dirs, files in os.walk(site_folder): + for file in files: + if file.endswith('.html'): + html_path = os.path.join(root, file) + + # insert the script into the html's head section + with open(html_path, 'r') as file: + html = file.read() + html = html.replace('', clarity_script + '') + + with open(html_path, 'w') as file: + file.write(html) + + print(f'Clarity script inserted into {html_path}') - uses: actions/upload-artifact@v4 with: path: "./docs/dotnet/build" From f4485fbb3d95cd6aa743f8c6f9ee008db2f35014 Mon Sep 17 00:00:00 2001 From: Jack Gerrits Date: Thu, 30 Jan 2025 18:56:32 -0500 Subject: [PATCH 5/5] formatting --- dotnet/samples/GettingStarted/Modifier.cs | 2 +- dotnet/samples/GettingStarted/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/samples/GettingStarted/Modifier.cs b/dotnet/samples/GettingStarted/Modifier.cs index f41fdbe52f60..374565783313 100644 --- a/dotnet/samples/GettingStarted/Modifier.cs +++ b/dotnet/samples/GettingStarted/Modifier.cs @@ -27,4 +27,4 @@ public async ValueTask HandleAsync(CountMessage item, MessageContext messageCont await this.PublishMessageAsync(updateMessage, topic: new TopicId("default")); } } -#endregion snippet_Modifier \ No newline at end of file +#endregion snippet_Modifier diff --git a/dotnet/samples/GettingStarted/Program.cs b/dotnet/samples/GettingStarted/Program.cs index acab55d265bb..bd9f11fa3368 100644 --- a/dotnet/samples/GettingStarted/Program.cs +++ b/dotnet/samples/GettingStarted/Program.cs @@ -40,4 +40,4 @@ await app.PublishMessageAsync(new CountMessage // Run until application shutdown await app.WaitForShutdownAsync(); #endregion snippet_Program_publish -#endregion snippet_Program \ No newline at end of file +#endregion snippet_Program