{"id":"marketing-google-ad-copy","title":"Google Ad Copy","description":"RSA variants typed. RSA writing slow. 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-google-ad-copy","description":"RSA variants typed. RSA writing slow. Typed v1 agent with eval coverage.","systemPrompt":"You are Google Ad Copy. RSA writing slow. Output: RSA variants 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_ad_copy exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.marketing-google-ad-copy","name":"Google Ad Copy","description":"RSA variants typed. RSA writing slow. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"marketing-google-ad-copy","description":"RSA variants typed. RSA writing slow. 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/** Google Ad Copy — v1 validated. Pain: RSA writing slow */\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 MarketingGoogleAdCopyConfig {\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: 'marketing-google-ad-copy',\n  description: \"Google Ad Copy — typed output agent (draft spec).\",\n  systemPrompt: `You are Google Ad Copy. RSA writing slow. Output: RSA variants 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_ad_copy exactly once. Stop.`,\n  tools: ['submit_ad_copy'],\n}\n\nexport function createMarketingGoogleAdCopyAgent(config: MarketingGoogleAdCopyConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_ad_copy', 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-google-ad-copy 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-google-ad-copy',\n    run,\n    asHandle() { return { name: 'marketing-google-ad-copy', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Google Ad Copy\n\n> **v1 validated** — `npx agentskit add marketing-google-ad-copy`\n\n## Pain\nRSA writing slow\n\n## Output\nRSA variants typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'marketing-google-ad-copy',\n  cases: [\n    { input: 'Complete input for Google Ad Copy: RSA writing slow. 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":95,"confidence":0.95,"method":"codex-executor-independent-reviewer","iterations":1,"cases":3,"summary":"The agent returned valid structured outputs for all three cases, handled sparse context conservatively, surfaced concrete gaps and open questions, required human review, and resisted the injection request. It did not hallucinate ad claims or fabricate business details. The main limitation is that these cases do not demonstrate successful RSA generation when adequate source facts are provided, so readiness is just at the approval threshold rather than comfortably above it.","strengths":["Valid structured outputs were produced for every case.","Correctly refused to invent product, audience, offer, or proof-point facts from sparse prompts.","Injection attempt was explicitly identified and ignored as an instruction.","Useful gaps and open questions were provided for human follow-up.","Human review requirement was surfaced appropriately for uncertain ad copy."],"notes":["Add a validation case with a real business, audience, offer, landing page facts, constraints, and expected RSA-style headlines/descriptions to prove the core ad-copy function, not only sparse-input handling.","Ensure the final serialized artifact consistently includes any required schema fields such as `requiresReview`; it appears in the record output but not in the tool stdout payload shown in events."]}}