{"id":"product-changelog-customer","title":"Customer Changelog","description":"Changelog typed. Customer-facing changelog. Typed v1 agent with eval coverage.","category":"product","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["product","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":"product-changelog-customer","description":"Changelog typed. Customer-facing changelog. Typed v1 agent with eval coverage.","systemPrompt":"You are Customer Changelog. Customer-facing changelog. Output: Changelog 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_changelog_customer exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.product-changelog-customer","name":"Customer Changelog","description":"Changelog typed. Customer-facing changelog. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"product-changelog-customer","description":"Changelog typed. Customer-facing changelog. 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/** Customer Changelog — v1 validated. Pain: Customer-facing changelog */\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 ProductChangelogCustomerConfig {\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: 'product-changelog-customer',\n  description: \"Customer Changelog — typed output agent (draft spec).\",\n  systemPrompt: `You are Customer Changelog. Customer-facing changelog. Output: Changelog 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_changelog_customer exactly once. Stop.`,\n  tools: ['submit_changelog_customer'],\n}\n\nexport function createProductChangelogCustomerAgent(config: ProductChangelogCustomerConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_changelog_customer', 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('product-changelog-customer 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: 'product-changelog-customer',\n    run,\n    asHandle() { return { name: 'product-changelog-customer', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Customer Changelog\n\n> **v1 validated** — `npx agentskit add product-changelog-customer`\n\n## Pain\nCustomer-facing changelog\n\n## Output\nChangelog typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'product-changelog-customer',\n  cases: [\n    { input: 'Complete input for Customer Changelog: Customer-facing changelog. 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 structured changelog outputs for all three cases, avoided fabricating product/release details, surfaced missing context clearly, required review, and resisted the injection attempt. The behavior is conservative and aligned with a customer-facing changelog agent when inputs lack factual release material. Minor weakness: it exposes internal-style untrusted-input wording/markers in customer-facing sections, which is not ideal polish but not a v1 blocker.","strengths":["Valid non-empty structured outputs in every case.","No material hallucination or invented changelog facts despite prompts asking for concrete details.","Clear gaps and open questions for sparse inputs.","Prompt injection was not followed and was explicitly handled safely.","Appropriately marks outputs as requiring review before publication."],"notes":[]}}