DEV Community

Richard Dillon
Richard Dillon

Posted on

The LangSmith LLM Gateway — Runtime Controls for Production Agents

The LangSmith LLM Gateway — Runtime Controls for Production Agents

Last week, a financial services firm running LangGraph agents in production watched helplessly as a misconfigured research loop made 2,400 Claude API calls in under three minutes, burning through $1,800 before anyone could kill the process. The agent was working correctly—it just didn't know when to stop. This scenario, increasingly common as agents move from demos to production, exposes a critical gap in our current tooling: we have excellent observability for what agents did, but almost no runtime control over what they're doing right now.

LangSmith's new LLM Gateway, announced July 30, 2026, directly addresses this gap by introducing a proxy layer that intercepts all LLM calls for real-time governance. Unlike existing solutions that focus on after-the-fact tracing or deployment orchestration, the Gateway provides active runtime intervention—transforming requests, enforcing cost ceilings, routing to fallback models, and filtering responses, all without touching your agent code. For teams running agents that make thousands of LLM calls per session, this isn't a nice-to-have; it's the control plane that's been conspicuously absent from the agentic stack.

Architecture: How the Gateway Intercepts Agent-to-Model Traffic

The Gateway operates as a transparent proxy between your agents and their LLM providers, but its design reflects hard-learned lessons about production agent behavior. Understanding the architecture helps you choose the right deployment mode and anticipate how policies interact with your existing retry logic.

Deployment Topology

The Gateway supports three deployment modes, each with distinct tradeoffs. Sidecar mode runs the gateway as a local process alongside your agent, minimizing latency but requiring deployment coordination. Standalone proxy mode centralizes the gateway for multiple agents, simplifying policy management at the cost of network hops. LangSmith-hosted mode eliminates infrastructure overhead entirely—LangChain operates the gateway as a managed service, routing your traffic through their edge network.

Request Lifecycle

Every LLM call follows a predictable path: your agent initiates a request, the Gateway intercepts it, evaluates applicable policies, potentially transforms the request, forwards it to the upstream LLM, receives the response, applies output policies (redaction, filtering), and finally returns the result to your agent. This happens transparently—your agent code sees a normal LLM response, unaware that it passed through a governance layer.

Integration Points

LangChain provides three integration methods of increasing explicitness. The simplest approach uses the langchain-gateway wrapper that automatically routes all LangChain/LangGraph LLM calls through the gateway. For non-LangChain code, setting LANGCHAIN_LLM_GATEWAY_URL as an environment variable routes OpenAI-compatible API calls. For maximum control, explicit GatewayClient instantiation lets you selectively gateway specific calls.

Stateless vs. Stateful Policies

A crucial architectural distinction: some policies evaluate each request independently (content filters, prompt injection detection), while others maintain session state (cumulative token budgets, conversation-level PII tracking). Stateful policies require the Gateway to track session boundaries, which it infers from LangGraph thread IDs or explicit session headers. This agent-aware approach distinguishes the Gateway from generic API management tools like Azure API Management or AWS Bedrock Guardrails, which lack context about multi-step agent plans and tool call sequences.

Latency Overhead

LangChain's published benchmarks show less than 15ms P99 added latency in sidecar mode and under 40ms for hosted mode. For agents where individual LLM calls take 500ms–3s, this overhead is typically negligible. However, for agents making rapid-fire tool calls with smaller models, the cumulative overhead can add up—something to measure in your specific deployment.

Policy Configuration: Declarative Rules for Agent Governance

Policies are the heart of the Gateway—declarative rules that define what's allowed, what gets transformed, and what triggers alerts or hard stops. The YAML-based format prioritizes readability and version control, with inheritance chains that let you define organization-wide defaults while allowing per-agent overrides.

Policy File Structure

Policies live in gateway-policies.yaml, organized into namespaces that can inherit from each other. A common pattern establishes baseline policies at the organization level, then progressively tightens or loosens constraints for specific teams, environments, or individual agents. Environment variable interpolation (${COST_CEILING}) enables different values across dev/staging/prod without separate policy files.

Cost Ceiling Policies

