Skip to content
Orqen Docs

Code Examples

Framework integrations

LangChain, LangGraph, and MCP work with Orqen out of the box. The change is always the same two lines: swap api_key to your Orqen key and set base_url to https://api.orqen.app/v1. Everything else — tool definitions, graph logic, MCP sessions — stays unchanged.

Orqen prunes the full tool list down to the relevant subset before forwarding to your LLM provider. Your framework code never sees the routing — it just gets a faster, cheaper response.

LangChain

Use ChatOpenAI with Orqen's base URL. Bind as many tools as your agent needs — Orqen routes each request to the relevant subset automatically.

langchain_orqen.py
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, ToolMessage
from langchain_core.tools import tool

# ── Before (direct OpenAI) ────────────────────────────────────────────────────
# llm = ChatOpenAI(model="gpt-4o", api_key="sk-...")

# ── After (via Orqen) — two lines ────────────────────────────────────────────
llm = ChatOpenAI(
    model="gpt-4o",
    api_key=os.environ["ORQEN_API_KEY"],   # sk-orq-...
    base_url="https://api.orqen.app/v1",
)

# ── Define your tools (Orqen prunes to the relevant subset per request) ───────
@tool
def get_weather(city: str) -> str:
    """Get current weather for a city."""
    return f"Weather in {city}: 22°C, partly cloudy."

@tool
def get_stock_price(ticker: str) -> str:
    """Get the current stock price for a ticker symbol."""
    return f"{ticker}: $142.50 (+1.2%)"

# ... add as many tools as your agent needs

ALL_TOOLS = [get_weather, get_stock_price, ...]
TOOL_MAP = {t.name: t for t in ALL_TOOLS}

# ── Agentic loop ─────────────────────────────────────────────────────────────
llm_with_tools = llm.bind_tools(ALL_TOOLS)
messages = [HumanMessage(content="What is the weather in Tokyo?")]

for _ in range(8):
    response = llm_with_tools.invoke(messages)
    if not response.tool_calls:
        print(response.content)
        break
    messages.append(response)
    for tc in response.tool_calls:
        result = TOOL_MAP[tc["name"]].invoke(tc["args"])
        messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

LangGraph

Drop Orqen into a LangGraph StateGraph ReAct loop. The ToolNode and conditional edges are unchanged — only the LLM constructor differs.

langgraph_orqen.py
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_core.tools import tool
from langgraph.graph import END, StateGraph
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode
from typing import Annotated, Sequence, TypedDict

# ── Before (direct OpenAI) ────────────────────────────────────────────────────
# llm = ChatOpenAI(model="gpt-4o", api_key="sk-...")

# ── After (via Orqen) — two lines ────────────────────────────────────────────
llm = ChatOpenAI(
    model="gpt-4o",
    api_key=os.environ["ORQEN_API_KEY"],   # sk-orq-...
    base_url="https://api.orqen.app/v1",
)

# ── Tools ─────────────────────────────────────────────────────────────────────
@tool
def get_weather(city: str) -> str:
    """Get current weather for a city."""
    return f"Weather in {city}: 22°C, partly cloudy."

ALL_TOOLS = [get_weather, ...]  # Orqen prunes to the relevant subset

# ── Graph state ───────────────────────────────────────────────────────────────
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], add_messages]

# ── Nodes ─────────────────────────────────────────────────────────────────────
llm_with_tools = llm.bind_tools(ALL_TOOLS)

def agent_node(state: AgentState) -> AgentState:
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

def should_continue(state: AgentState) -> str:
    last = state["messages"][-1]
    return "tools" if getattr(last, "tool_calls", None) else END

# ── Build and run ─────────────────────────────────────────────────────────────
tool_node = ToolNode(ALL_TOOLS)
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)
graph.set_entry_point("agent")
graph.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
graph.add_edge("tools", "agent")
app = graph.compile()

result = app.invoke({"messages": [HumanMessage(content="What is the weather in Tokyo?")]})
print(result["messages"][-1].content)

MCP (Model Context Protocol)

MCP clients often aggregate tools from 5+ servers, quickly reaching 50–200 tools per request. Point your Anthropic client at Orqen and every call is automatically routed to only the tools relevant to that prompt.

mcp_orqen.py
import asyncio
import os
import anthropic
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# ── Before (direct Anthropic) ─────────────────────────────────────────────────
# client = anthropic.Anthropic(api_key="sk-ant-...")

# ── After (via Orqen) — two lines ────────────────────────────────────────────
client = anthropic.Anthropic(
    api_key=os.environ["ORQEN_API_KEY"],   # sk-orq-...
    base_url="https://api.orqen.app",
)

# ── Everything else is standard MCP ──────────────────────────────────────────
async def run():
    server_params = StdioServerParameters(
        command="python",
        args=["-m", "mcp.server.filesystem", "."],
    )

    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Collect tools from all MCP servers
            tools_response = await session.list_tools()
            anthropic_tools = [
                {
                    "name": t.name,
                    "description": t.description or "",
                    "input_schema": t.inputSchema or {"type": "object", "properties": {}},
                }
                for t in tools_response.tools
            ]

            # Orqen prunes to the relevant subset before forwarding
            messages = [{"role": "user", "content": "List the Python files here."}]
            response = client.messages.create(
                model="claude-sonnet-4-6",
                max_tokens=1024,
                tools=anthropic_tools,
                messages=messages,
            )

            for block in response.content:
                if block.type == "tool_use":
                    result = await session.call_tool(block.name, block.input)
                    print(result.content[0].text)

asyncio.run(run())

Download the full examples

Runnable scripts with 20 tools and a complete agentic loop are available in the examples/ directory of the Orqen repository: langchain_orqen.py, langgraph_orqen.py, and mcp_orqen.py.