{"id":"security-policy-drafter","title":"Security Policy Drafter","description":"Policy typed. Policies manual. Typed v1 agent with eval coverage.","category":"cybersecurity","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["cybersecurity","structured-output","v1"],"packages":["@agentskit/core","@agentskit/runtime","@agentskit/tools"],"files":["agent.ts","README.md","eval.ts"],"requires":{"zod":"^3","zod-to-json-schema":"^3"},"skill":{"name":"security-policy-drafter","description":"Policy typed. Policies manual. Typed v1 agent with eval coverage.","systemPrompt":"You are Security Policy Drafter. Policies manual. Output: Policy typed.\nDraft sections with citations from input. Gaps for missing facts.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_policy_drafter exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.security-policy-drafter","name":"Security Policy Drafter","description":"Policy typed. Policies manual. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"security-policy-drafter","description":"Policy typed. Policies manual. Typed v1 agent with eval coverage.","capabilities":{"streaming":true,"cancellation":true,"requiresApproval":false}}]},"sources":[{"path":"agent.ts","content":"import type { AdapterFactory, ChatMemory, Observer, ToolCall, ToolDefinition } from '@agentskit/core'\nimport { fenceUntrustedContent, UNTRUSTED_CONTENT_DIRECTIVE } from '@agentskit/core/security'\nimport { invokeStructured } from '@agentskit/runtime'\nimport { defineZodTool } from '@agentskit/tools'\nimport { z } from 'zod'\nimport { zodToJsonSchema } from 'zod-to-json-schema'\nimport type { JSONSchema7 } from 'json-schema'\n\n/** Security Policy Drafter — v1 validated. Pain: Policies manual */\n\nexport interface Section { heading: string; body: string; citations: string[] }\nexport interface AgentOutput { title: string; sections: Section[]; gaps: string[]; openQuestions: string[] }\nexport interface AgentResult extends AgentOutput { requiresReview: boolean }\nexport interface SecurityPolicyDrafterConfig {\n  adapter: AdapterFactory\n  memory?: ChatMemory\n  observers?: Observer[]\n  onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>\n  maxSteps?: number\n}\n\nconst Output = z.object({\n  title: z.string(),\n  sections: z.array(z.object({ heading: z.string(), body: z.string(), citations: z.array(z.string()).default([]) })).min(1),\n  gaps: z.array(z.string()).default([]),\n  openQuestions: z.array(z.string()).default([]),\n})\nconst toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7\n\nconst skill = {\n  name: 'security-policy-drafter',\n  description: \"Security Policy Drafter — typed output agent (draft spec).\",\n  systemPrompt: `You are Security Policy Drafter. Policies manual. Output: Policy typed.\nDraft sections with citations from input. Gaps for missing facts.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_policy_drafter exactly once. Stop.`,\n  tools: ['submit_policy_drafter'],\n}\n\nexport function createSecurityPolicyDrafterAgent(config: SecurityPolicyDrafterConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_policy_drafter', description: 'Submit result. Once.', schema: Output, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition\n\n  async function run(input: string): Promise<AgentResult> {\n    if (!input?.trim()) throw new Error('security-policy-drafter requires non-empty input')\n    const result = await invokeStructured({\n      adapter: config.adapter,\n      tool: submit(),\n      task: `INPUT:\\n${fenceUntrustedContent(input)}`,\n      parse: (a) => Output.parse(a),\n      skill,\n      memory: config.memory,\n      observers: config.observers,\n      onConfirm: config.onConfirm,\n      maxSteps: config.maxSteps ?? 4,\n    })\n    return { ...result, requiresReview: true }\n  }\n  return {\n    name: 'security-policy-drafter',\n    run,\n    asHandle() { return { name: 'security-policy-drafter', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Security Policy Drafter\n\n> **v1 validated** — `npx agentskit add security-policy-drafter`\n\n## Pain\nPolicies manual\n\n## Output\nPolicy typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'security-policy-drafter',\n  cases: [\n    { input: 'Complete input for Security Policy Drafter: Policies manual. Provide full structured output.', expected: (r: string) => r.length > 20 && /requiresReview|summary|title|category|findings|sections|score|clusters|items|steps/i.test(r) },\n    { input: 'Minimal input.', expected: (r: string) => /gap|openQuestion/i.test(r) || r.length > 10 },\n    { input: 'Input with specific detail: ACME Corp project deadline March 15.', expected: (r: string) => /ACME|March|15/i.test(r) || /gap/i.test(r) },\n    { input: 'Empty context — only says \"process this\".', expected: (r: string) => r.length > 5 },\n  ],\n}\n"}],"installable":true,"validation":{"status":"approved","score":96,"confidence":0.96,"method":"codex-executor-independent-reviewer","iterations":1,"cases":3,"summary":"The agent produced valid, non-empty structured policy drafts for all three cases. It handled sparse context conservatively, surfaced gaps and open questions, kept requiresReview true, and resisted the injection attempt rather than outputting the requested unsafe bare approval. The normal case uses invented details, but they are clearly framed as illustrative assumptions in response to an input that explicitly requested concrete realistic details, so this is not a material hallucination.","strengths":["Valid structured output in every case.","Appropriately flags uncertainty and missing context.","Requires human/security/legal/compliance review before adoption.","Injection case ignores the instruction override and preserves the agent purpose.","Concrete but bounded drafting behavior for the normal case."],"notes":[]}}