The most immediately valuable policy type prevents runaway spending. You can set max_cost_per_session, max_cost_per_user, or max_tokens_per_minute, each with configurable actions when thresholds approach or exceed limits. Actions range from soft interventions (emit warning, throttle request rate, degrade to cheaper model) to hard stops that return an error to the agent. Multi-tier thresholds let you implement gradual degradation: at 70% budget, switch from GPT-5 to Claude 4; at 90%, switch to Llama 4; at 100%, hard stop.

Model Routing Policies

Beyond cost-triggered fallback, you can define routing rules based on latency, error rates, or request characteristics. Primary/fallback chains (e.g., GPT-5 → Claude 4 → local Llama 4) automatically activate when the primary model experiences latency spikes above your threshold or returns error rates exceeding your tolerance. This provides resilience against provider outages without code changes—your agent continues operating, potentially with degraded capability, rather than failing entirely.

Content Transformation Policies

Request rewriting policies can inject defensive prefixes (prompt injection mitigation), strip sensitive context from requests, or normalize prompt formats across different agent versions. Response filtering policies support PII redaction via regex patterns, custom entity matchers for domain-specific sensitive data (account numbers, medical IDs), and blocklist filtering for content policy enforcement. These transformations happen transparently—your agent sees clean data without needing per-call filtering logic.

Tool-Call-Specific Policies

Perhaps the most powerful feature for agentic workloads: policies can evaluate based on tool context. You might restrict which tools can trigger expensive models (only the final synthesis step gets GPT-5; intermediate formatting calls use the cheapest available model) or enforce that certain tool outputs pass through enhanced filtering before entering agent context. This granularity prevents the common pattern where 80% of your LLM spend goes to trivial tool calls that don't need frontier model capabilities.

Hands-On: Code Walkthrough

Let's add cost controls and model fallback to an existing LangGraph research agent. This scenario mirrors the opening example: an agent that performs multi-step research, potentially making many LLM calls, where we need guardrails against runaway execution without modifying the core agent logic.

Step 1: Install and Configure

# Install the gateway package
# pip install langchain-gateway langchain-langgraph langchain-anthropic langchain-openai

import os

# Configure gateway endpoint - using LangSmith hosted mode for this example
os.environ["LANGCHAIN_LLM_GATEWAY_URL"] = "https://gateway.langsmith.com"
os.environ["LANGCHAIN_API_KEY"] = "your-langsmith-api-key"

# The gateway automatically intercepts LLM calls when this is set
os.environ["LANGCHAIN_GATEWAY_ENABLED"] = "true"

# Optional: specify which policy namespace to use
os.environ["LANGCHAIN_GATEWAY_POLICY_NAMESPACE"] = "research-agents/production"
Enter fullscreen mode Exit fullscreen mode

Step 2: Define Gateway Policies

# gateway-policies.yaml
# This file defines runtime governance rules for your agents

version: "1.0"
namespace: research-agents/production

# Inherit organization-wide defaults
inherits: org-defaults/base

policies:
  # Cost ceiling with graduated response
  cost_control:
    max_cost_per_session: 5.00  # USD
    thresholds:
      - at_percent: 70
        action: log_warning
        message: "Session approaching cost ceiling"
      - at_percent: 85
        action: degrade_model
        fallback_to: "claude-3-5-sonnet-20241022"  # Cheaper than primary
      - at_percent: 95
        action: degrade_model
        fallback_to: "gpt-4o-mini"  # Even cheaper
      - at_percent: 100
        action: hard_stop
        error_message: "Session cost ceiling exceeded. Please start a new session."

  # Model fallback chain for resilience
  model_routing:
    primary: "claude-sonnet-4-20250514"
    fallback_chain:
      - model: "gpt-4o"
        trigger:
          latency_p95_above_ms: 3000
          error_rate_above_percent: 5
      - model: "gpt-4o-mini"
        trigger:
          latency_p95_above_ms: 5000
          error_rate_above_percent: 15
    # Track metrics over rolling 5-minute windows
    evaluation_window_seconds: 300

  # PII redaction on all responses
  content_filtering:
    response_filters:
      - type: pii_redaction
        enabled: true
        entity_types:
          - email
          - phone_number
          - ssn
          - credit_card
        replacement: "[REDACTED]"
      - type: custom_regex
        patterns:
          - name: internal_account_id
            pattern: "ACC-[A-Z0-9]{8}"
            replacement: "[ACCOUNT_ID_REDACTED]"

  # Tool-specific model routing - use cheaper models for low-stakes operations
  tool_policies:
    - tool_name_pattern: "format_*"
      force_model: "gpt-4o-mini"
    - tool_name_pattern: "log_*"
      force_model: "gpt-4o-mini"
    - tool_name_pattern: "search_*"
      # Allow expensive models for search synthesis
      allowed_models: ["claude-sonnet-4-20250514", "gpt-4o"]
