@@ -645,6 +645,124 @@ public async Task UseAIContextFromSection()
645645 Assert . Same ( tool , context . Tools ? . First ( ) ) ;
646646 }
647647
648+ [ Fact ]
649+ public async Task UseAIContextFromProvider ( )
650+ {
651+ var builder = new HostApplicationBuilder ( ) ;
652+ var voseo =
653+ """
654+ Default to using spanish language, using argentinean "voseo" in your responses.
655+ """ ;
656+
657+ builder . Configuration . AddToml (
658+ $$ """
659+ [ai.clients.openai]
660+ modelid = "gpt-4.1"
661+ apikey = "sk-asdf"
662+
663+ [ai.agents.chat]
664+ description = "Chat agent."
665+ client = "openai"
666+ use = ["default"]
667+ """ ) ;
668+
669+ var tool = AIFunctionFactory . Create ( ( ) => DateTimeOffset . Now , "get_date" ) ;
670+ builder . Services . AddKeyedSingleton ( "default" , Mock . Of < AIContextProvider > ( x
671+ => x . InvokingAsync ( It . IsAny < AIContextProvider . InvokingContext > ( ) , default ) == ValueTask . FromResult ( new AIContext
672+ {
673+ Instructions = voseo ,
674+ Tools = new [ ] { tool }
675+ } ) ) ) ;
676+
677+ builder . AddAIAgents ( ) ;
678+ var app = builder . Build ( ) ;
679+
680+ var agent = app . Services . GetRequiredKeyedService < AIAgent > ( "chat" ) ;
681+ var options = agent . GetService < ChatClientAgentOptions > ( ) ;
682+
683+ Assert . NotNull ( options ? . AIContextProviderFactory ) ;
684+ var provider = options ? . AIContextProviderFactory ? . Invoke ( new ( ) ) ;
685+ Assert . NotNull ( provider ) ;
686+
687+ var context = await provider . InvokingAsync ( new ( [ ] ) , default ) ;
688+
689+ Assert . NotNull ( context . Instructions ) ;
690+ Assert . Equal ( voseo , context . Instructions ) ;
691+ Assert . Same ( tool , context . Tools ? . First ( ) ) ;
692+ }
693+
694+ [ Fact ]
695+ public async Task CombineAIContextFromStaticDinamicAndSection ( )
696+ {
697+ var builder = new HostApplicationBuilder ( ) ;
698+
699+ builder . Configuration . AddToml (
700+ $$ """
701+ [ai.clients.openai]
702+ modelid = "gpt-4.1"
703+ apikey = "sk-asdf"
704+
705+ [ai.agents.chat]
706+ description = "Chat agent."
707+ client = "openai"
708+ use = ["default", "static", "dynamic"]
709+
710+ [ai.context.default]
711+ instructions = 'foo'
712+ messages = [
713+ { system = "You are strictly professional." },
714+ { user = "Hey you!"},
715+ { assistant = "Hello there. How can I assist you today?" }
716+ ]
717+ tools = ["get_date"]
718+ """ ) ;
719+
720+ var tool = AIFunctionFactory . Create ( ( ) => DateTimeOffset . Now , "get_date" ) ;
721+ builder . Services . AddKeyedSingleton ( "get_date" , tool ) ;
722+
723+ builder . Services . AddKeyedSingleton ( "static" , new AIContext
724+ {
725+ Instructions = "bar" ,
726+ Tools = new AITool [ ] { AIFunctionFactory . Create ( ( ) => "bar" , "get_bar" ) }
727+ } ) ;
728+
729+ AITool [ ] getbaz = [ AIFunctionFactory . Create ( ( ) => "baz" , "get_baz" ) ] ;
730+
731+ builder . Services . AddKeyedSingleton ( "dynamic" , Mock . Of < AIContextProvider > ( x
732+ => x . InvokingAsync ( It . IsAny < AIContextProvider . InvokingContext > ( ) , default ) == ValueTask . FromResult ( new AIContext
733+ {
734+ Instructions = "baz" ,
735+ Tools = getbaz
736+ } ) ) ) ;
737+
738+ builder . AddAIAgents ( ) ;
739+ var app = builder . Build ( ) ;
740+
741+ var agent = app . Services . GetRequiredKeyedService < AIAgent > ( "chat" ) ;
742+ var options = agent . GetService < ChatClientAgentOptions > ( ) ;
743+
744+ Assert . NotNull ( options ? . AIContextProviderFactory ) ;
745+ var provider = options ? . AIContextProviderFactory ? . Invoke ( new ( ) ) ;
746+ Assert . NotNull ( provider ) ;
747+
748+ var context = await provider . InvokingAsync ( new ( [ ] ) , default ) ;
749+
750+ Assert . NotNull ( context . Instructions ) ;
751+ Assert . Contains ( "foo" , context . Instructions ) ;
752+ Assert . Contains ( "bar" , context . Instructions ) ;
753+ Assert . Contains ( "baz" , context . Instructions ) ;
754+
755+ Assert . Equal ( 3 , context . Messages ? . Count ) ;
756+ Assert . Single ( context . Messages ! , x => x . Role == ChatRole . System && x . Text == "You are strictly professional." ) ;
757+ Assert . Single ( context . Messages ! , x => x . Role == ChatRole . User && x . Text == "Hey you!" ) ;
758+ Assert . Single ( context . Messages ! , x => x . Role == ChatRole . Assistant && x . Text == "Hello there. How can I assist you today?" ) ;
759+
760+ Assert . NotNull ( context . Tools ) ;
761+ Assert . Contains ( tool , context . Tools ! ) ;
762+ Assert . Contains ( context . Tools , x => x . Name == "get_bar" ) ;
763+ Assert . Contains ( context . Tools , x => x . Name == "get_baz" ) ;
764+ }
765+
648766 [ Fact ]
649767 public async Task MissingToolAIContextFromSectionThrows ( )
650768 {
0 commit comments