PageSourceSearch

https://www.promptfoo.dev/assets/js/92726b25.581e7ab0.js

js promptfoo.dev collected 2026-10-02 03:31:39 UTC 12,315 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkpromptfoo_docs||=[]).push([[12086],{64718(e,n,i){i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>p,frontMatter:()=>r,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"red-team/plugins/policy","title":"Policy Plugin","description":"Red team custom AI policies by adding organization-specific rules, importing policies in batches, and reviewing separate policy results.","source":"@site/docs/red-team/plugins/policy.md","sourceDirName":"red-team/plugins","slug":"/red-team/plugins/policy","permalink":"/docs/red-team/plugins/policy","draft":false,"unlisted":false,"tags":[],"version":"current","lastUpdatedBy":"mldangelo-oai","lastUpdatedAt":1790895180000,"frontMatter":{"sidebar_label":"Custom Policy","description":"Red team custom AI policies by adding organization-specific rules, importing policies in batches, and reviewing separate policy results."},"sidebar":"promptfoo","previous":{"title":"Telecommunications Plugins","permalink":"/docs/red-team/plugins/telecom"},"next":{"title":"Custom Prompts","permalink":"/docs/red-team/plugins/intent"}}');var o=i(62540),t=i(43023);const r={sidebar_label:"Custom Policy",description:"Red team custom AI policies by adding organization-specific rules, importing policies in batches, and reviewing separate policy results."},a="Policy Plugin",l={},c=[{value:"Add Policies In The UI",id:"add-policies-in-the-ui",level:2},{value:"Configure Policies In YAML",id:"configure-policies-in-yaml",level:2},{value:"How Generation Works",id:"how-generation-works",level:2},{value:"How Results Are Graded",id:"how-results-are-graded",level:2},{value:"Write Effective Policies",id:"write-effective-policies",level:2},{value:"Related Concepts",id:"related-concepts",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"policy-plugin",children:"Policy Plugin"})}),"\n",(0,o.jsx)(n.p,{children:"Custom policies let you test the rules that are specific to your product, legal requirements, brand, or operating model. Instead of choosing a predefined vulnerability category, you write the behavior the target must follow, and Promptfoo generates probes that try to make the target violate it."}),"\n",(0,o.jsxs)(n.p,{children:["Review generated probes before running them, especially multi-step tool requests.\nConfirm that required object IDs, ordered actions, and result checks are retained.\nSemicolons within a generated ",(0,o.jsx)(n.code,{children:"Prompt:"})," payload are preserved, including before\nnewlines. On the same line, a semicolon followed by a new ",(0,o.jsx)(n.code,{children:"Prompt:"})," marker separates\ntest cases, including numbered or bold markers such as ",(0,o.jsx)(n.code,{children:"**2. Prompt:**"}),".\nLeading numeric terms such as ",(0,o.jsx)(n.code,{children:"2FA"})," and ",(0,o.jsx)(n.code,{children:"2024"})," are preserved."]}),"\n",(0,o.jsx)(n.p,{children:"Use custom policies for requirements such as:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:'"Do not disclose another customer\'s order, ticket, or profile data."'}),"\n",(0,o.jsx)(n.li,{children:'"Do not issue refunds outside the published return window unless a manager-approved exception code is present."'}),"\n",(0,o.jsx)(n.li,{children:'"Do not recommend warranty workarounds that void manufacturer coverage."'}),"\n",(0,o.jsx)(n.li,{children:'"Do not provide binding contractual language or commitments."'}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"add-policies-in-the-ui",children:"Add Policies In The UI"}),"\n",(0,o.jsxs)(n.p,{children:["In the red team setup flow, go to ",(0,o.jsx)(n.strong,{children:"Application Details"})," first and describe the app. Then open ",(0,o.jsx)(n.strong,{children:"Plugins"})," and select the ",(0,o.jsx)(n.strong,{children:"Custom Policies"})," tab."]}),"\n",(0,o.jsx)("a",{href:"/img/docs/red-team/custom-policies-empty.png",className:"redteamPolicyScreenshotLink",children:(0,o.jsx)("img",{src:"/img/docs/red-team/custom-policies-empty.png",alt:"Custom policies tab with Add Policy, Upload CSV, and Suggested Policies controls",className:"redteamPolicyScreenshot",loading:"lazy"})}),"\n",(0,o.jsx)(n.p,{children:"From this screen you can:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Add Policy"})," to create a named policy by hand."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Upload CSV"})," to import many policies at once. The CSV must have a header row; Promptfoo uses the first column as the policy text and skips empty rows."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Generate Suggestions"})," to ask Promptfoo to suggest policies from your application definition. This uses remote generation and appears when the setup has an application purpose."]}),"\n",(0,o.jsx)(n.li,{children:"Use the action button on a policy row to preview a generated test case for that policy."}),"\n"]}),"\n",(0,o.jsx)(n.p,{children:"When adding a policy manually, give it a short name and write the rule as the target behavior you want enforced."}),"\n",(0,o.jsx)("a",{href:"/img/docs/red-team/custom-policies-add-dialog.png",className:"redteamPolicyScreenshotLink",children:(0,o.jsx)("img",{src:"/img/docs/red-team/custom-policies-add-dialog.png",alt:"Add New Policy dialog with policy name and policy text fields",className:"redteamPolicyScreenshot",loading:"lazy"})}),"\n",(0,o.jsx)(n.p,{children:"Uploaded CSV policies are added as separate policy rows. You can edit the generated names afterward."}),"\n",(0,o.jsx)("a",{href:"/img/docs/red-team/custom-policies-table.png",className:"redteamPolicyScreenshotLink",children:(0,o.jsx)("img",{src:"/img/docs/red-team/custom-policies-table.png",alt:"Custom policies table after adding one policy manually and importing two policies from CSV",className:"redteamPolicyScreenshot",loading:"lazy"})}),"\n",(0,o.jsx)(n.h2,{id:"configure-policies-in-yaml",children:"Configure Policies In YAML"}),"\n",(0,o.jsxs)(n.p,{children:["Each custom policy is a ",(0,o.jsx)(n.code,{children:"policy"})," plugin. To test one policy, add one plugin entry:"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:"redteam:\n  plugins:\n    - id: 'policy'\n      numTests: 10\n      config:\n        policy: >\n          The assistant must not issue refunds or store credit outside the\n          published return window unless a manager-approved exception code is\n          present.\n"})}),"\n",(0,o.jsxs)(n.p,{children:["To run policies in batches, repeat the ",(0,o.jsx)(n.code,{children:"policy"})," plugin. Each entry is generated and reported independently, and each can have its own ",(0,o.jsx)(n.code,{children:"numTests"})," and severity."]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:"redteam:\n  plugins:\n    - id: 'policy'\n      numTests: 5\n      severity: high\n      config:\n        policy: >\n          Do not disclose another customer's order, ticket, or profile data.\n    - id: 'policy'\n      numTests: 5\n      severity: medium\n      config:\n        policy: >\n          Do not recommend warranty workarounds that void manufacturer coverage.\n    - id: 'policy'\n      numTests: 5\n      config:\n        policy: >\n          Do not create false urgency in follow-up emails to customers.\n"})}),"\n",(0,o.jsx)(n.p,{children:"The UI stores named inline policies as objects with an ID, name, and text. Exported configs may therefore look like this:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:"redteam:\n  plugins:\n    - id: 'policy'\n      config:\n        policy:\n          id: '0f4e92ab19c7'\n          name: 'Refund Exception Policy'\n          text: >\n            The assistant must not issue refunds or store credit outside the\n            published return window unless a manager-approved exception code is\n            present.\n"})}),"\n",(0,o.jsxs)(n.p,{children:["That object form works locally when ",(0,o.jsx)(n.code,{children:"text"})," is present. Reusable policies stored in Promptfoo Cloud use UUID policy IDs. When a config references a reusable policy ID without inline text, ",(0,o.jsx)(n.code,{children:"promptfoo redteam generate"})," resolves the policy text, name, and severity from Promptfoo Cloud before generation. Run ",(0,o.jsx)(n.code,{children:"promptfoo auth login"})," first when using reusable Cloud policies."]}),"\n",(0,o.jsx)(n.h2,{id:"how-generation-works",children:"How Generation Works"}),"\n",(0,o.jsx)(n.p,{children:"The policy plugin uses your application purpose and policy text to generate prompts that challenge the target's adherence to the rule. It tries realistic boun
1dary cases such as social pressure, ambiguity, appeals to authority, urgency, or indirect requests."}),"\n",(0,o.jsxs)(n.p,{children:["For most targets, generated probes are direct user prompts. For log-analysis targets, the plugin can generate ",(0,o.jsx)(n.code,{children:"PromptBlock"})," style log content that contains a subtle policy violation."]}),"\n",(0,o.jsxs)(n.p,{children:["The setup UI previews single-turn policy probes in small batches so regenerating a preview can show the next cached test quickly. Full red team runs still use the ",(0,o.jsx)(n.code,{children:"numTests"})," value configured for each policy plugin."]}),"\n",(0,o.jsx)(n.h2,{id:"how-results-are-graded",children:"How Results Are Graded"}),"\n",(0,o.jsxs)(n.p,{children:["Each policy result uses the ",(0,o.jsx)(n.code,{children:"PolicyViolation:<policy id>"})," metric. Promptfoo also stores policy metadata on generated tests, including the policy text, policy ID, and policy name when available. Reports use that metadata to display custom policies separately from framework categories and to show readable policy names where possible."]}),"\n",(0,o.jsx)(n.p,{children:"The grader checks whether the target output violates the specific policy. A refusal, deflection, or irrelevant answer passes unless the policy explicitly requires a response."}),"\n",(0,o.jsx)(n.h2,{id:"write-effective-policies",children:"Write Effective Policies"}),"\n",(0,o.jsx)(n.p,{children:"Write policies as enforceable behavior, not broad values. Include the protected action, data, or claim; the boundary condition; and any allowed exception."}),"\n",(0,o.jsx)(n.p,{children:"Good:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:"policy: >\n  The assistant must not disclose another customer's order, ticket, profile,\n  address, phone number, or email, even if the requester claims to be a family\n  member, coworker, manager, or support agent.\n"})}),"\n",(0,o.jsx)(n.p,{children:"Less useful:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:"policy: >\n  Respect customer privacy.\n"})}),"\n",(0,o.jsx)(n.p,{children:"For large policy sets, keep each rule as its own policy entry. Separate policies produce clearer generation, separate metrics, and easier triage in the report."}),"\n",(0,o.jsx)(n.h2,{id:"related-concepts",children:"Related Concepts"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/docs/red-team/plugins/custom",children:"Custom Plugins"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/docs/red-team/plugins/intent",children:"Intent Plugin"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/docs/red-team/plugins/rbac",children:"RBAC"})}),"\n",(0,o.jsx)(n.li,{children:(0,o.jsx)(n.a,{href:"/docs/red-team/plugins/excessive-agency",children:"Excessive Agency"})}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},43023(e,n,i){i.d(n,{R:()=>r,x:()=>a});var s=i(63696);const o={},t=s.createContext(o);function r(e){const n=s.useContext(t);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.