Enter fullscreen mode Exit fullscreen mode

Step 3: Wrap the Agent (Before/After Comparison)

# BEFORE: Direct LLM instantiation without gateway
# from langchain_anthropic import ChatAnthropic
# llm = ChatAnthropic(model="claude-sonnet-4-20250514")

# AFTER: Gateway-wrapped instantiation (minimal changes!)
from langchain_gateway import GatewayLLM
from langchain_anthropic import ChatAnthropic

# The underlying model - gateway will route/transform as policies dictate
base_llm = ChatAnthropic(model="claude-sonnet-4-20250514")

# Wrap with gateway - this enables all policy enforcement
llm = GatewayLLM(
    llm=base_llm,
    # Session ID enables stateful policies (cost tracking across calls)
    session_id_header="X-Research-Session-ID",
    # Tags for policy matching and observability
    gateway_tags=["research-agent", "production"],
)

# Your existing LangGraph code works unchanged
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.prebuilt import ToolNode

# Example research tools
def search_papers(query: str) -> str:
    """Search academic papers for the given query."""
    # Implementation would call actual search API
    return f"Found 15 papers about {query}"

def summarize_findings(papers: list) -> str:
    """Synthesize findings from multiple papers."""
    return "Synthesis of research findings..."

def format_citation(paper: dict) -> str:
    """Format a paper as a citation."""
    return "Formatted citation string"

tools = [search_papers, summarize_findings, format_citation]

# Bind tools to the gateway-wrapped LLM
llm_with_tools = llm.bind_tools(tools)
Enter fullscreen mode Exit fullscreen mode

Step 4: Build the Agent Graph

from typing import Annotated, Literal
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages

class ResearchState(TypedDict):
    messages: Annotated[list, add_messages]
    research_depth: int
    cost_alerts: list[str]

def researcher_node(state: ResearchState):
    """Main research reasoning node - makes LLM calls through gateway."""
    messages = state["messages"]

    # This call goes through the gateway, subject to all policies
    # Gateway tracks cost, may route to fallback model, filters response
    response = llm_with_tools.invoke(messages)

    return {"messages": [response]}

def should_continue(state: ResearchState) -> Literal["tools", "end"]:
    """Determine if we should continue researching or finish."""
    last_message = state["messages"][-1]
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "tools"
    return "end"

# Build the graph
graph_builder = StateGraph(ResearchState)

graph_builder.add_node("researcher", researcher_node)
graph_builder.add_node("tools", ToolNode(tools))

graph_builder.add_edge(START, "researcher")
graph_builder.add_conditional_edges("researcher", should_continue)
graph_builder.add_edge("tools", "researcher")

# Compile with checkpointing for cost-per-checkpoint analysis
from langgraph.checkpoint.memory import MemorySaver
memory = MemorySaver()
research_agent = graph_builder.compile(checkpointer=memory)
Enter fullscreen mode Exit fullscreen mode

Step 5: Run and Observe Gateway Behavior

from langchain_gateway import GatewayEventHandler
import uuid

# Create a session ID for cost tracking
session_id = str(uuid.uuid4())

# Optional: Add event handler to see gateway decisions in real-time
class CostAlertHandler(GatewayEventHandler):
    def on_cost_threshold(self, event):
        print(f"⚠️ Cost alert: {event.message} (${event.current_cost:.2f}/${event.ceiling:.2f})")

    def on_model_fallback(self, event):
        print(f"🔄 Model fallback: {event.original_model}{event.fallback_model}")
        print(f"   Reason: {event.trigger_reason}")

    def on_content_filtered(self, event):
        print(f"🔒 Content filtered: {event.filter_type} applied")

