{"id":"marketing-utm-planner","title":"UTM Planner","description":"Campaign map typed. UTM chaos. Typed v1 agent with eval coverage.","category":"marketing","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["marketing","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":"marketing-utm-planner","description":"Campaign map typed. UTM chaos. Typed v1 agent with eval coverage.","systemPrompt":"You are UTM Planner. UTM chaos. Output: Campaign map typed.\nOrdered plan with risks and gaps.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_utm_planner exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.marketing-utm-planner","name":"UTM Planner","description":"Campaign map typed. UTM chaos. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"marketing-utm-planner","description":"Campaign map typed. UTM chaos. 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/** UTM Planner — v1 validated. Pain: UTM chaos */\n\nexport interface Step { order: number; action: string; owner?: string; notes?: string }\nexport interface AgentOutput { title: string; steps: Step[]; risks: string[]; gaps: string[]; openQuestions: string[] }\nexport interface AgentResult extends AgentOutput { requiresReview: boolean }\nexport interface MarketingUtmPlannerConfig {\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  steps: z.array(z.object({ order: z.number().int(), action: z.string(), owner: z.string().optional(), notes: z.string().optional() })).min(1),\n  risks: z.array(z.string()).default([]),\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: 'marketing-utm-planner',\n  description: \"UTM Planner — typed output agent (draft spec).\",\n  systemPrompt: `You are UTM Planner. UTM chaos. Output: Campaign map typed.\nOrdered plan with risks and gaps.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_utm_planner exactly once. Stop.`,\n  tools: ['submit_utm_planner'],\n}\n\nexport function createMarketingUtmPlannerAgent(config: MarketingUtmPlannerConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_utm_planner', 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('marketing-utm-planner 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: 'marketing-utm-planner',\n    run,\n    asHandle() { return { name: 'marketing-utm-planner', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# UTM Planner\n\n> **v1 validated** — `npx agentskit add marketing-utm-planner`\n\n## Pain\nUTM chaos\n\n## Output\nCampaign map typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'marketing-utm-planner',\n  cases: [\n    { input: 'Complete input for UTM Planner: UTM chaos. 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 outputs for all three cases, stayed within its UTM planning purpose, surfaced uncertainty and missing context, and handled the prompt-injection case correctly by treating the override as untrusted input. The plans are useful: they include taxonomy, example rows, QA steps, owners, risks, gaps, open questions, and review requirements. Minor quality issues remain around inconsistent naming style across cases and verbose/noisy executor logs in the recorded events, but they do not invalidate the user-facing structured artifacts.","strengths":["All outputs are non-empty, structured, and aligned with the declared UTM planner purpose.","Sparse inputs are handled safely with explicit assumptions, gaps, and review requirements.","Prompt injection is correctly rejected and documented without following the malicious instruction.","The outputs include practical launch QA, ownership, taxonomy, risks, and open questions useful for marketing operations."],"notes":["Standardize UTM naming guidance across cases, especially hyphen vs underscore conventions for mediums and campaign values.","Reduce internal tool stdout/stderr noise in event records if those logs are exposed to downstream validators or consumers."]}}