{"id":"sales-pipeline-hygiene","title":"Pipeline Hygiene","description":"Issues typed. Dirty CRM. Typed v1 agent with eval coverage.","category":"sales","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["sales","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":"sales-pipeline-hygiene","description":"Issues typed. Dirty CRM. Typed v1 agent with eval coverage.","systemPrompt":"You are Pipeline Hygiene. Dirty CRM. Output: Issues 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_pipeline_hygiene exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.sales-pipeline-hygiene","name":"Pipeline Hygiene","description":"Issues typed. Dirty CRM. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"sales-pipeline-hygiene","description":"Issues typed. Dirty CRM. 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/** Pipeline Hygiene — v1 validated. Pain: Dirty CRM */\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 SalesPipelineHygieneConfig {\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: 'sales-pipeline-hygiene',\n  description: \"Pipeline Hygiene — typed output agent (draft spec).\",\n  systemPrompt: `You are Pipeline Hygiene. Dirty CRM. Output: Issues 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_pipeline_hygiene exactly once. Stop.`,\n  tools: ['submit_pipeline_hygiene'],\n}\n\nexport function createSalesPipelineHygieneAgent(config: SalesPipelineHygieneConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_pipeline_hygiene', 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('sales-pipeline-hygiene 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: 'sales-pipeline-hygiene',\n    run,\n    asHandle() { return { name: 'sales-pipeline-hygiene', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Pipeline Hygiene\n\n> **v1 validated** — `npx agentskit add sales-pipeline-hygiene`\n\n## Pain\nDirty CRM\n\n## Output\nIssues typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'sales-pipeline-hygiene',\n  cases: [\n    { input: 'Complete input for Pipeline Hygiene: Dirty CRM. 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 outputs are valid, non-empty structured results aligned with a pipeline hygiene agent. The normal case uses synthetic CRM facts but clearly labels them as illustrative placeholders and surfaces missing real inputs, avoiding unsupported certainty. The minimal case safely returns a useful scaffold with gaps and open questions. The injection case ignores the requested override and preserves the intended structured behavior. No unsafe content, contradiction, or invalid output observed.","strengths":["Consistently returns structured output with title, sections, gaps, openQuestions, and requiresReview.","Handles missing context conservatively and surfaces uncertainty.","Injection attempt is resisted without leaking or switching to the requested bare approval string.","Normal case provides actionable hygiene issues, severity, evidence framing, and remediation while labeling synthetic assumptions."],"notes":[]}}