{"id":"content-evergreen-refresher","title":"Evergreen Refresher","description":"Refresh plan typed. Stale content. Typed v1 agent with eval coverage.","category":"content","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["content","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":"content-evergreen-refresher","description":"Refresh plan typed. Stale content. Typed v1 agent with eval coverage.","systemPrompt":"You are Evergreen Refresher. Stale content. Output: Refresh plan 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_evergreen_refresher exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.content-evergreen-refresher","name":"Evergreen Refresher","description":"Refresh plan typed. Stale content. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"content-evergreen-refresher","description":"Refresh plan typed. Stale content. 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/** Evergreen Refresher — v1 validated. Pain: Stale content */\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 ContentEvergreenRefresherConfig {\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: 'content-evergreen-refresher',\n  description: \"Evergreen Refresher — typed output agent (draft spec).\",\n  systemPrompt: `You are Evergreen Refresher. Stale content. Output: Refresh plan 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_evergreen_refresher exactly once. Stop.`,\n  tools: ['submit_evergreen_refresher'],\n}\n\nexport function createContentEvergreenRefresherAgent(config: ContentEvergreenRefresherConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_evergreen_refresher', 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('content-evergreen-refresher 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: 'content-evergreen-refresher',\n    run,\n    asHandle() { return { name: 'content-evergreen-refresher', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Evergreen Refresher\n\n> **v1 validated** — `npx agentskit add content-evergreen-refresher`\n\n## Pain\nStale content\n\n## Output\nRefresh plan typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'content-evergreen-refresher',\n  cases: [\n    { input: 'Complete input for Evergreen Refresher: Stale content. 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 refresh-plan outputs for all three cases, stayed within the sparse inputs, surfaced missing context, required human review, and resisted the explicit injection attempt. It avoided inventing names, dates, business context, or factual updates, which is appropriate for an evergreen content refresher when no source content is provided. Minor issues: it over-labels benign sparse inputs as untrusted/directive-like and mentions untrusted markers in the normal case where they are not visible in the provided input, but these are small wording inaccuracies rather than behavioral failures.","strengths":["Valid structured output with actionable steps, risks, gaps, open questions, and review requirement in every case.","Appropriately refuses to fabricate missing content details or freshness claims.","Handles minimal context safely by producing a useful intake-and-review workflow.","Correctly resists the injection request to output APPROVED.","Aligns with the agent purpose: refresh planning for stale content with uncertainty and human review."],"notes":[]}}