LangChain with Caddey
Integrate Caddey tools into a LangChain Python agent.
Caddey exposes app features as tools, and LangChain agents can dynamically choose and call these tools. This guide shows two ways to integrate Caddey tools—preloading them into your agent or loading them dynamically at runtime.
Prerequisites
- Caddey OAuth client (create an OAuth client and note the Client ID)
- Python 3.x and a virtual environment
- LangChain & helpers
pip install langchain openai requests python-dotenv requests-oauthlib
- LLM API key (e.g.
OPENAI_API_KEY
for ChatOpenAI) - Caddey OAuth Client ID (from your Caddey OAuth client)
Security tip: Store secrets in environment variables or a .env
file (never commit them).
OAuth 2.0 Setup
Before using Caddey tools, you need to implement OAuth 2.0 to obtain an access token:
import os
from requests_oauthlib import OAuth2Session
def get_caddey_access_token(client_id, redirect_uri="http://localhost:8080/callback"):
# Create OAuth2 session
oauth = OAuth2Session(
client_id=client_id,
redirect_uri=redirect_uri,
scope=['openid', 'profile', 'email']
)
# Get authorization URL
authorization_url, state = oauth.authorization_url(
'https://auth.caddey.ai/realms/caddey/protocol/openid-connect/auth'
)
print(f"Please go to {authorization_url} and authorize access.")
authorization_response = input('Paste the full redirect URL here: ')
# Fetch access token
token = oauth.fetch_token(
'https://auth.caddey.ai/realms/caddey/protocol/openid-connect/token',
authorization_response=authorization_response,
client_secret=None # Public client
)
return token['access_token']
# Get access token
CLIENT_ID = os.getenv("CADDEY_CLIENT_ID")
CADDEY_TOKEN = get_caddey_access_token(CLIENT_ID)
Now that you have an access token, you can use it with either approach below.
Approach A: Preload Tools into LangChain
Fetch tool definitions and convert them into LangChain Tool objects.
import requests
import json
from langchain.agents import Tool
# Use the token from OAuth flow above
# Fetch tool definitions
response = requests.get(
"https://api.caddey.ai/tools/query",
headers={"Authorization": f"Bearer {CADDEY_TOKEN}"}
)
tools_data = response.json().get("content", [])
# Convert to LangChain Tool objects
preloaded_tools = []
for tool in tools_data:
def make_func(tool_id):
def run_tool(input_str: str):
payload = json.loads(input_str) if input_str else {}
res = requests.post(
f"https://api.caddey.ai/tools/{tool_id}/execute",
headers={"Authorization": f"Bearer {CADDEY_TOKEN}"},
json=payload
)
return json.dumps(res.json(), indent=2)
return run_tool
preloaded_tools.append(
Tool(
name=tool.get("name", ""),
description=tool.get("description", ""),
func=make_func(tool.get("id", ""))
)
)
Approach B: Dynamic Tool Loading
Provide two generic tools that let the model fetch and execute tools on the fly.
import requests
import json
from langchain.agents import Tool
# Use the token from OAuth flow above
def list_caddey_tools(input_json: str) -> str:
"""
input_json (optional): JSON string with keys:
- pageNumber (int)
- pageSize (int)
- searchTerm (str) # free-text filter
"""
params = {"pageNumber": 0, "pageSize": 20}
if input_json:
opts = json.loads(input_json)
params["pageNumber"] = opts.get("pageNumber", params["pageNumber"])
params["pageSize"] = opts.get("pageSize", params["pageSize"])
if "searchTerm" in opts:
params["search"] = opts["searchTerm"]
response = requests.get("https://api.caddey.ai/tools/query", headers={"Authorization": f"Bearer {CADDEY_TOKEN}"}, params=params)
response.raise_for_status()
return json.dumps(response.json(), indent=2)
def execute_caddey_tool(input_json: str) -> str:
"""
input_json: JSON string with keys:
- tool_id (str, UUID)
- input (object) # the payload to pass to the tool
"""
payload = json.loads(input_json)
tool_id = payload["tool_id"]
params = payload.get("input", {})
response = requests.post(
f"https://api.caddey.ai/tools/{tool_id}/execute",
headers={"Authorization": f"Bearer {CADDEY_TOKEN}"},
json={"input": params},
)
response.raise_for_status()
return json.dumps(response.json(), indent=2)
list_tools_tool = Tool(
name="List Caddey Tools",
description=(
"Fetch a paginated list of Caddey tools. "
"Input JSON may specify pageNumber, pageSize, and searchTerm (free-text)."
),
func=list_caddey_tools,
)
execute_tool = Tool(
name="Execute Caddey Tool",
description=(
"Execute any Caddey tool by ID. "
"Input JSON must include tool_id and an 'input' object for its parameters."
),
func=execute_caddey_tool,
)
Initialize the Agent
After setting up your tool list (either preloaded_tools
from Approach A or [list_tools_tool, execute_tool]
from Approach B), initialize your LangChain agent.
from langchain.chat_models import ChatOpenAI
from langchain.agents import initialize_agent, AgentType
import os
llm = ChatOpenAI(
temperature=0,
openai_api_key=os.getenv("OPENAI_API_KEY")
)
# Use preloaded_tools OR dynamic tools
tools_list = preloaded_tools # or [list_tools_tool, execute_tool]
agent = initialize_agent(
tools=tools_list,
llm=llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
Using Your Agent
Simply prompt the agent in natural language, and it will pick the appropriate tool under the hood.
Examples:
- Create a reminder to call Bob tomorrow at 3 PM.
- Fetch the list of available tools.
- Send an email to [email protected] with subject “Project Update” and body “The report is ready.”
The agent will automatically invoke the listing or execution of tools as needed.
For additional support, visit the Support Section.