Skip to main content

What it is

Prevention Config (displayed as Guards in the dashboard) lets you configure per-agent safety controls that run inside the LangSight SDK before each tool call is made. These controls are enforced at the call site — before the tool executes — not after the fact. Three guard types are available:

Loop Detection

Detect and stop agents that call the same tool repeatedly with the same arguments, alternating between two calls, or retrying a failing call without progress.

Budget Controls

Cap the LLM + tool cost or wall-clock time of a session. Soft alerts before the hard limit; hard terminate when the limit is reached.

Circuit Breaker

Prevent an agent from hammering a failing MCP server. Trip the circuit after N failures, hold it open during a cooldown period, then allow limited traffic to test recovery.

Where to find it

Agents (/agents) → click any agent name → Guards tab

Loop Detection

Loop detection fires before each tool call by checking three patterns in the current session’s call history:
PatternDescription
RepetitionSame tool called with identical arguments N times consecutively
Ping-pongAlternating between two tool+argument pairs repeatedly (A→B→A→B→A…)
Retry without progressSame tool failing with the same error N times in a row
When a pattern is detected, the call is blocked and a loop_detected health tag is applied to the session. Float normalization: Before hashing tool arguments, the loop detector rounds all float values to 6 decimal places. This prevents LLMs from bypassing loop detection through micro-variations in numeric arguments — for example, {"price": 1.0} and {"price": 0.999999} hash identically. Integer, boolean, string, and null values are unchanged. The normalization applies recursively to nested objects and arrays.

Configuration fields

enabled
boolean
default:"true"
Turn loop detection on or off for this agent.
threshold
integer
default:"5"
Number of consecutive repeat calls before the loop is detected and the action fires.
action
string
default:"warn"
What to do when a loop is detected.
  • warn — log the event and fire a LangSight alert, but allow the call to proceed. The session is tagged loop_detected.
  • terminate — block the call and terminate the session immediately. The session is tagged loop_detected.
max_steps
integer
Hard cap on total tool calls per session, regardless of repetition. When the session reaches this limit, the next call is blocked and the session is terminated. Leave unset for no limit.
The warn action is the recommended starting point. Use it to measure how frequently loops occur before switching to terminate. Switching to terminate too early can break agents that use intentional retry logic.

Budget Controls

Budget controls enforce cost and time limits per session. Limits are evaluated before each LLM call and tool call.
max_cost_usd
number
Hard cost cap per session in USD. When the running total of LLM cost + tool cost reaches this value, the session is terminated and tagged budget_exceeded. Leave unset for no limit.
soft_alert_threshold_usd
number
Warn when session cost reaches this value. A LangSight alert fires and the session is tagged budget_warning, but execution continues. Must be less than max_cost_usd.
max_wall_time_seconds
integer
Maximum session wall-clock time in seconds. When elapsed time exceeds this value, the next tool call is blocked and the session is terminated with budget_exceeded.
Cost estimates are computed from model pricing tables. Actual billed amounts may differ slightly depending on provider pricing changes and rounding. Use budget controls as a safety net, not a billing guarantee.

Unknown model fallback pricing

When a span’s model_id is not found in the pricing_table passed to LangSightClient, the SDK uses a conservative fallback cost instead of treating the cost as $0:
Rate
Input tokens$10.00 / 1M tokens
Output tokens$30.00 / 1M tokens
This prevents unknown or custom model names (preview endpoints, fine-tuned deployments, typos) from silently bypassing budget enforcement — a max_cost_usd limit would never fire if unknown model costs were treated as zero. When the fallback is used, the SDK logs a warning:
budget.unknown_model_cost_estimated model_id=my-custom-model estimated_cost_usd=0.004200
hint="Add this model to pricing_table= to get accurate cost tracking"
Add missing models to the pricing_table constructor parameter:
client = LangSightClient(
    url="http://localhost:8000",
    max_cost_usd=1.00,
    pricing_table={
        "my-custom-model": (5.00, 20.00),   # (input_per_1m_usd, output_per_1m_usd)
        "claude-sonnet-4-6": (3.00, 15.00),
        "gpt-4o": (2.50, 10.00),
    },
)
Built-in models (Claude, GPT-4o, Gemini families) use pricing seeded from the dashboard’s model pricing table and do not require manual entries.

Circuit Breaker

The circuit breaker prevents an agent from repeatedly calling a failing MCP server. It operates in three states:
StateBehaviour
ClosedNormal operation — calls are allowed through
OpenTripped after N failures — all calls to the server are blocked immediately
Half-openAfter the cooldown period — a limited number of calls are allowed through to test whether the server has recovered
If the half-open test calls succeed, the circuit closes and normal operation resumes. If they fail, the circuit re-opens and the cooldown timer resets.

Configuration fields

enabled
boolean
default:"true"
Turn the circuit breaker on or off for this agent.
open_after_failures
integer
default:"5"
Number of consecutive failures before the circuit trips to open state.
cooldown_seconds
integer
default:"30"
How long (in seconds) the circuit stays open before transitioning to half-open and allowing test traffic.
half_open_max_calls
integer
default:"3"
Maximum number of calls allowed in the half-open state to test whether the server has recovered.
The circuit breaker operates per-agent, per-server. An agent calling two servers has independent circuit breakers for each. One server failing does not trip the circuit for the other.

Config inheritance

Guards configuration uses a two-level inheritance model:

Project default

A single configuration that applies to all agents in the project. Set it in Settings → Projects → Prevention Default. All agents without an agent-specific override inherit the project default. Changes to the project default take effect on the next agent run — there is no restart required.

Agent override

When you save a config from the Guards tab for a specific agent, it creates an agent-level override. The Guards tab shows an “Agent-specific config” banner to indicate that this agent is no longer using the project default. Agent overrides take precedence over the project default in every field — there is no partial merge. If you set an agent override, the entire config (loop detection, budget, circuit breaker) comes from the override, not the project default.

Reset to default

The “Reset to project default” button in the Guards tab deletes the agent-specific override. On the next agent run, the agent falls back to the project default. The historical guard events (loop detections, budget alerts) are not deleted — they remain in the session history.

How to configure Guards

1

Open the agent detail panel

Go to Agents (/agents) and click the agent name you want to configure.
2

Select the Guards tab

The Guards tab shows the current configuration — either the project default (with a grey “Using project default” banner) or an agent-specific override (with an indigo “Agent-specific config” banner).
3

Configure the controls

Adjust the loop detection threshold, budget limits, and circuit breaker settings using the form fields. Each section can be enabled or disabled independently.
4

Save config

Click Save config. The configuration is stored immediately in PostgreSQL and applied on the next tool call from this agent.
Start with loop detection enabled=true, action=warn, threshold=5. Monitor the Agents table Loops column for a few days to understand your agents’ natural retry patterns before switching to action=terminate.

Data storage

Prevention configs are stored in the prevention_configs table in PostgreSQL:
CREATE TABLE prevention_configs (
    id                        UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    project_id                TEXT NOT NULL,
    agent_name                TEXT,        -- NULL = project default
    loop_enabled              BOOLEAN NOT NULL DEFAULT true,
    loop_threshold            INTEGER NOT NULL DEFAULT 5,
    loop_action               TEXT NOT NULL DEFAULT 'warn',
    loop_max_steps            INTEGER,
    budget_max_cost_usd       NUMERIC(10, 6),
    budget_soft_alert_usd     NUMERIC(10, 6),
    budget_max_wall_time_secs INTEGER,
    cb_enabled                BOOLEAN NOT NULL DEFAULT true,
    cb_open_after_failures    INTEGER NOT NULL DEFAULT 5,
    cb_cooldown_seconds       INTEGER NOT NULL DEFAULT 30,
    cb_half_open_max_calls    INTEGER NOT NULL DEFAULT 3,
    created_at                TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at                TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (project_id, agent_name)
);
A row with agent_name = NULL is the project default. Rows with a non-null agent_name are agent overrides.

API reference

Get agent config

GET /api/agents/{name}/prevention-config
Returns the effective config for the agent — agent override if one exists, otherwise the project default.
curl http://localhost:8000/api/agents/research-agent/prevention-config
{
  "agent_name": "research-agent",
  "is_agent_override": true,
  "loop_detection": {
    "enabled": true,
    "threshold": 3,
    "action": "terminate",
    "max_steps": 50
  },
  "budget": {
    "max_cost_usd": 0.50,
    "soft_alert_threshold_usd": 0.40,
    "max_wall_time_seconds": 120
  },
  "circuit_breaker": {
    "enabled": true,
    "open_after_failures": 5,
    "cooldown_seconds": 30,
    "half_open_max_calls": 3
  }
}

Save agent config

PUT /api/agents/{name}/prevention-config
Creates or replaces the agent-specific override. Send the full config object — partial updates are not supported.
curl -X PUT http://localhost:8000/api/agents/research-agent/prevention-config \
  -H "Content-Type: application/json" \
  -d '{
    "loop_detection": {
      "enabled": true,
      "threshold": 3,
      "action": "terminate",
      "max_steps": 50
    },
    "budget": {
      "max_cost_usd": 0.50,
      "soft_alert_threshold_usd": 0.40,
      "max_wall_time_seconds": 120
    },
    "circuit_breaker": {
      "enabled": true,
      "open_after_failures": 5,
      "cooldown_seconds": 30,
      "half_open_max_calls": 3
    }
  }'

Reset to project default

DELETE /api/agents/{name}/prevention-config
Deletes the agent-specific override. The agent falls back to the project default on the next run.

Get project default

GET /api/projects/prevention-config

Save project default

PUT /api/projects/prevention-config
Same request body as the agent config endpoint. Applies to all agents without an agent-specific override.

Session health tags

Prevention Config actions produce the following session health tags, which appear in the Agents → Sessions tab and the session detail page:
Health tagCause
loop_detectedLoop detection fired (warn or terminate action)
budget_warningSession cost reached soft_alert_threshold_usd
budget_exceededSession cost or wall time reached the hard limit
circuit_breaker_openA call was blocked because the circuit is in the open state
For definitions of all health tags, see Session Health.
  • Agents — agent table, health scores, loop detection count column
  • Session Health — full health tag reference
  • Agent SLOs — reliability targets for agents
  • Costs — session cost calculation and model pricing