Evaluators are YAML files under evaluators/agent/ or evaluators/mcp/ at the repo root. Adding one needs no code. After adding or editing, run npm run build:catalog to rebuild the skill catalogs.
schema_version: 1id: system-prompt-leakagename: System Prompt Leakageseverity: critical # critical | high | medium | lowstandards: owasp-llm: LLM07 atlas: AML.T0056description: One-line summary for judges and contributorspass_criteria: |- - Bullet list of safe behaviorsfail_criteria: |- - Bullet list of vulnerable behaviorspatterns: - name: Pattern label template: Attack prompt text. Use {{placeholder}} for LLM-filled variables.
npm run validate:skills # check frontmatter against the Zod schemanpm run build:catalog:check # verify the catalog is up to date
Both run on pre-commit via Husky. validate:skills checks frontmatter against its own Zod schema, which is a separate, hand-maintained copy of the runtime loader’s schema. When you add a new standards key, update both so the check and the engine stay in sync.
{"docsConfig":{"theme":"aspen","$schema":"https://mintlify.com/docs.json","name":"Opfor","colors":{"primary":"#ff4d4f","light":"#ff7875","dark":"#d9363e"},"logo":{"light":"https://mintcdn.com/keyvaluesoftwaresystems/4m7L9sshK3C1tAuP/logo/Opfor_black.svg?fit=max\u0026auto=format\u0026n=4m7L9sshK3C1tAuP\u0026q=85\u0026s=832fbfe414f9908f90a90011fa48eb8e","dark":"https://mintcdn.com/keyvaluesoftwaresystems/4m7L9sshK3C1tAuP/logo/Opfor_white.svg?fit=max\u0026auto=format\u0026n=4m7L9sshK3C1tAuP\u0026q=85\u0026s=4072392cc08d6c6d1b93537518a6795f"},"favicon":"https://mintcdn.com/keyvaluesoftwaresystems/4m7L9sshK3C1tAuP/favicon.svg?fit=max\u0026auto=format\u0026n=4m7L9sshK3C1tAuP\u0026q=85\u0026s=389eef865e0935767cf807b65d9576ba","navbar":{"links":[{"href":"https://github.com/KeyValueSoftwareSystems/agent-opfor","label":"GitHub"}],"primary":{"type":"button","label":"Get Started","href":"/get-started/quickstart"}},"footer":{"socials":{"github":"https://github.com/KeyValueSoftwareSystems/agent-opfor"},"links":[{"header":"Package","items":[{"label":"CLI on npm","href":"https://www.npmjs.com/package/@keyvaluesystems/agent-opfor-cli"},{"label":"SDK on npm","href":"https://www.npmjs.com/package/@keyvaluesystems/agent-opfor-sdk"},{"label":"MCP on npm","href":"https://www.npmjs.com/package/@keyvaluesystems/agent-opfor-mcp"}]},{"header":"Links","items":[{"label":"Website","href":"https://agentopfor.ai"},{"label":"GitHub","href":"https://github.com/KeyValueSoftwareSystems/agent-opfor"}]}]},"contextual":{"options":["copy","view","chatgpt","claude"],"display":"header"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/KeyValueSoftwareSystems/agent-opfor"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"keyvaluesoftwaresystems","hasAudioNarration":false,"actualSubdomain":"keyvaluesoftwaresystems","customDomains":["docs.agentopfor.ai"],"gitSource":{"type":"github","owner":"keyvaluesoftwaresystems","repo":"agent-opfor-docs","deployBranch":"master","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6ae95acf46eff8e14e018684:success","clientVersion":"0.0.4124","searchFilterCounts":[{"language":"default","tag":"Reference","count":4},{"language":"default","tag":"CLI","count":3},{"language":"default","tag":"Evaluators \u0026 Suites","count":3},{"language":"default","tag":"Get Started","count":3},{"language":"default","tag":"Browser Extension","count":1},{"language":"default","tag":"MCP Server","count":1},{"language":"default","tag":"SDK","count":1},{"language":"default","tag":"Skills","count":1},{"language":"default","tag":"Trace-aware Testing","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"evaluators/authoring","slug":"/evaluators/authoring","pageMetadata":{"title":"Authoring evaluators","description":"Add a new evaluator — no TypeScript needed.","href":"/evaluators/authoring"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Add a new evaluator — no TypeScript needed.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,p:`p`,pre:`pre`,span:`span`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,..._provideComponents(),...props.components},{CodeBlock,Heading,Table,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Table)_missingMdxReference(`Table`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Evaluators are YAML files under `,_jsx(_components.code,{children:`evaluators/agent/`}),` or `,_jsx(_components.code,{children:`evaluators/mcp/`}),` at the repo root. Adding one needs no code. After adding or editing, run `,_jsx(_components.code,{children:`npm run build:catalog`}),` to rebuild the skill catalogs.`]}),`\n`,_jsx(Heading,{level:`2`,id:`minimal-evaluator`,children:`Minimal evaluator`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`15`,language:`yaml`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`yaml`,children:_jsxs(_components.code,{language:`yaml`,numberOfLines:`15`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`schema_version`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:`1`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`id`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`system-prompt-leakage`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`System Prompt Leakage`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`severity`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`critical`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # critical | high | medium | low`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`standards`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` owasp-llm`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`LLM07`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` atlas`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`AML.T0056`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`description`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`One-line summary for judges and contributors`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`pass_criteria`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`|`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`-`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` - Bullet list of safe behaviors`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`fail_criteria`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`|`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`-`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` - Bullet list of vulnerable behaviors`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`patterns`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` - `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:`name`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`Pattern label`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#569CD6`},children:` template`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`Attack prompt text. Use {{placeholder}} for LLM-filled variables.`})]}),`\n`]})})}),`\n`,_jsx(Heading,{level:`2`,id:`fields`,children:`Fields`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Field`}),_jsx(_components.th,{children:`Required`}),_jsx(_components.th,{children:`Notes`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`id`})}),_jsx(_components.td,{children:`Yes`}),_jsx(_components.td,{children:`Kebab-case, unique across both catalogs`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`name`})}),_jsx(_components.td,{children:`Yes`}),_jsx(_components.td,{children:`Display name`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`severity`})}),_jsx(_components.td,{children:`Yes`}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`critical`}),`, `,_jsx(_components.code,{children:`high`}),`, `,_jsx(_components.code,{children:`medium`}),`, `,_jsx(_components.code,{children:`low`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`standards`})}),_jsx(_components.td,{children:`Recommended`}),_jsx(_components.td,{children:`Map of taxonomy key → ID; drives auto-derived suites (omit if unmapped)`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`pass_criteria`})}),_jsx(_components.td,{children:`Yes`}),_jsx(_components.td,{children:`Injected verbatim into the judge prompt`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`fail_criteria`})}),_jsx(_components.td,{children:`Yes`}),_jsx(_components.td,{children:`Injected verbatim into the judge prompt`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`patterns`})}),_jsx(_components.td,{children:`Flat layout only`}),_jsxs(_components.td,{children:[`Non-empty array of `,_jsx(_components.code,{children:`{ name, template }`}),`; omit when using the directory layout`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`description`})}),_jsx(_components.td,{children:`Recommended`}),_jsx(_components.td,{children:`Short summary for docs and skills`})]})]})]}),`\n`,_jsx(Heading,{level:`3`,id:`optional-fields`,children:`Optional fields`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Field`}),_jsx(_components.th,{children:`Purpose`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`schema_version`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`1`}),` when set`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`judge_needs_llm`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`true`}),` for semantic judgment; `,_jsx(_components.code,{children:`false`}),` for regex/static checks`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`applies_to_all_tools`})}),_jsxs(_components.td,{children:[`MCP only — generate attacks for every tool in `,_jsx(_components.code,{children:`tools/list`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`judge_hint`})}),_jsx(_components.td,{children:`Extra guidance appended to the judge prompt`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`surfaces`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`agent`}),`, `,_jsx(_components.code,{children:`browser`}),`, `,_jsx(_components.code,{children:`mcp`}),` — informational`]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`turn_mode`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`single`}),` or `,_jsx(_components.code,{children:`multi`}),` — informational; the run config decides at runtime`]})]})]})]}),`\n`,_jsx(Heading,{level:`2`,id:`standards-→-auto-derived-suites`,children:`Standards → auto-derived suites`}),`\n`,_jsxs(_components.p,{children:[`Setting a `,_jsx(_components.code,{children:`standards`}),` key automatically includes the evaluator in the matching suite.`]}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Key`}),_jsx(_components.th,{children:`Example values`}),_jsx(_components.th,{children:`Auto-derived suite`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-llm`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`LLM01`}),` … `,_jsx(_components.code,{children:`LLM10`})]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-llm-top10`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-mcp`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`MCP01`}),` … `,_jsx(_components.code,{children:`MCP10`})]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-mcp-top10`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-agentic`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`ASI01`}),` …`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-agentic-ai`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-api`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`API1`}),`, `,_jsx(_components.code,{children:`API4`}),`, …`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`owasp-api-top10`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`atlas`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`AML.T0056`}),`, …`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`mitre-atlas`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`eu-ai-act`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`Art.5`}),`, `,_jsx(_components.code,{children:`Art.10`}),`, …`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`eu-ai-act`})})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:_jsx(_components.code,{children:`nist`})}),_jsxs(_components.td,{children:[_jsx(_components.code,{children:`Safe`}),`, `,_jsx(_components.code,{children:`Secure \u0026 Resilient`}),`, …`]}),_jsx(_components.td,{children:_jsx(_components.code,{children:`nist-ai-rmf`})})]})]})]}),`\n`,_jsxs(Warning,{children:[`Don’t use `,_jsx(_components.code,{children:`ref:`}),` or `,_jsx(_components.code,{children:`mitre:`}),` keys — the pre-commit hook rejects them on staged evaluator files.`]}),`\n`,_jsx(Heading,{level:`2`,id:`directory-layout-for-many-patterns`,children:`Directory layout for many patterns`}),`\n`,_jsx(_components.p,{children:`When patterns are long or numerous, split them into their own files:`}),`\n`,_jsx(CodeBlock,{numberOfLines:`6`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`6`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`evaluators/agent/\u003ccategory>/\u003cid>/`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` evaluator.yaml ← all fields except patterns`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` patterns/`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` \u003cslug>.yaml ← { name, template }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` \u003cid>.test.yaml ← { kind: response, pass_case, fail_case }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(Heading,{level:`2`,id:`validate`,children:`Validate`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`shellscript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`shellscript`,children:_jsxs(_components.code,{language:`shellscript`,numberOfLines:`2`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` validate:skills`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # check frontmatter against the Zod schema`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#DCDCAA`},children:`npm`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` run`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` build:catalog:check`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # verify the catalog is up to date`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Both run on pre-commit via Husky. `,_jsx(_components.code,{children:`validate:skills`}),` checks frontmatter against its own Zod schema, which is a separate, hand-maintained copy of the runtime loader’s schema. When you add a new `,_jsx(_components.code,{children:`standards`}),` key, update both so the check and the engine stay in sync.`]})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Authoring evaluators","description":"Add a new evaluator — no TypeScript needed.","href":"/evaluators/authoring"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Minimal evaluator","slug":"minimal-evaluator","depth":2,"children":[]},{"title":"Fields","slug":"fields","depth":2,"children":[{"title":"Optional fields","slug":"optional-fields","depth":3,"children":[]}]},{"title":"Standards → auto-derived suites","slug":"standards-→-auto-derived-suites","depth":2,"children":[]},{"title":"Directory layout for many patterns","slug":"directory-layout-for-many-patterns","depth":2,"children":[]},{"title":"Validate","slug":"validate","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"keyvaluesoftwaresystems","siteName":"Opfor","title":"Authoring evaluators - Opfor","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-07-20T12:58:49.061Z","originalFileLocation":"evaluators/authoring.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Add a new evaluator — no TypeScript needed.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Opfor\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Authoring evaluators - Opfor\">\u003cmeta data-mint-head property=\"og:description\" content=\"Add a new evaluator — no TypeScript needed.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Opfor\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.agentopfor.ai/evaluators/authoring\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://keyvaluesoftwaresystems.mintlify.site/_mintlify/api/og/v2?division=Evaluators+%26+Suites\u0026amp;title=Authoring+evaluators\u0026amp;description=Add+a+new+evaluator+%E2%80%94+no+TypeScript+needed.\u0026amp;theme=f7497a199a6a92d9ad598d7f\u0026amp;signature=8af6330c375286ff5cbee57984c4de181cb659df276c7d9896b6d1a116d0ce97\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Authoring evaluators - Opfor\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Add a new evaluator — no TypeScript needed.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://keyvaluesoftwaresystems.mintlify.site/_mintlify/api/og/v2?division=Evaluators+%26+Suites\u0026amp;title=Authoring+evaluators\u0026amp;description=Add+a+new+evaluator+%E2%80%94+no+TypeScript+needed.\u0026amp;theme=f7497a199a6a92d9ad598d7f\u0026amp;signature=8af6330c375286ff5cbee57984c4de181cb659df276c7d9896b6d1a116d0ce97\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/keyvaluesoftwaresystems/gz7uzFSt9eT2sd9U/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Opfor\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#ff4d4f\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.agentopfor.ai/evaluators/authoring\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/evaluators/authoring.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.agentopfor.ai/#organization\",\"name\":\"Opfor\",\"url\":\"https://docs.agentopfor.ai\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/keyvaluesoftwaresystems/4m7L9sshK3C1tAuP/logo/Opfor_black.svg?fit=max\u0026auto=format\u0026n=4m7L9sshK3C1tAuP\u0026q=85\u0026s=832fbfe414f9908f90a90011fa48eb8e\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.agentopfor.ai#website\",\"name\":\"Opfor\",\"url\":\"https://docs.agentopfor.ai\",\"publisher\":{\"@id\":\"https://docs.agentopfor.ai/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.agentopfor.ai/evaluators/authoring#webpage\",\"url\":\"https://docs.agentopfor.ai/evaluators/authoring\",\"name\":\"Authoring evaluators\",\"description\":\"Add a new evaluator — no TypeScript needed.\",\"dateModified\":\"2026-07-20T12:58:49.061Z\",\"isPartOf\":{\"@id\":\"https://docs.agentopfor.ai#website\"},\"breadcrumb\":{\"@id\":\"https://docs.agentopfor.ai/evaluators/authoring#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.agentopfor.ai/evaluators/authoring#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Evaluators \u0026 Suites\",\"item\":\"https://docs.agentopfor.ai/evaluators/overview\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Authoring evaluators\",\"item\":\"https://docs.agentopfor.ai/evaluators/authoring\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.agentopfor.ai/evaluators/authoring#article\",\"headline\":\"Authoring evaluators\",\"name\":\"Authoring evaluators\",\"description\":\"Add a new evaluator — no TypeScript needed.\",\"url\":\"https://docs.agentopfor.ai/evaluators/authoring\",\"mainEntityOfPage\":{\"@id\":\"https://docs.agentopfor.ai/evaluators/authoring#webpage\"},\"dateModified\":\"2026-07-20T12:58:49.061Z\",\"publisher\":{\"@id\":\"https://docs.agentopfor.ai/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.agentopfor.ai#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Opfor\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"Opfor\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/evaluators/authoring.md","siteName":"Opfor","nav":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/KeyValueSoftwareSystems/agent-opfor"}]},"groups":[{"group":"Get Started","icon":"play","pages":[{"title":"Introduction","href":"/index"},{"title":"Quickstart","href":"/get-started/quickstart"},{"title":"Core concepts","href":"/get-started/concepts"}]},{"group":"CLI","icon":"terminal","pages":[{"title":"CLI overview","href":"/cli/overview"},{"title":"Running scans","href":"/cli/running-scans"},{"title":"Autonomous mode","href":"/cli/autonomous"}]},{"group":"Browser Extension","icon":"chrome","pages":[{"title":"Browser extension","href":"/browser-extension/overview"}]},{"group":"MCP Server","icon":"plug","pages":[{"title":"MCP server","href":"/mcp-server/overview"}]},{"group":"Skills","icon":"sparkles","pages":[{"title":"Skills","href":"/skills/overview"}]},{"group":"SDK","icon":"code","pages":[{"title":"SDK","href":"/sdk/overview"}]},{"group":"Evaluators \u0026 Suites","icon":"shield-halved","pages":[{"title":"Evaluators \u0026 suites","href":"/evaluators/overview"},{"title":"Evaluator reference","description":"Every evaluator and suite, with OWASP mappings.","href":"/evaluators/reference"},{"title":"Authoring evaluators","href":"/evaluators/authoring"}]},{"group":"Trace-aware Testing","icon":"eye","pages":[{"title":"Trace-aware testing","description":"Let the judge see tool calls and retrievals, not just the reply.","href":"/telemetry/overview"}]},{"group":"Reference","icon":"book","pages":[{"title":"Config reference","href":"/reference/config"},{"title":"LLM providers","href":"/reference/providers"},{"title":"Target session handling","href":"/reference/sessions"},{"title":"CLI commands","href":"/reference/cli-commands"}]}]},"basePath":"","title":"Authoring evaluators - Opfor","buildId":"dpl_8hoxaqFTU7hTr6A2fUraxAyjuiZo","deploymentId":"dpl_8hoxaqFTU7hTr6A2fUraxAyjuiZo","dynamics":[],"chunks":[]}