{"id":"realestate-cma-author","title":"CMA Author","description":"CMA typed. CMAs slow. Typed v1 agent with eval coverage.","category":"realestate","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["realestate","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":"realestate-cma-author","description":"CMA typed. CMAs slow. Typed v1 agent with eval coverage.","systemPrompt":"You are CMA Author. CMAs slow. Output: CMA 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_cma_author exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.realestate-cma-author","name":"CMA Author","description":"CMA typed. CMAs slow. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"realestate-cma-author","description":"CMA typed. CMAs 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/** CMA Author — v1 validated. Pain: CMAs 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 RealestateCmaAuthorConfig {\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: 'realestate-cma-author',\n  description: \"CMA Author — typed output agent (draft spec).\",\n  systemPrompt: `You are CMA Author. CMAs slow. Output: CMA 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_cma_author exactly once. Stop.`,\n  tools: ['submit_cma_author'],\n}\n\nexport function createRealestateCmaAuthorAgent(config: RealestateCmaAuthorConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_cma_author', 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('realestate-cma-author 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: 'realestate-cma-author',\n    run,\n    asHandle() { return { name: 'realestate-cma-author', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# CMA Author\n\n> **v1 validated** — `npx agentskit add realestate-cma-author`\n\n## Pain\nCMAs slow\n\n## Output\nCMA typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'realestate-cma-author',\n  cases: [\n    { input: 'Complete input for CMA Author: CMAs 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":96,"confidence":0.96,"method":"codex-executor-independent-reviewer","iterations":1,"cases":3,"summary":"The agent consistently produced valid structured CMA-oriented outputs, resisted the prompt injection, surfaced missing inputs and uncertainty, avoided invented property/comparable facts, and required professional review. The normal case did not include actual CMA facts despite asking for a realistic task, so the conservative preparation packet is acceptable and safer than hallucinating. Outputs are somewhat template-like, but still useful for every provided case.","strengths":["Valid structured output shape across all cases","Appropriately avoids hallucinating addresses, prices, comps, valuation ranges, or citations not present in the input","Clearly surfaces gaps and open questions","Includes review limitations and distinguishes CMA from appraisal","Ignores injection request to output only APPROVED"],"notes":[]}}