# Register handler
GatewayLLM.add_event_handler(CostAlertHandler())

# Run a research task that might hit cost limits
config = {
    "configurable": {
        "thread_id": session_id,
    },
    "metadata": {
        "gateway_session_id": session_id,  # Links to gateway cost tracking
    }
}

# This query might trigger many LLM calls
result = research_agent.invoke(
    {
        "messages": [
            ("user", "Research the latest developments in quantum error correction. "
                     "Find at least 10 recent papers, summarize each, identify common themes, "
                     "and synthesize a comprehensive overview with proper citations.")
        ],
        "research_depth": 3,
        "cost_alerts": [],
    },
    config=config,
)

# Example output during execution:
# ⚠️ Cost alert: Session approaching cost ceiling ($3.52/$5.00)
# 🔄 Model fallback: claude-sonnet-4-20250514 → gpt-4o-mini
#    Reason: cost_threshold_95_percent
# 🔒 Content filtered: pii_redaction applied
Enter fullscreen mode Exit fullscreen mode

Step 6: Policy Hot-Reload

from langchain_gateway import GatewayAdmin

# Connect to gateway admin API
admin = GatewayAdmin(api_key=os.environ["LANGCHAIN_API_KEY"])

# Check current policy version
current = admin.get_active_policy("research-agents/production")
print(f"Active policy version: {current.version} (deployed {current.deployed_at})")

# Update cost ceiling without restarting agents
# This takes effect immediately for all sessions in this namespace
admin.update_policy(
    namespace="research-agents/production",
    updates={
        "policies.cost_control.max_cost_per_session": 10.00  # Increased ceiling
    },
    reason="Increased limit for complex research tasks",
)

# Verify the change
updated = admin.get_active_policy("research-agents/production")
print(f"New policy version: {updated.version}")

# Rollback if needed
# admin.rollback_policy("research-agents/production", to_version=current.version)
Enter fullscreen mode Exit fullscreen mode

Advanced Patterns: Combining Gateway with Existing LangGraph Features

The Gateway doesn't exist in isolation—it interacts with LangGraph's existing fault tolerance, checkpointing, and human-in-the-loop features. Understanding these interactions prevents subtle bugs and enables powerful combined patterns.

Gateway + LangGraph Retry Decorators

A common pitfall: if your agent code uses LangGraph's @retry decorator and the Gateway also implements retry logic (for model fallback), you can trigger retry storms. The solution is clear separation of concerns. Let the Gateway handle model-level failures (provider outages, rate limits) while your application code handles semantic failures (bad tool outputs, validation errors). Configure the Gateway's retry behavior explicitly and disable application-level retries for HTTP errors the Gateway already handles.

Gateway + Checkpointing for Cost Analysis

The Gateway exposes cost metrics per request, but correlating costs with specific agent decisions requires checkpoint integration. By enabling checkpoint cost attribution, you can query which graph branches are most expensive—invaluable for optimizing agents that explore multiple reasoning paths. This data flows into LangSmith dashboards, enabling queries like "which tool calls contribute most to session cost?"

Gateway + Human-in-the-Loop

A powerful pattern ties Gateway cost alerts to LangGraph's interrupt() API. When cumulative session cost exceeds a threshold, rather than hard-stopping or degrading the model, the Gateway can signal the agent to interrupt and request human approval before continuing. This preserves agent autonomy for routine operations while ensuring human oversight for unexpectedly expensive sessions.

# Policy configuration for HITL cost approval
# In gateway-policies.yaml:
#   - at_percent: 90
#     action: signal_interrupt
#     interrupt_type: "cost_approval_required"

# Agent code handling the interrupt
from langgraph.types import interrupt

def researcher_node(state: ResearchState):
    messages = state["messages"]

    try:
        response = llm_with_tools.invoke(messages)
    except GatewayCostInterrupt as e:
        # Gateway signaled we need approval to continue
        approval = interrupt({
            "type": "cost_approval",
            "current_cost": e.current_cost,
            "estimated_remaining": e.estimated_remaining,
            "message": f"Session has spent ${e.current_cost:.2f}. Approve additional ${e.estimated_remaining:.2f}?"
        })
        if approval.get("approved"):
            # Human approved - gateway will allow continued spending
            response = llm_with_tools.invoke(messages)
        else:
            return {"messages": [AIMessage(content="Research stopped by user due to cost concerns.")]}

    return {"messages": [response]}
