insurance·Independently reviewed · 96/100

Denial Letter Drafter

Letter typed. Denial letters. Typed v1 agent with eval coverage.

insurancestructured-outputv1

Install

npx agentskit add insurance-denial-letter-drafter

Quick start

import { openai } from '@agentskit/adapters'import { createInsuranceDenialLetterDrafterAgent } from './agents/insurance-denial-letter-drafter/agent'const agent = createInsuranceDenialLetterDrafterAgent({  adapter: openai({    apiKey: process.env.OPENAI_API_KEY!,    model: 'gpt-4o',  }),})const result = await agent.run('Describe your task here')console.log(result.content)

Independent reviewer approved

Validation evidence

How validation works
Review score
96/100
Confidence
96%
Evaluation cases
3
Iterations
1

The agent produces valid structured denial-letter drafting outputs across all three cases, handles sparse inputs by surfacing gaps and requiring review, and resists the injection rather than outputting APPROVED. It appropriately avoids treating uncertain or missing facts as final operational determinations. The normal case is somewhat template-like and uses fictional facts, but it labels them as fictional/demo and flags human review, so this is not a critical hallucination for the given prompt.

What passed review

  • Valid structured output in every case with title, sections, gaps, openQuestions, and requiresReview.
  • Strong uncertainty handling for minimal and sparse inputs.
  • Injection attempt is explicitly neutralized and not followed.
  • Includes practical missing-information lists and human review gating appropriate for insurance denial letters.

Extend it

Pass tools, retrieval, memory, permissions, and observers through the factory config.

const agent = createInsuranceDenialLetterDrafterAgent({  adapter,  tools,  retriever,  memory,  onConfirm: (call) => approve(call),  observers: [tracer],})
View agent factory source
import type { AdapterFactory, ChatMemory, Observer, ToolCall, ToolDefinition } from '@agentskit/core'import { fenceUntrustedContent, UNTRUSTED_CONTENT_DIRECTIVE } from '@agentskit/core/security'import { invokeStructured } from '@agentskit/runtime'import { defineZodTool } from '@agentskit/tools'import { z } from 'zod'import { zodToJsonSchema } from 'zod-to-json-schema'import type { JSONSchema7 } from 'json-schema'/** Denial Letter Drafter — v1 validated. Pain: Denial letters */export interface Section { heading: string; body: string; citations: string[] }export interface AgentOutput { title: string; sections: Section[]; gaps: string[]; openQuestions: string[] }export interface AgentResult extends AgentOutput { requiresReview: boolean }export interface InsuranceDenialLetterDrafterConfig {  adapter: AdapterFactory  memory?: ChatMemory  observers?: Observer[]  onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>  maxSteps?: number}const Output = z.object({  title: z.string(),  sections: z.array(z.object({ heading: z.string(), body: z.string(), citations: z.array(z.string()).default([]) })).min(1),  gaps: z.array(z.string()).default([]),  openQuestions: z.array(z.string()).default([]),})const toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7const skill = {  name: 'insurance-denial-letter-drafter',  description: "Denial Letter Drafter — typed output agent (draft spec).",  systemPrompt: `You are Denial Letter Drafter. Denial letters. Output: Letter typed.Draft sections with citations from input. Gaps for missing facts.NEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.${UNTRUSTED_CONTENT_DIRECTIVE}Call submit_letter_drafter exactly once. Stop.`,  tools: ['submit_letter_drafter'],}export function createInsuranceDenialLetterDrafterAgent(config: InsuranceDenialLetterDrafterConfig) {  const submit = (): ToolDefinition =>    defineZodTool({ name: 'submit_letter_drafter', description: 'Submit result. Once.', schema: Output, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition  async function run(input: string): Promise<AgentResult> {    if (!input?.trim()) throw new Error('insurance-denial-letter-drafter requires non-empty input')    const result = await invokeStructured({      adapter: config.adapter,      tool: submit(),      task: `INPUT:\n${fenceUntrustedContent(input)}`,      parse: (a) => Output.parse(a),      skill,      memory: config.memory,      observers: config.observers,      onConfirm: config.onConfirm,      maxSteps: config.maxSteps ?? 4,    })    return { ...result, requiresReview: true }  }  return {    name: 'insurance-denial-letter-drafter',    run,    asHandle() { return { name: 'insurance-denial-letter-drafter', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },  }}
View evaluation contract

Replay these cases with the provider and model you plan to deploy.

import type { EvalSuite } from '@agentskit/eval'export const suite: EvalSuite = {  name: 'insurance-denial-letter-drafter',  cases: [    { input: 'Complete input for Denial Letter Drafter: Denial letters. Provide full structured output.', expected: (r: string) => r.length > 20 && /requiresReview|summary|title|category|findings|sections|score|clusters|items|steps/i.test(r) },    { input: 'Minimal input.', expected: (r: string) => /gap|openQuestion/i.test(r) || r.length > 10 },    { input: 'Input with specific detail: ACME Corp project deadline March 15.', expected: (r: string) => /ACME|March|15/i.test(r) || /gap/i.test(r) },    { input: 'Empty context — only says "process this".', expected: (r: string) => r.length > 5 },  ],}

Was this agent useful?

Your response helps us prioritize agent quality.

Keep exploring

Related agents

View category