Repository: microsoft/semantic-kernel
File: dotnet/samples/Concepts/Agents/ChatCompletion_Whiteboard.cs (C#)

Code before:
        kernel.Plugins.AddFromType<VMPlugin>();
        ChatCompletionAgent agent =
            new()
            {
                Name = AgentName,
                Instructions = AgentInstructions,
                Kernel = kernel,
                Arguments = new KernelArguments(new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() })
            };

        // Create a chat history reducer that we can use to truncate the chat history
        // when it goes over 3 items.
        var chatHistoryReducer = new ChatHistoryTruncationReducer(3, 3);

        // Create a thread for the agent and add the whiteboard to it.
        ChatHistoryAgentThread agentThread = new();
        agentThread.AIContextBehaviors.Add(whiteboardBehavior);

        // Simulate a conversation with the agent.
        // We will also truncate the conversation once it goes over a few items.
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Hello");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I'd like to create a VM?");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it to have 3 cores.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it to have 48GB of RAM.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it to have a 500GB Harddrive.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it in in Europe.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Can you make it Linux and call it 'ContosoVM'.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "OK, let's call it `ContosoFinanceVM_Europe` instead.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Thanks, now I want to create another VM.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Make all the options the same as the last one, except for the region, which should be North America, and the name, which should be 'ContosoFinanceVM_NorthAmerica'.");
    }

    private async Task InvokeWithConsoleWriteLine(ChatCompletionAgent agent, ChatHistoryAgentThread agentThread, WhiteboardBehavior whiteboardBehavior, IChatHistoryReducer chatHistoryReducer, string message)
    {
        // Print the user input.
        Console.WriteLine($"User: {message}");

        // Invoke the agent.
        ChatMessageContent response = await agent.InvokeAsync(message, agentThread).FirstAsync();

        // Print the response.
        Console.WriteLine($"Assistant:\n{response.Content}\n");

        // Make sure any async whiteboard processing is complete before we print out its contents.
        await whiteboardBehavior.WhenProcessingCompleteAsync();

        // Print out the whiteboard contents.
        Console.WriteLine("Whiteboard contents:");
        foreach (var item in whiteboardBehavior.CurrentWhiteboardContent)
        {
            Console.WriteLine($"- {item}");

Review comment (suggestion):
```suggestion
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it in Europe.");
```

Code after:
        kernel.Plugins.AddFromType<VMPlugin>();
        ChatCompletionAgent agent =
            new()
            {
                Name = AgentName,
                Instructions = AgentInstructions,
                Kernel = kernel,
                Arguments = new KernelArguments(new PromptExecutionSettings { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() })
            };

        // Create a chat history reducer that we can use to truncate the chat history
        // when it goes over 3 items.
        var chatHistoryReducer = new ChatHistoryTruncationReducer(3, 3);

        // Create a thread for the agent and add the whiteboard to it.
        ChatHistoryAgentThread agentThread = new();
        agentThread.AIContextBehaviors.Add(whiteboardBehavior);

        // Simulate a conversation with the agent.
        // We will also truncate the conversation once it goes over a few items.
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Hello");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I'd like to create a VM?");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it to have 3 cores.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it to have 48GB of RAM.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it to have a 500GB Harddrive.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "I want it in Europe.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Can you make it Linux and call it 'ContosoVM'.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "OK, let's call it `ContosoFinanceVM_Europe` instead.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Thanks, now I want to create another VM.");
        await this.InvokeWithConsoleWriteLine(agent, agentThread, whiteboardBehavior, chatHistoryReducer, "Make all the options the same as the last one, except for the region, which should be North America, and the name, which should be 'ContosoFinanceVM_NorthAmerica'.");
    }

    private async Task InvokeWithConsoleWriteLine(ChatCompletionAgent agent, ChatHistoryAgentThread agentThread, WhiteboardBehavior whiteboardBehavior, IChatHistoryReducer chatHistoryReducer, string message)
    {
        // Print the user input.
        Console.WriteLine($"User: {message}");

        // Invoke the agent.
        ChatMessageContent response = await agent.InvokeAsync(message, agentThread).FirstAsync();

        // Print the response.
        Console.WriteLine($"Assistant:\n{response.Content}\n");

        // Make sure any async whiteboard processing is complete before we print out its contents.
        await whiteboardBehavior.WhenProcessingCompleteAsync();

        // Print out the whiteboard contents.
        Console.WriteLine("Whiteboard contents:");
        foreach (var item in whiteboardBehavior.CurrentWhiteboardContent)
        {
            Console.WriteLine($"- {item}");