Enter fullscreen mode Exit fullscreen mode

Anti-Patterns to Avoid

Several configurations cause problems in practice. Overly aggressive rate limits (especially max_tokens_per_minute set too low) cause agents to stall mid-reasoning, often leaving them in confused states when they resume. Misconfigured fallback chains can create infinite loops if the fallback model also triggers the original failure condition. And content filters that are too broad can strip essential context from responses, causing agents to lose track of their goals. Start permissive, monitor actual behavior, then tighten incrementally.

What This Means for Your Stack

Adopting the Gateway isn't an all-or-nothing proposition. The recommended path starts with observability-only mode: deploy the Gateway, route traffic through it, but disable all enforcement policies. This gives you visibility into what policies would trigger without affecting production behavior. Use this data to tune thresholds before enabling enforcement.

Hosted vs. Self-Hosted Decision Framework

Choose LangSmith-hosted for fastest time to value and when your data can traverse LangChain's infrastructure. Choose self-hosted (sidecar or standalone) for strict data residency requirements, latency-critical applications, or multi-cloud deployments where you need gateway instances in each cloud region.

Cost-Benefit Analysis

The Gateway adds infrastructure complexity and per-request latency. Is it worth it? LangChain claims 40% average cost reduction for high-volume customers, primarily from preventing runaway loops and routing low-stakes calls to cheaper models. For teams spending more than $1,000/month on LLM APIs, the savings typically justify the overhead within weeks.

Migration Checklist

Before deploying: audit existing LLM call patterns using LangSmith traces, identify tool loops that historically generated high call volumes, establish baseline cost metrics per session type, and define initial cost ceilings with generous margins. Deploy in observability-only mode for at least one week. Review triggered policy events. Adjust thresholds. Enable enforcement gradually, starting with logging-only actions before enabling throttling or hard stops.

Team Workflow Considerations

Who owns gateway policies? The most successful teams treat policies as platform infrastructure: the platform team owns the policy framework, default policies, and deployment mechanism, while agent developers propose policy changes for their specific agents via pull requests. This balances governance with developer velocity, similar to how networking policies work in Kubernetes environments.

Looking ahead, LangChain's blog hints at upcoming features: semantic caching that deduplicates equivalent requests across agents, cross-agent request batching for efficiency, and deeper integration with the emerging agentic patterns around multi-agent coordination. The Gateway is clearly positioned as the control plane for the next generation of production agent deployments.

What to Build This Week

Project: Cost-Aware Research Agent with Graceful Degradation

Build a research agent that demonstrates the full Gateway capability stack. The agent should accept open-ended research queries and work through them iteratively, using expensive models (Claude Sonnet, GPT-4) for synthesis and reasoning, but automatically degrading to cheaper models for routine operations.

Implement three policy tiers: a "generous" tier for internal research ($20 ceiling), a "standard" tier for customer-facing features ($5 ceiling), and a "strict" tier for demos ($1 ceiling). Add a human-in-the-loop approval gate when any session exceeds 75% of its budget.

Log all gateway events to a local file and build a simple dashboard (even a CLI printout works) showing: total cost across all sessions today, number of model fallbacks triggered, number of content filtering events, and any hard stops. Run the same complex research query under each policy tier and observe how the agent adapts its behavior—does it produce useful output even under strict constraints?

This exercise forces you to confront the real tradeoffs: how much does degraded model routing affect output quality? At what cost ceiling does the agent become useless? Where should the human approval threshold sit to balance autonomy with oversight? These are the questions every production agent team faces, and answering them empirically with the Gateway gives you a concrete foundation for production policy decisions.

Sources

- Agentic Engineering: How Swarms of AI Agents Are Redefining Software Engineering

This is part of the **Agentic Engineering Weekly* series — a deep-dive every Monday into the frameworks,
patterns, and techniques shaping the next generation of AI systems.*

Follow the Agentic Engineering Weekly series on Dev.to to catch every edition.

Building something agentic? Drop a comment — I'd love to feature reader projects.

Top comments (0)