@@ -125,6 +125,81 @@ def to_dict(self) -> dict:
125125 }
126126
127127
128+ @dataclass (frozen = True )
129+ class LDAIAgent :
130+ """
131+ Represents an AI agent configuration with instructions and model settings.
132+
133+ An agent is similar to an AIConfig but focuses on instructions rather than messages,
134+ making it suitable for AI assistant/agent use cases.
135+ """
136+ enabled : Optional [bool ] = None
137+ model : Optional [ModelConfig ] = None
138+ provider : Optional [ProviderConfig ] = None
139+ instructions : Optional [str ] = None
140+ tracker : Optional [LDAIConfigTracker ] = None
141+
142+ def to_dict (self ) -> Dict [str , Any ]:
143+ """
144+ Render the given agent as a dictionary object.
145+ """
146+ result : Dict [str , Any ] = {
147+ '_ldMeta' : {
148+ 'enabled' : self .enabled or False ,
149+ },
150+ 'model' : self .model .to_dict () if self .model else None ,
151+ 'provider' : self .provider .to_dict () if self .provider else None ,
152+ }
153+ if self .instructions is not None :
154+ result ['instructions' ] = self .instructions
155+ return result
156+
157+
158+ @dataclass (frozen = True )
159+ class LDAIAgentDefaults :
160+ """
161+ Default values for AI agent configurations.
162+
163+ Similar to LDAIAgent but without tracker and with optional enabled field,
164+ used as fallback values when agent configurations are not available.
165+ """
166+ enabled : Optional [bool ] = None
167+ model : Optional [ModelConfig ] = None
168+ provider : Optional [ProviderConfig ] = None
169+ instructions : Optional [str ] = None
170+
171+ def to_dict (self ) -> Dict [str , Any ]:
172+ """
173+ Render the given agent defaults as a dictionary object.
174+ """
175+ result : Dict [str , Any ] = {
176+ '_ldMeta' : {
177+ 'enabled' : self .enabled or False ,
178+ },
179+ 'model' : self .model .to_dict () if self .model else None ,
180+ 'provider' : self .provider .to_dict () if self .provider else None ,
181+ }
182+ if self .instructions is not None :
183+ result ['instructions' ] = self .instructions
184+ return result
185+
186+
187+ @dataclass
188+ class LDAIAgentConfig :
189+ """
190+ Configuration for individual agent in batch requests.
191+
192+ Combines agent key with its specific default configuration and variables.
193+ """
194+ key : str
195+ default_value : LDAIAgentDefaults
196+ variables : Optional [Dict [str , Any ]] = None
197+
198+
199+ # Type alias for multiple agents
200+ LDAIAgents = Dict [str , LDAIAgent ]
201+
202+
128203class LDAIClient :
129204 """The LaunchDarkly AI SDK client object."""
130205
@@ -147,13 +222,144 @@ def config(
147222 :param variables: Additional variables for the model configuration.
148223 :return: The value of the model configuration along with a tracker used for gathering metrics.
149224 """
150- variation = self ._client .variation (key , context , default_value .to_dict ())
225+ model , provider , messages , instructions , tracker , enabled = self .__evaluate (key , context , default_value .to_dict (), variables )
226+
227+ config = AIConfig (
228+ enabled = bool (enabled ),
229+ model = model ,
230+ messages = messages ,
231+ provider = provider ,
232+ )
233+
234+ return config , tracker
235+
236+ def agent (
237+ self ,
238+ config : LDAIAgentConfig ,
239+ context : Context ,
240+ ) -> LDAIAgent :
241+ """
242+ Retrieve a single AI Config agent.
243+
244+ This method retrieves a single agent configuration with instructions
245+ dynamically interpolated using the provided variables and context data.
246+
247+ Example::
248+
249+ agent = client.agent(LDAIAgentConfig(
250+ key='research_agent',
251+ default_value=LDAIAgentDefaults(
252+ enabled=True,
253+ model=ModelConfig('gpt-4'),
254+ instructions="You are a research assistant specializing in {{topic}}."
255+ ),
256+ variables={'topic': 'climate change'}
257+ ), context)
258+
259+ if agent.enabled:
260+ research_result = agent.instructions # Interpolated instructions
261+ agent.tracker.track_success()
262+
263+ :param config: The agent configuration to use.
264+ :param context: The context to evaluate the agent configuration in.
265+ :return: Configured LDAIAgent instance.
266+ """
267+ # Track single agent usage
268+ self ._client .track (
269+ "$ld:ai:agent:function:single" ,
270+ context ,
271+ config .key ,
272+ 1
273+ )
274+
275+ return self .__evaluate_agent (config .key , context , config .default_value , config .variables )
276+
277+ def agents (
278+ self ,
279+ agent_configs : List [LDAIAgentConfig ],
280+ context : Context ,
281+ ) -> LDAIAgents :
282+ """
283+ Retrieve multiple AI agent configurations.
284+
285+ This method allows you to retrieve multiple agent configurations in a single call,
286+ with each agent having its own default configuration and variables for instruction
287+ interpolation.
288+
289+ Example::
290+
291+ agents = client.agents([
292+ LDAIAgentConfig(
293+ key='research_agent',
294+ default_value=LDAIAgentDefaults(
295+ enabled=True,
296+ instructions='You are a research assistant.'
297+ ),
298+ variables={'topic': 'climate change'}
299+ ),
300+ LDAIAgentConfig(
301+ key='writing_agent',
302+ default_value=LDAIAgentDefaults(
303+ enabled=True,
304+ instructions='You are a writing assistant.'
305+ ),
306+ variables={'style': 'academic'}
307+ )
308+ ], context)
309+
310+ research_result = agents["research_agent"].instructions
311+ agents["research_agent"].tracker.track_success()
312+
313+ :param agent_configs: List of agent configurations to retrieve.
314+ :param context: The context to evaluate the agent configurations in.
315+ :return: Dictionary mapping agent keys to their LDAIAgent configurations.
316+ """
317+ # Track multiple agents usage
318+ agent_count = len (agent_configs )
319+ self ._client .track (
320+ "$ld:ai:agent:function:multiple" ,
321+ context ,
322+ agent_count ,
323+ agent_count
324+ )
325+
326+ result : LDAIAgents = {}
327+
328+ for config in agent_configs :
329+ agent = self .__evaluate_agent (
330+ config .key ,
331+ context ,
332+ config .default_value ,
333+ config .variables
334+ )
335+ result [config .key ] = agent
336+
337+ return result
338+
339+ def __evaluate (
340+ self ,
341+ key : str ,
342+ context : Context ,
343+ default_dict : Dict [str , Any ],
344+ variables : Optional [Dict [str , Any ]] = None ,
345+ ) -> Tuple [Optional [ModelConfig ], Optional [ProviderConfig ], Optional [List [LDMessage ]], Optional [str ], LDAIConfigTracker , bool ]:
346+ """
347+ Internal method to evaluate a configuration and extract components.
348+
349+ :param key: The configuration key.
350+ :param context: The evaluation context.
351+ :param default_dict: Default configuration as dictionary.
352+ :param variables: Variables for interpolation.
353+ :return: Tuple of (model, provider, messages, instructions, tracker, enabled).
354+ """
355+ variation = self ._client .variation (key , context , default_dict )
151356
152357 all_variables = {}
153358 if variables :
154359 all_variables .update (variables )
155360 all_variables ['ldctx' ] = context .to_dict ()
156361
362+ # Extract messages
157363 messages = None
158364 if 'messages' in variation and isinstance (variation ['messages' ], list ) and all (
159365 isinstance (entry , dict ) for entry in variation ['messages' ]
@@ -168,11 +374,18 @@ def config(
168374 for entry in variation ['messages' ]
169375 ]
170376
377+ # Extract instructions
378+ instructions = None
379+ if 'instructions' in variation and isinstance (variation ['instructions' ], str ):
380+ instructions = self .__interpolate_template (variation ['instructions' ], all_variables )
381+
382+ # Extract provider config
171383 provider_config = None
172384 if 'provider' in variation and isinstance (variation ['provider' ], dict ):
173385 provider = variation ['provider' ]
174386 provider_config = ProviderConfig (provider .get ('name' , '' ))
175387
388+ # Extract model config
176389 model = None
177390 if 'model' in variation and isinstance (variation ['model' ], dict ):
178391 parameters = variation ['model' ].get ('parameters' , None )
@@ -183,6 +396,7 @@ def config(
183396 custom = custom
184397 )
185398
399+ # Create tracker
186400 tracker = LDAIConfigTracker (
187401 self ._client ,
188402 variation .get ('_ldMeta' , {}).get ('variationKey' , '' ),
@@ -192,21 +406,46 @@ def config(
192406 )
193407
194408 enabled = variation .get ('_ldMeta' , {}).get ('enabled' , False )
195- config = AIConfig (
196- enabled = bool (enabled ),
197- model = model ,
198- messages = messages ,
199- provider = provider_config ,
409+
410+ return model , provider_config , messages , instructions , tracker , enabled
411+
412+ def __evaluate_agent (
413+ self ,
414+ key : str ,
415+ context : Context ,
416+ default_value : LDAIAgentDefaults ,
417+ variables : Optional [Dict [str , Any ]] = None ,
418+ ) -> LDAIAgent :
419+ """
420+ Internal method to evaluate an agent configuration.
421+
422+ :param key: The agent configuration key.
423+ :param context: The evaluation context.
424+ :param default_value: Default agent values.
425+ :param variables: Variables for interpolation.
426+ :return: Configured LDAIAgent instance.
427+ """
428+ model , provider , messages , instructions , tracker , enabled = self .__evaluate (
429+ key , context , default_value .to_dict (), variables
200430 )
201431
202- return config , tracker
432+ # For agents, prioritize instructions over messages
433+ final_instructions = instructions if instructions is not None else default_value .instructions
434+
435+ return LDAIAgent (
436+ enabled = bool (enabled ) if enabled is not None else default_value .enabled ,
437+ model = model or default_value .model ,
438+ provider = provider or default_value .provider ,
439+ instructions = final_instructions ,
440+ tracker = tracker ,
441+ )
203442
204443 def __interpolate_template (self , template : str , variables : Dict [str , Any ]) -> str :
205444 """
206- Interpolate the template with the given variables.
445+ Interpolate the template with the given variables using Mustache format .
207446
208- :template: The template string.
209- :variables: The variables to interpolate into the template.
447+ :param template: The template string.
448+ :param variables: The variables to interpolate into the template.
210449 :return: The interpolated string.
211450 """
212451 return chevron .render (template , variables )
0 commit comments