gen-ai: add run guardrail span and security finding - #427
Conversation
Reproduces open-telemetry#262 (original author Nagkumar Arkalgud), rebased onto current main. Co-authored-by: Nagkumar Arkalgud~ Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
- Drop gen_ai.security.guardrail.id (redundant with .name; R424) - Drop gen_ai.security.guardrail.version (R440) - Drop gen_ai.security.guardrail.provider.name; reuse gen_ai.provider.name (R448) - Drop gen_ai.security.finding.evidence — carries customer content, GDPR/DLP (R658/R666) - Remove span-hierarchy requirement language (R666) - Regenerate docs, reports, and openai scenario data Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Pull request dashboard statusWaiting on the author · refreshed 2026-08-24 09:32 UTC Resolve merge conflicts. Respond to 1 review item (e.g. link a commit, explain why not, ask a follow-up):
Status above doesn't look right?
|
There was a problem hiding this comment.
Pull request overview
This PR introduces first-class GenAI security guardrail observability to the semantic conventions, adding two new run_guardrail span types (client + internal) and a gen_ai.security.finding event, plus the corresponding registry attributes and OpenAI reference coverage/reporting to demonstrate capturability.
Changes:
- Add
gen_ai.run_guardrail.{client,internal}span definitions and agen_ai.security.findingevent, with a newgen_ai.security.*attribute set in the registry. - Update the reference pipeline (model/spec loading, classification, report linking, and ordering) to recognize and report the new spans/events.
- Extend the OpenAI reference scenario + generated reports/data to emit the new spans and event.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| reference/src/semconv_genai/semconv_model.py | Registers the new guardrail span specs and security finding event spec for reference evaluation. |
| reference/src/semconv_genai/report.py | Adds doc links for the new span/event types in generated reference reports. |
| reference/src/semconv_genai/data_files.py | Adds ordering for new span/event types in reference report generation. |
| reference/src/semconv_genai/classify.py | Disambiguates run_guardrail client vs internal span types during classification. |
| reference/scenarios/openai/scenario.py | Emits guardrail client/internal spans and gen_ai.security.finding event in the OpenAI scenario. |
| reference/scenarios/openai/data.json | Captures observed attribute coverage for the new span/event types in the OpenAI scenario. |
| reference/reports/run-guardrail-internal-span.md | New generated coverage report for internal guardrail spans. |
| reference/reports/run-guardrail-client-span.md | New generated coverage report for client guardrail spans. |
| reference/reports/gen-ai-security-finding-event.md | New generated coverage report for the security finding event. |
| reference/README.md | Lists the new guardrail span reports and the new event report. |
| model/gen-ai/spans.yaml | Adds shared attribute group + defines gen_ai.run_guardrail.{client,internal} spans. |
| model/gen-ai/registry.yaml | Adds gen_ai.security.* attributes and registers run_guardrail as an operation name. |
| model/gen-ai/gen-ai-security-content.json | Introduces a JSON schema placeholder for guardrail content value attributes. |
| model/gen-ai/events.yaml | Adds the gen_ai.security.finding event definition and its attribute set. |
| docs/registry/attributes/gen-ai.md | Regenerated attribute registry docs including the new gen_ai.security.* attributes. |
| docs/gen-ai/README.md | Adds the new “Security” documentation page to the GenAI docs index. |
| docs/gen-ai/openai.md | Adds run_guardrail to operation-name guidance tables for OpenAI docs. |
| docs/gen-ai/mcp.md | Adds run_guardrail to operation-name guidance tables for MCP docs. |
| docs/gen-ai/gen-ai-spans.md | Adds run_guardrail to operation-name guidance tables for span docs. |
| docs/gen-ai/gen-ai-security.md | New documentation page for guardrail spans + finding event (weaver-generated sections). |
| docs/gen-ai/gen-ai-metrics.md | Adds run_guardrail to operation-name guidance tables for metrics docs. |
| docs/gen-ai/gen-ai-events.md | Adds the gen_ai.security.finding event section and TOC entry. |
| docs/gen-ai/gen-ai-agent-spans.md | Adds run_guardrail to operation-name guidance tables for agent span docs. |
| docs/gen-ai/azure-ai-inference.md | Adds run_guardrail to operation-name guidance tables for Azure AI Inference docs. |
| docs/gen-ai/aws-bedrock.md | Adds run_guardrail to operation-name guidance tables for AWS Bedrock docs. |
| docs/gen-ai/anthropic.md | Adds run_guardrail to operation-name guidance tables for Anthropic docs. |
| changelog.d/NNN.component.md | Adds a Towncrier fragment describing the new security guardrail conventions. |
| { | ||
| "description": "Represents content evaluated or produced by a security guardrail.", | ||
| "title": "SecurityGuardrailContent" | ||
| } |
| @@ -0,0 +1 @@ | |||
| Add GenAI security guardrail span conventions and a security finding event. | |||
|
Hi @habibam — just a friendly reminder that this pull request is waiting on you. The dashboard status comment has the open items and is kept current.
|
…l' framing Restructure the guardrail attributes into a layered namespace agreed at the Aug-7 GenAI SIG: a generic base tier (gen_ai.guardrail.component.name, .verdict.*, .action.*, .target.*) that any guardrail instrumentation can populate, and an opt-in security layer (gen_ai.guardrail.security.*: policy, content, risk, external_finding_id). Rename risk.finding -> risk.category since its values are risk categories (OWASP LLM Top-10), and rename the finding event to gen_ai.guardrail.security.finding. Stop describing the guardrail mechanism as a 'security guardrail' in the base tier: generic auto-instrumentation cannot know whether a guardrail is security-related, so the span, operation, component, and verdict now read as a plain 'guardrail'. 'security' is kept only for the genuine security layer (findings, policies, risk, external systems). Rename the changelog fragment to the successor PR number. Regenerates registry docs, embedded tables, and reference reports. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
|
Saw the open item in your description — a real instrumented guardrail library in the reference scenarios, rather than hand-authored spans. I have one running in #368. It currently sits on a draft PR of mine, but nothing in the scenario is specific to my proposal — it is just a guardrail library being instrumented for real. Happy to move it here, or leave it where it is and reference it from this PR. Whichever is less work for you. One practical note while you are in here: EasyCLA is still failing on this PR, and reviewers generally will not start until that goes green. |
…erlay Address review feedback to keep the guardrail attribute set minimal and make the security-specific fields separable from the base guardrail span. - Drop gen_ai.guardrail.security.policy.name and .policy.version. policy.id (with the optional policy.rule.id) is enough to correlate a verdict to the policy that produced it; the name/version pair added surface without a capture story. - Split the run_guardrail attributes into a base group (attributes.gen_ai.run_guardrail.common) and a separable security overlay (attributes.gen_ai.guardrail.security), so generic guardrail instrumentation can emit the base span without the security fields. Move gen_ai.conversation.id into the base group. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
…erlay Address review feedback to keep the guardrail attribute set minimal and make the security-specific fields separable from the base guardrail span. - Drop gen_ai.guardrail.security.policy.name and .policy.version. policy.id (with the optional policy.rule.id) is enough to correlate a verdict to the policy that produced it; the name/version pair added surface without a capture story. - Split the run_guardrail attributes into a base group (attributes.gen_ai.run_guardrail.common) and a separable security overlay (attributes.gen_ai.guardrail.security), so generic guardrail instrumentation can emit the base span without the security fields. Move gen_ai.conversation.id into the base group. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Update the hand-authored openai security-guardrail scenario to drop the gen_ai.guardrail.security.policy.name / .policy.version attributes and regenerate its data.json to match the slimmed model. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Add a runnable scenario that wraps the real openai-guardrails framework and emits the base gen_ai.run_guardrail.internal span from framework-owned runtime state, proving the base tier is capturable by generic instrumentation. It intentionally does not emit the security overlay or the finding event: the framework runtime exposes no policy identity, external finding id, or standardized risk class, which is the concrete capture gap that motivates keeping the security overlay separable. It emits only guardrail spans; the delegated chat inference span belongs to the openai library. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Regenerated with 'uv run update-reports'. The base run_guardrail attributes now show coverage from both openai and openai-guardrails; the security overlay and finding event remain openai-only, matching the documented capture gap. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Integrate the upstream conformance-tooling refactor with the GenAI security-guardrail conventions. semconv_model.py: upstream rewrite plus the run_guardrail spans and finding event; classify.py: accept deletion; openai/data.json: upstream keys plus guardrail entries; regenerate docs; add openai-guardrails/conformance.yaml. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
The gen-ai-events.md table-of-contents link for gen_ai.guardrail.security.finding still pointed at the pre-rename anchor (#event-gen_aisecurityfinding). Point it at the actual heading anchor (#event-gen_aiguardrailsecurityfinding) so the link checker passes. Signed-off-by: Habiba Mohamed <habibam314@gmail.com>
Description
Defines semantic conventions for observing GenAI guardrails policy, security findings and other controls that inspect GenAI content or actions before, during, or after a GenAI operation.
Adds:
gen_ai.run_guardrail.clientfor out-of-process guardrail services.gen_ai.run_guardrail.internalfor in-process guardrail checks.gen_ai.security.findingevent for findings produced by a guardrail run.gen_ai.security.guardrail.*(evaluating service/component),gen_ai.security.verdict.*(result returned),gen_ai.security.action.type(caller enforcement),
gen_ai.security.policy.*/gen_ai.security.policy.rule.id(policy/rule attribution),gen_ai.security.risk.*(classification/scoring), andgen_ai.security.external_finding_id(SIEM correlation).Successor to #262 by Nagkumar Arkalgud.
Motivation
User journey: security investigation and incident triage. When a GenAI application blocks, modifies, or escalates a request, responders need to answer from telemetry alone which guardrail ran, what it evaluated, what verdict it returned, what the caller actually enforced, which policy/rule fired, and how to correlate the finding with the external security system (SIEM). Also supports sampling decisions (verdict/action) and audit.
Separating verdict (the guardrail's judgment) from action (the caller's enforcement) lets telemetry represent cases where a guardrail returns one result but the caller enforces another (e.g. verdict
deny, actionescalate).Prior art: Google's Model Armor emits these guardrail spans in production (public reference).
Content-safety services, DLP filters, prompt-injection detectors, and policy engines all expose equivalent concepts (guardrail identity, verdict, policy, finding) today in vendor-specific forms.
Prototype
The reference scenarios under
reference/scenarios/openai/are updated to emit both therun_guardrailclient/internal spans and thegen_ai.security.findingevent, with generated reports underreference/reports/.Caveat / follow-up: the current scenario is hand-authored rather than produced by an auto-instrumented guardrail library. Per @lmolkova top level review on #262, a survey of instrumentable open-source server-side guardrail libraries and adding a real one to the reference scenarios is the main remaining work item and is tracked as an open question tobe addressed at the SIG meeting.
Checklist
changelog.d/