new-agent

nimag's avatarfrom nimag

Create a new underwriting agent (assets, credit, collateral) following established patterns. Use when implementing new agents, extending the system with new document analysis capabilities, or understanding how agents work.

⭐0stars🔀0forks📁View on GitHub🕐Updated Dec 22, 2025

When & Why to Use This Skill

This Claude skill provides a comprehensive framework and boilerplate for developing specialized underwriting agents (Assets, Credit, and Collateral) within a Go-based environment. It streamlines the creation of AI-driven financial analysis tools by enforcing a standardized interface, providing step-by-step implementation guides, and integrating Gemini-powered document processing patterns to ensure consistent and scalable agent architecture.

Use Cases

  • Case 1: Rapidly scaffolding a new 'Assets' verification agent to automate the analysis of bank statements and retirement account documents using established Go patterns.
  • Case 2: Extending a mortgage processing system by implementing a 'Collateral' agent that follows the standard interface for appraisal and title report evaluation.
  • Case 3: Standardizing the integration of LLM-based document analysis across different financial domains by utilizing pre-defined system prompt patterns and structured JSON response parsing.
  • Case 4: Onboarding developers to a complex underwriting system by providing a clear reference implementation and directory structure for new agent modules.
namenew-agent
descriptionCreate a new underwriting agent (assets, credit, collateral) following established patterns. Use when implementing new agents, extending the system with new document analysis capabilities, or understanding how agents work.

Create New Underwriting Agent

Purpose

Create new agents for assets, credit, or collateral analysis following the income agent pattern.

Agent Interface

All agents must implement this interface from internal/agent/agent.go:

type Agent interface {
    Type() AgentType
    Name() string
    RequiredDocuments() []model.DocumentType
    OptionalDocuments() []model.DocumentType
    Dependencies() []AgentType
    Analyze(ctx context.Context, input *AnalysisInput) (*model.AnalysisResult, error)
    CanProceed(docs []*model.Document) (bool, []model.DocumentType)
}

Agent Types

const (
    AgentTypeIncome     AgentType = "income"
    AgentTypeAssets     AgentType = "assets"
    AgentTypeCredit     AgentType = "credit"
    AgentTypeCollateral AgentType = "collateral"
)

Step-by-Step Guide

1. Create Directory Structure

mkdir -p internal/agent/<agentname>

2. Create Agent File

Use this template based on internal/agent/income/income.go:

package <agentname>

import (
    "context"
    "encoding/json"
    "fmt"
    "strings"
    "time"

    "github.com/nimag/fast/internal/agent"
    "github.com/nimag/fast/internal/gemini"
    "github.com/nimag/fast/internal/guidelines"
    "github.com/nimag/fast/internal/model"
)

type Agent struct {
    gemini     *gemini.Client
    guidelines string
}

type Config struct {
    GuidelinesPath string
}

func New(geminiClient *gemini.Client) *Agent {
    return &Agent{gemini: geminiClient}
}

func NewWithConfig(geminiClient *gemini.Client, cfg Config) *Agent {
    a := &Agent{gemini: geminiClient}

    if cfg.GuidelinesPath != "" {
        loader := guidelines.NewLoader(cfg.GuidelinesPath)
        // Load appropriate section: "assets", "credit", or "collateral"
        if content, err := loader.LoadSection("<section>"); err == nil {
            a.guidelines = content
        }
    }
    return a
}

func (a *Agent) Type() agent.AgentType {
    return agent.AgentType<Name>
}

func (a *Agent) Name() string {
    return "<Name> Verification Agent"
}

func (a *Agent) RequiredDocuments() []model.DocumentType {
    return []model.DocumentType{
        // Add required document types
    }
}

func (a *Agent) OptionalDocuments() []model.DocumentType {
    return []model.DocumentType{
        // Add optional document types
    }
}

func (a *Agent) Dependencies() []agent.AgentType {
    return nil // Or list dependent agents
}

func (a *Agent) CanProceed(docs []*model.Document) (bool, []model.DocumentType) {
    required := a.RequiredDocuments()
    // Check if required docs are present
    // Return (true, nil) if can proceed
    // Return (false, missingTypes) if cannot
}

func (a *Agent) Analyze(ctx context.Context, input *agent.AnalysisInput) (*model.AnalysisResult, error) {
    // 1. Filter documents for this agent
    // 2. Build prompts
    // 3. Call Gemini
    // 4. Parse response
    // 5. Return AnalysisResult
}

3. Document Types by Agent

Assets Agent:

Required: DocTypeBankStatement
Optional: DocTypeAssetStatement, DocTypeRetirementStmt, DocTypeGiftLetter

Credit Agent:

Required: DocTypeCreditReport
Optional: DocTypeDebtPayoff

Collateral Agent:

Required: DocTypeAppraisal
Optional: DocTypePurchaseContract, DocTypeTitleReport, DocTypePropertyInsurance

4. Guidelines Section Mapping

// Load the correct section for your agent
loader.LoadSection("assets")     // For assets agent
loader.LoadSection("credit")     // For credit agent
loader.LoadSection("collateral") // For collateral agent

5. Streaming Output Format

For streaming analysis with real-time progress display, prompts should output markers that StreamFormatter detects. See the streaming-output skill for the full specification.

Key markers:

**📋 GUIDELINE: [Section ID] - [Title]**
Status: ✅ COMPLIANT | ⚠️ ISSUE | ❌ NON-COMPLIANT

**🔍 CROSS-CHECK: [Doc1] vs [Doc2]**
Result: MATCH | MISMATCH

**🧮 INCOME CALCULATION**
Base annual salary: $X,XXX.XX
Total qualifying monthly income: $X,XXX.XX

**✅ FINAL DETERMINATION**
Status: APPROVED | DENIED | NEEDS REVIEW

6. System Prompt Pattern

func (a *Agent) buildSystemPrompt() string {
    // Load guidelines - they contain the analysis instructions
    // Don't duplicate guideline content in the prompt
    if a.guidelines != "" {
        return "## Fannie Mae Guidelines\n\n" + a.guidelines
    }
    return ""
}

7. Response Parsing

Request JSON output and parse into model.AnalysisResult:

type analysisResponse struct {
    Status           string    `json:"status"`
    Confidence       float64   `json:"confidence"`
    Summary          string    `json:"summary"`
    Findings         []finding `json:"findings"`
    Risks            []risk    `json:"risks"`
    MissingDocuments []string  `json:"missing_documents"`
}

8. Register in Main

Update cmd/underwriter/main.go:

import "<agentname>" // Add import

// Create agent
newAgent := <agentname>.NewWithConfig(geminiClient, <agentname>.Config{
    GuidelinesPath: *guidelinesDir,
})

// Add to agents slice
agents := []agent.Agent{incomeAgent, newAgent}

Reference Implementation

Study internal/agent/income/income.go for:

  • Complete Analyze() implementation
  • Prompt building patterns
  • JSON response parsing
  • Error handling
  • Document filtering
  • internal/agent/agent.go - Interface definition
  • internal/agent/income/income.go - Reference implementation
  • internal/model/document.go - Document types
  • internal/model/analysis.go - Result structures
  • internal/guidelines/loader.go - Guideline loading
  • configs/guidelines/ - Guideline files by section