Skip to content

Commit aaaed58

Browse files
authored
feat: Add LangGraph agent example (#11)
1 parent 22f2d19 commit aaaed58

3 files changed

Lines changed: 150 additions & 1 deletion

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ This repository includes examples for `OpenAI`, `Bedrock`, and `LangChain` for m
1212

1313
### General setup
1414

15-
1. Set the environment variable `LAUNCHDARKLY_SDK_KEY` to your LaunchDarkly SDK key. If there is an existing an AI Config in your LaunchDarkly project that you want to evaluate, set `LAUNCHDARKLY_AI_CONFIG_KEY` to the flag key; otherwise, an AI Config of `sample-ai-config` will be assumed.
15+
1. Set the environment variable `LAUNCHDARKLY_SDK_KEY` to your LaunchDarkly SDK key. If there is an existing AI Config in your LaunchDarkly project that you want to evaluate, set `LAUNCHDARKLY_AI_CONFIG_KEY` to the flag key; otherwise, an AI Config of `sample-ai-config` or `sample-ai-agent-config` will be assumed.
1616

1717
```bash
1818
export LAUNCHDARKLY_SDK_KEY="1234567890abcdef"
@@ -48,3 +48,13 @@ This example uses `OpenAI`, `Bedrock`, and `Gemini` LangChain provider packages.
4848
1. Install all dependencies with `poetry install -E langchain` or `poetry install --all-extras`.
4949
1. Set up API keys for the providers you want to use
5050
1. On the command line, run `poetry run langchain-example`
51+
52+
#### LangGraph setup (multiple providers, single agent)
53+
54+
1. Install all dependencies with `poetry install -E langgraph` or `poetry install --all-extras`.
55+
1. Set up API keys for the providers you want to use
56+
1. Optionally set environment variable for the agent config:
57+
```bash
58+
export LAUNCHDARKLY_AGENT_CONFIG_KEY="sample-ai-agent-config"
59+
```
60+
1. On the command line, run `poetry run langgraph-agent-example`
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import os
2+
import ldclient
3+
from pprint import pprint
4+
from ldclient import Context
5+
from ldclient.config import Config
6+
from ldai.client import LDAIClient, LDAIAgentConfig, LDAIAgentDefaults
7+
from ldai.tracker import TokenUsage
8+
from langchain.chat_models import init_chat_model
9+
from langgraph.prebuilt import create_react_agent
10+
11+
# Set sdk_key to your LaunchDarkly SDK key.
12+
sdk_key = os.getenv('LAUNCHDARKLY_SDK_KEY')
13+
14+
# Set config key for the agent
15+
agent_config_key = os.getenv('LAUNCHDARKLY_AGENT_CONFIG_KEY', 'sample-ai-agent-config')
16+
17+
def map_provider_to_langchain(provider_name):
18+
"""Map LaunchDarkly provider names to LangChain provider names."""
19+
provider_mapping = {
20+
'gemini': 'google_genai'
21+
}
22+
lower_provider = provider_name.lower()
23+
return provider_mapping.get(lower_provider, lower_provider)
24+
25+
def track_langgraph_metrics(tracker, func):
26+
"""
27+
Track LangGraph agent operations with LaunchDarkly metrics.
28+
"""
29+
try:
30+
result = tracker.track_duration_of(func)
31+
tracker.track_success()
32+
33+
# For LangGraph agents, usage_metadata is included on all messages that used AI
34+
total_input_tokens = 0
35+
total_output_tokens = 0
36+
total_tokens = 0
37+
38+
if "messages" in result:
39+
for message in result['messages']:
40+
# Check for usage_metadata directly on the message
41+
if hasattr(message, "usage_metadata") and message.usage_metadata:
42+
usage_data = message.usage_metadata
43+
total_input_tokens += usage_data.get("input_tokens", 0)
44+
total_output_tokens += usage_data.get("output_tokens", 0)
45+
total_tokens += usage_data.get("total_tokens", 0)
46+
47+
if total_tokens > 0:
48+
token_usage = TokenUsage(
49+
input=total_input_tokens,
50+
output=total_output_tokens,
51+
total=total_tokens
52+
)
53+
tracker.track_tokens(token_usage)
54+
except Exception:
55+
tracker.track_error()
56+
raise
57+
return result
58+
59+
def get_weather(city: str) -> str:
60+
"""Get the weather for a given city."""
61+
return f"The weather in {city} is sunny."
62+
63+
def main():
64+
if not sdk_key:
65+
print("*** Please set the LAUNCHDARKLY_SDK_KEY env first")
66+
exit()
67+
68+
ldclient.set_config(Config(sdk_key))
69+
if not ldclient.get().is_initialized():
70+
print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.")
71+
exit()
72+
73+
aiclient = LDAIClient(ldclient.get())
74+
print("*** SDK successfully initialized")
75+
76+
# Set up the evaluation context
77+
context = (
78+
Context
79+
.builder('weather-user')
80+
.kind('user')
81+
.name('Weather User')
82+
.build()
83+
)
84+
85+
print(f"🔍 Using agent config: {agent_config_key}")
86+
print()
87+
88+
# Create a LangChain model with LaunchDarkly AI config.
89+
# Default value with disabled agent
90+
default_value = LDAIAgentDefaults(
91+
enabled=False, # Disabled by default
92+
)
93+
94+
agent_config = aiclient.agent(
95+
LDAIAgentConfig(
96+
key=agent_config_key,
97+
default_value=default_value,
98+
),
99+
context
100+
)
101+
102+
if not agent_config.enabled:
103+
print("AI Agent Config is disabled")
104+
return
105+
106+
langchain_provider = map_provider_to_langchain(agent_config.provider.name)
107+
llm = init_chat_model(
108+
model=agent_config.model.name,
109+
model_provider=langchain_provider,
110+
)
111+
112+
# Create a React agent with the LLM and tools
113+
agent = create_react_agent(
114+
model=llm,
115+
tools=[get_weather],
116+
prompt=agent_config.instructions
117+
)
118+
119+
try:
120+
# Track and execute the agent
121+
response = track_langgraph_metrics(agent_config.tracker, lambda: agent.invoke({
122+
"messages": [{"role": "user", "content": "What is the weather in Tokyo?"}]
123+
}))
124+
125+
print("Agent response:")
126+
print(response["messages"][-1].content)
127+
128+
except Exception as e:
129+
print(f"Error: {e}")
130+
print("Please ensure you have the correct API keys and credentials set up for the detected providers.")
131+
132+
# Close the client to flush events and close the connection.
133+
ldclient.get().close()
134+
135+
if __name__ == "__main__":
136+
main()

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ bedrock-example = 'examples.bedrock_example:main'
1212
openai-example = 'examples.openai_example:main'
1313
gemini-example = 'examples.gemini_example:main'
1414
langchain-example = 'examples.langchain_example:main'
15+
langgraph-agent-example = 'examples.langgraph_agent_example:main'
1516

1617
[tool.poetry.dependencies]
1718
python = "^3.9"
@@ -24,12 +25,14 @@ langchain = {version = "^0.3.0", optional = true}
2425
langchain-aws = {version = "^0.2.30", optional = true}
2526
langchain-google-genai = {version = "^2.1.9", optional = true}
2627
langchain-openai = {version = "^0.3.30", optional = true}
28+
langgraph = {version = "^0.2.0", optional = true}
2729

2830
[tool.poetry.extras]
2931
bedrock = ["boto3"]
3032
openai = ["openai"]
3133
gemini = ["google-genai"]
3234
langchain = ["langchain", "langchain-openai", "langchain-google-genai", "langchain-aws"]
35+
langgraph = ["langgraph", "typing-extensions"]
3336

3437
[build-system]
3538
requires = ["poetry-core"]

0 commit comments

Comments
 (0)