Optimization SDK quickstart

This topic explains how to configure the SDK to use agent optimization. After you enable agent optimization, you can start tuning AI agent prompts, models, and parameters.

Install agent optimization

Agent optimization is available for the Python AI SDK.

Here’s how to install it:

$pip install launchdarkly-server-sdk launchdarkly-server-sdk-ai launchdarkly-server-sdk-ai-optimization

Add your LaunchDarkly API key

If you want to pull configurations from LaunchDarkly or commit variations, metrics, and scores back to LaunchDarkly, you must provide your LAUNCHDARKLY_API_KEY as an environment variable. The agent optimization SDK automatically ingests the API key if you include it.

To learn how to get your LaunchDarkly API token, read API access tokens.

Running your first optimization

There are two ways to run an optimization:

Regardless of which option you use, the same data is emitted and returned. To learn more, read Output.

Use a LaunchDarkly config object

optimize_from_config pulls judges, model choices, and evaluation parameters from a LaunchDarkly configuration. First, you create an optimization config in the LaunchDarkly UI. Then you point your code at the config to bring its specifications into the run.

To learn how to create the config, read Performing optimization runs.

Here’s how to pull in the config:

Python
1# LD imports
2from ldai_optimization import (
3 OptimizationClient,
4 OptimizationFromConfigOptions,
5 OptimizationResponse,
6 LLMCallConfig,
7 LLMCallContext,
8)
9from ldai import LDAIClient
10from ldai.tracker import TokenUsage
11
12# anthropic imports
13from claude_agent_sdk import query, ClaudeAgentOptions
14from claude_agent_sdk.types import ResultMessage
15
16default_fallback_model = "claude-opus-4-5-20251101"
17
18async def run_optimization(ld_ai_client: LDAIClient):
19 async def handle_agent_call(
20 key: str,
21 config: LLMCallConfig,
22 context: LLMCallContext,
23 is_evaluation: bool = False,
24 ) -> OptimizationResponse:
25 model = config.model.name if config.model else default_fallback_model
26 final_message = None
27 async for message in query(
28 prompt=context.user_input or "",
29 options=ClaudeAgentOptions(
30 system_prompt=config.instructions or "",
31 model=model,
32 ),
33 ):
34 final_message = message
35
36 if not isinstance(final_message, ResultMessage):
37 raise ValueError(f"Unexpected final message type: {type(final_message)}")
38
39 u = final_message.usage or {}
40 input_tokens = u.get("input_tokens", 0)
41 output_tokens = u.get("output_tokens", 0)
42
43 return OptimizationResponse(
44 output=final_message.result or "",
45 usage=TokenUsage(
46 total=input_tokens + output_tokens,
47 input=input_tokens,
48 output=output_tokens,
49 ),
50 )
51
52 options = OptimizationFromConfigOptions(
53 project_key="default",
54 handle_agent_call=handle_agent_call,
55 handle_judge_call=handle_agent_call,
56 )
57
58 client = OptimizationClient(ld_ai_client)
59 result = await client.optimize_from_config("my-optimization-key", options)

Do it in your code

optimize_from_options lets you define all judges, model choices, and evaluation parameters directly in code without a LaunchDarkly configuration object.

To learn more about optimize_from_options, read Optimization runs without a config.

Output

This call returns an OptimizationContext representing the final output of the optimization. You can access OptimizationContext.history to get all of the historical OptimizationContexts generated during the run.

To learn more, read the OptimizationContext reference.

Wrapping up

These are the two core ways to run an optimization, but there is even more optimization functionality. Read these other resources to get more information: