Safety Shields Guide

August 3, 2026 · View on GitHub

This guide covers LCORE-owned safety shields: how to configure them in lightspeed-stack.yaml, which shield types are supported, how they apply on request endpoints, how to list them via /v1/shields, and how shield_ids request overrides work.

Important

Shields used by /query, /streaming_query, /responses, and /rlsapi are owned and configured by Lightspeed Core Stack, not by the Llama Stack / OGX Safety or Moderations APIs anymore. Do not configure LCORE request guardrails under providers.safety / registered_resources.shields in the stack run.yaml.



Introduction

LCORE shields are guardrails declared in the Lightspeed Core Stack configuration. Each entry has:

FieldMeaning
nameUnique shield name used in /v1/shields and in shield_ids overrides
provider_idShield type discriminator (question_validity or redaction)
configType-specific settings

Names must be unique across the shields list.

Configuration

Add a shields list to lightspeed-stack.yaml:

shields:
  - name: topic-guard
    provider_id: question_validity
    config:
      model_id: openai/gpt-4o-mini
      # optional:
      # model_prompt: "..."
      # invalid_question_response: "..."

  - name: pii-redaction
    provider_id: redaction
    config:
      rules:
        - pattern: '\b\d{3}-\d{2}-\d{4}\b'
          replacement: '[REDACTED]'
      case_sensitive: false

See examples/lightspeed-stack-shields.yaml for a complete example.

Supported shield types

provider_idPurposeTypical application
question_validityClassify whether the user question is in-topic; reject off-topic input with a fixed replyAgent capability on agent-based endpoints; also considered by direct-run input moderation
redactionRegex-based PII / sensitive-data redaction of model messagesAgent capability on agent-based endpoints

question_validity

Config fieldRequiredDescription
model_idYesModel used for the validity check (for example openai/gpt-4o-mini)
model_promptNoClassifier prompt (has a built-in default)
invalid_question_responseNoReply returned when the question is rejected

redaction

Config fieldRequiredDescription
rulesNo (default [])Ordered list of {pattern, replacement, case_sensitive?} rules
case_sensitiveNo (default false)Global case sensitivity when a rule does not override it

Invalid regex patterns are rejected at configuration load time.

How shields apply at runtime

The same shield logic (question_validity and redaction) is used on both agent-based and responses-based endpoints; only the integration point differs.

Agent-based endpoints

On agent-based endpoints (for example /v1/query and /v1/streaming_query), shields run as pydantic-ai capabilities attached when the agent is built. Those capabilities wrap the agent pipeline — for example rejecting off-topic questions or redacting PII from model messages — using the configured shields.

Responses-based endpoints

On pure responses-based endpoints (for example /v1/responses and /v1/infer), there is no agent capability layer. Instead, LCORE runs the same core shield functionality directly through a custom API (run_shield_moderation) before each request. When moderation blocks the input, the endpoint returns a refusal (and may persist the blocked turn) without calling the model.

Per-endpoint behavior

EndpointHow shields runshield_ids
POST /v1/queryAgent capabilities (via build_agent)Yes; subject to disable_shield_ids_override
POST /v1/streaming_queryAgent capabilities (via build_agent)Yes; subject to disable_shield_ids_override
POST /v1/responsesDirect custom API before the request; agent capabilities when the request uses the agent pathYes (shield_ids is an LCORE extension). Override disable gate is not applied on this endpoint today
POST /v1/infer (rlsapi v1)Direct custom API before the requestNo shield_ids field — always uses all configured shields

Listing shields (GET /v1/shields)

GET /v1/shields returns shields from LCORE configuration only. It does not call Llama Stack / OGX to list Safety or Moderations resources.

Each catalog entry has this shape:

FieldDescription
nameConfigured shield name
provider_idquestion_validity or redaction
typeAlways "shield"
configType-specific shield configuration

Example response body:

{
  "shields": [
    {
      "name": "pii-redaction",
      "provider_id": "redaction",
      "type": "shield",
      "config": {
        "rules": [
          {
            "pattern": "\\d+",
            "replacement": "[NUM]",
            "case_sensitive": null
          }
        ],
        "case_sensitive": false
      }
    }
  ]
}

Request overrides (shield_ids)

Optional request field on /v1/query, /v1/streaming_query, and /v1/responses:

shield_ids valueBehavior
omitted / nullApply all configured shields
[]Apply no shields
["topic-guard", ...]Apply only those names; unknown IDs yield HTTP 404

Values must match configured name strings (as returned by GET /v1/shields), not Llama Stack shield resource names.

Example:

{
  "query": "How do I scale a Deployment?",
  "shield_ids": ["topic-guard"]
}

Disabling overrides

To ignore client-provided shield_ids on /v1/query and /v1/streaming_query (always use the configured set), set:

customization:
  disable_shield_ids_override: true

When this flag is set and the client still sends shield_ids (including an empty list), the endpoint returns HTTP 422.

References