Output Controls
Financial Compliance
financial-compliance checks model answers for financial phrases. It blocks an answer that contains a phrase you list, such as "guaranteed return", and puts a disclaimer in front of an answer that looks like investment advice.
It does not check that a financial statement is correct or suitable for a person, and it does not make you compliant with a regulation. It runs only with stream: false.
Configuration
Save this as policy-config.yaml and apply it to a test agent with the config-first workflow.
pack:
name: financial-compliance-example
version: 1.0.0
enabled: true
policies:
chain:
- financial-compliance
policy:
financial-compliance:
blocked_patterns:
- you should buy
- you should sell
- guaranteed return
- strong buy
- strong sell
required_disclaimers:
- This is not financial advice.
- >-
Consult a qualified financial advisor before making
investment decisions.Verify the result
Use controlled provider responses: telling a model to return a phrase does not guarantee that it does.
| Provider response | Result |
|---|---|
This has a guaranteed return. | Blocked with financial.blocked. The client gets no text. |
Buy a ticket. | Disclaimer added with financial.disclaimer_injected, a false match |
Hello. | Returned unchanged with financial.clean |
Compare the client response with the nested result in the runtime event.
Fields
| Field | Type | Default | Description |
|---|---|---|---|
blocked_patterns | list of strings | [] | Literal substrings that block the answer. Case does not matter. Not regular expressions. |
required_disclaimers | list of strings | [] | Lines joined with line breaks and put before an answer that looks like advice. Empty uses This is not financial advice. |
How it works
- The gateway takes the text of the complete model response.
- The control lowercases it and looks for each
blocked_patternsentry. A match blocks withfinancial.blocked. - Otherwise, text that contains
buy,sell,you should invest,guaranteed returns,target price,strong buy, orstrong sellcounts as advice. - Advice that does not already start with the disclaimer gets the disclaimer and two line breaks in front of it, with
financial.disclaimer_injected. - Anything else is returned with
financial.clean.
The details contain looks_like_advice and disclaimer_injected, or blocked: true.
Phase and verdicts
| Item | Value |
|---|---|
| Phase | output |
| Request families | Chat Completions, Completions, Responses, Messages |
| Verdicts | allow, block |
| Reason codes | financial.clean, financial.disclaimer_injected, financial.blocked |
Examples
Disclaimer only:
policy:
financial-compliance:
required_disclaimers:
- This is not financial advice.
- Review any financial decisions with a licensed advisor.Block strong recommendations and price targets:
policy:
financial-compliance:
blocked_patterns:
- you should buy
- target price
- guaranteed return
required_disclaimers:
- This is not financial advice.Limits and failure behavior
- A block returns HTTP
400with error codecontent_policy_violation. - The advice check matches substrings:
buy a ticketandsell your carget a disclaimer. - The control compares the start of the answer with your full disclaimer. An answer that starts with a different disclaimer still gets yours.
blocked_patternsalso matches inside longer words and in quoted or negated text:strong buymatchesthis is not a strong buy.- With
stream: true, the gateway buffers the response but does not run the control. - There is no
actionfield. For a disclaimer-only setup, leaveblocked_patternsempty. - A
whencondition does not limit this control. Use routes.
Next steps
- MNPI Filter: phrases that suggest non-public information.
- Response Rewriter: your own text rules for responses.
- Investigate a Blocked Request: trace a
financial.blockeddecision.