AgentSkillsCN

Skill

技能

SKILL.md

NOFO Processor Skill (General)

Purpose

This skill enables Claude to create AI-powered grant solicitation analysis tools that extract key information from NOFOs (Notices of Funding Opportunity), RFAs, program announcements, and other funding opportunity documents. The tool generates proposal preparation timelines, flags policy conflicts with institutional requirements, and produces actionable checklists for grants management workflows.

This is a generalized skill designed to work with any research institution. It requires gathering institution-specific rates and policies during setup.

When to Use This Skill

  • User requests a tool to analyze grant solicitations or funding opportunities
  • User needs to extract deadlines, requirements, or budget information from NOFOs
  • User wants to generate proposal preparation timelines
  • User needs to compare sponsor policies against institutional policies
  • User requests a grants management or proposal planning tool

Institution Configuration (Required)

Before building the tool, gather the following information from the user's institution. This data is typically available from the institution's Office of Sponsored Programs, Controller's Office, or Research Administration website.

1. F&A (Indirect Cost) Rates

Prompt the user to provide their institution's federally negotiated F&A rates:

code
Please provide your institution's current F&A (indirect cost) rates:

1. On-campus Research rate: ___% (base: MTDC/TDC)
2. Off-campus Research rate: ___% (base: MTDC/TDC)
3. Instruction rate: ___% (base: MTDC/TDC)
4. Other Sponsored Activities rate: ___% (base: MTDC/TDC)
5. Industry/Commercial rates (if different): ___%
6. Clinical Trials rate (if applicable): ___%

Rate Agreement effective dates: From ___ to ___

Where to find this: 
- Your institution's Controller's Office or Cost Accounting website
- Office of Sponsored Programs rate information page
- Search "[Institution Name] F&A rates" or "indirect cost rates"

2. Fringe Benefit Rates

Prompt the user to provide fringe benefit rates by employee category:

code
Please provide your institution's current fringe benefit rates:

Federal/On-Campus Rates:
- Faculty: ___%
- Staff: ___%
- Graduate Students (GSR/GRA): ___%
- Postdoctoral Researchers: ___%
- Temporary/Hourly: ___%
- Student Workers: ___%

Non-Federal Rates (if different): [same categories]

Effective fiscal year: FY____

Where to find this:
- Controller's Office or Budget Office website
- Proposal preparation guidelines
- Search "[Institution Name] fringe benefit rates"

3. Key Policy Thresholds

Prompt the user for institutional policy thresholds:

code
Please provide your institution's current policy thresholds:

1. Equipment capitalization threshold: $______
   (Items above this are classified as equipment vs. supplies)

2. Subaward F&A threshold: First $______ per subaward included in MTDC
   (Federal standard is $25,000; some institutions have different rates)

3. Cost sharing policy: 
   [ ] Discouraged unless required
   [ ] Allowed with approval
   [ ] Other: _______________

4. Off-campus rate criteria:
   When does off-campus F&A rate apply? _______________

Where to find this:
- Sponsored Programs policy manual
- Proposal preparation guidelines
- Federal rate agreement documentation

4. Workflow Stages and Timing

Gather the institution's internal proposal workflow:

code
Please describe your institution's proposal preparation workflow:

Stage 1: _____________ (Days before deadline: ___)
Stage 2: _____________ (Days before deadline: ___)
Stage 3: _____________ (Days before deadline: ___)
[Continue as needed...]

Internal submission deadline: ___ days before sponsor deadline
Final review/approval: ___ days before sponsor deadline

Key milestones:
- PI certification required: [ ] Yes [ ] No - Due: ___ days before
- Department approval required: [ ] Yes [ ] No - Due: ___ days before
- Dean/College approval required: [ ] Yes [ ] No - Due: ___ days before

5. Key Contacts

Gather institutional contacts for the checklist output:

code
Please provide key contacts for grant submissions:

Office of Sponsored Programs:
- General email: _______________
- Phone: _______________
- Website: _______________
- NIH-specific contact (if any): _______________
- NSF-specific contact (if any): _______________

Research Compliance:
- IRB (Human Subjects): _______________
- IACUC (Animal Research): _______________
- IBC (Biosafety): _______________
- Export Control: _______________

Budget/Rates:
- Controller's Office: _______________
- Cost Accounting: _______________

Other relevant offices: _______________

Core Capabilities

1. Dual Input Methods

The tool should support both:

  • PDF Upload: Convert PDF to base64 and send to Claude API for analysis
  • URL Input: Fetch web-based solicitations via web_fetch and analyze content

2. Intelligent Information Extraction

Extract the following structured data from solicitations:

json
{
  "title": "Full title of the solicitation",
  "sponsor": "Funding agency name",
  "program": "Program or mechanism name",
  "deadlines": [
    {"type": "Letter of Intent", "date": "YYYY-MM-DD", "notes": "optional notes"},
    {"type": "Full Proposal", "date": "YYYY-MM-DD", "notes": "optional notes"}
  ],
  "eligibility": {
    "institution_types": ["R1 universities", "non-profits"],
    "pi_requirements": "PI eligibility requirements",
    "geographic_restrictions": "Any geographic restrictions or none",
    "other": "Any other eligibility notes"
  },
  "budget": {
    "max_total": "Maximum total budget",
    "max_per_year": "Maximum per year",
    "indirect_cost_policy": "F&A policy details",
    "cost_sharing_required": "Yes/No and details",
    "restrictions": ["Budget restrictions or special rules"]
  },
  "required_documents": ["List of all required documents and forms"],
  "page_limits": [
    {"document": "Document name", "limit": "Page limit"}
  ],
  "compliance_requirements": ["IRB", "IACUC", "Data Management Plan"],
  "special_requirements": ["Other important requirements"],
  "policy_flags": ["Policy conflicts with institutional rates"],
  "recommended_resources": ["Recommended contacts and resources"],
  "helpful_hints": ["Tips for preparing a strong proposal"]
}

3. Institutional Policy Integration Template

Store the gathered institutional data in a configuration object:

javascript
const INSTITUTION_CONFIG = {
  name: "Institution Name",
  
  faRates: {
    onCampusResearch: { rate: 0.00, base: "MTDC" },
    offCampusResearch: { rate: 0.00, base: "MTDC" },
    instruction: { rate: 0.00, base: "MTDC" },
    otherSponsored: { rate: 0.00, base: "MTDC" },
    industryResearch: { rate: 0.00, base: "MTDC" },
    clinicalTrials: { rate: 0.00, base: "TDC" },
    effectiveDate: "YYYY-MM-DD",
    expirationDate: "YYYY-MM-DD"
  },
  
  fringeRates: {
    faculty: 0.00,
    staff: 0.00,
    graduateStudents: 0.00,
    postdocs: 0.00,
    temporary: 0.00,
    studentWorkers: 0.00,
    fiscalYear: "FY20XX"
  },
  
  policies: {
    equipmentThreshold: 5000,
    subawardMTDCThreshold: 25000,
    costSharingPolicy: "Discouraged unless required",
    offCampusCriteria: "When rent charged directly to project"
  },
  
  workflow: [
    { stage: 1, name: "Initial Notification", daysOffset: 0 },
    { stage: 2, name: "Solicitation Review", daysOffset: -30 },
    // ... additional stages
  ],
  
  contacts: {
    osp: { email: "", phone: "", website: "" },
    irb: { email: "", website: "" },
    iacuc: { email: "", website: "" },
    controller: { email: "", website: "" }
  }
};

4. Timeline Generation

Generate proposal preparation timelines using business day calculations based on the institution's workflow:

javascript
// Business day subtraction function
const subtractBusinessDays = (date, days) => {
  const result = new Date(date);
  let remaining = Math.abs(days);
  const direction = days < 0 ? -1 : 1;
  while (remaining > 0) {
    result.setDate(result.getDate() + direction);
    if (result.getDay() !== 0 && result.getDay() !== 6) {
      remaining--;
    }
  }
  return result;
};

// Generate timeline from institution config
const generateTimeline = (deadlineDate, workflowStages) => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  
  const milestones = workflowStages.map(stage => ({
    stage: stage.name,
    date: subtractBusinessDays(deadlineDate, Math.abs(stage.daysOffset)),
    daysOffset: stage.daysOffset
  }));
  
  // Filter to show only future milestones
  const futureMilestones = milestones.filter(m => m.date >= today);
  
  // Always add "Today" as starting point
  return [
    { stage: 'Initial Notification (Today)', date: today, isStart: true },
    ...futureMilestones
  ].sort((a, b) => a.date - b.date);
};

Timeline Logic:

  • Calculate dates by subtracting business days (exclude weekends)
  • Show only stages from today forward for compressed timelines
  • Display warnings when timeline is compressed
  • Support multiple deadline selection for sponsors with multiple windows

5. Policy Conflict Detection

Automatically flag when sponsor requirements conflict with institutional policies:

javascript
const detectPolicyConflicts = (sponsorPolicy, institutionConfig) => {
  const flags = [];
  
  // F&A rate conflicts
  if (sponsorPolicy.faCap && sponsorPolicy.faCap < institutionConfig.faRates.onCampusResearch.rate * 100) {
    flags.push(`Sponsor caps F&A at ${sponsorPolicy.faCap}% - below institutional rate of ${institutionConfig.faRates.onCampusResearch.rate * 100}%`);
  }
  
  // F&A base conflicts
  if (sponsorPolicy.faBase && sponsorPolicy.faBase !== institutionConfig.faRates.onCampusResearch.base) {
    flags.push(`Sponsor uses ${sponsorPolicy.faBase} base - institutional rate is ${institutionConfig.faRates.onCampusResearch.base}-based`);
  }
  
  // Cost sharing conflicts
  if (sponsorPolicy.voluntaryCostSharing && institutionConfig.policies.costSharingPolicy.includes("Discouraged")) {
    flags.push("Sponsor mentions voluntary cost sharing - check institutional policy before committing");
  }
  
  // Equipment threshold conflicts
  if (sponsorPolicy.equipmentThreshold && sponsorPolicy.equipmentThreshold !== institutionConfig.policies.equipmentThreshold) {
    flags.push(`Sponsor equipment threshold ($${sponsorPolicy.equipmentThreshold}) differs from institutional threshold ($${institutionConfig.policies.equipmentThreshold})`);
  }
  
  // Subaward threshold conflicts
  if (sponsorPolicy.subawardThreshold && sponsorPolicy.subawardThreshold !== institutionConfig.policies.subawardMTDCThreshold) {
    flags.push(`Sponsor subaward F&A threshold differs from institutional policy`);
  }
  
  return flags;
};

6. Export Capabilities

Generate exportable checklists including:

  • All deadlines with dates and notes
  • Required documents checklist
  • Compliance requirements
  • Budget considerations with institutional rates
  • Workflow stage checklist
  • Institutional contacts
  • Current rate reference
javascript
const generateChecklistText = (data, institutionConfig) => {
  let text = `GRANT PROPOSAL CHECKLIST\n`;
  text += `${data.title}\n`;
  text += `Sponsor: ${data.sponsor}\n`;
  text += `Institution: ${institutionConfig.name}\n`;
  text += `Generated: ${new Date().toLocaleDateString()}\n`;
  text += `\n${'='.repeat(80)}\n\n`;

  // Policy Flags
  if (data.policy_flags?.length > 0) {
    text += `⚠️  POLICY CONSIDERATIONS:\n`;
    data.policy_flags.forEach(flag => {
      text += `  ! ${flag}\n`;
    });
    text += `\n`;
  }

  // Deadlines
  text += `DEADLINES:\n`;
  data.deadlines.forEach(d => {
    text += `  [ ] ${d.type}: ${d.date}${d.notes ? ` (${d.notes})` : ''}\n`;
  });
  text += `\n`;

  // Budget Considerations
  text += `BUDGET CONSIDERATIONS:\n`;
  text += `  [ ] Review budget maximum: ${data.budget.max_total}\n`;
  text += `  [ ] Confirm F&A policy: ${data.budget.indirect_cost_policy}\n`;
  text += `  [ ] Cost sharing: ${data.budget.cost_sharing_required}\n`;
  text += `  [ ] Verify institutional F&A rate applies (${institutionConfig.faRates.onCampusResearch.rate * 100}% on-campus research)\n`;
  text += `  [ ] Use current fringe rates\n`;
  text += `\n`;

  // Required Documents
  text += `REQUIRED DOCUMENTS:\n`;
  data.required_documents.forEach(doc => {
    text += `  [ ] ${doc}\n`;
  });
  text += `\n`;

  // Compliance
  if (data.compliance_requirements?.length > 0) {
    text += `COMPLIANCE REQUIREMENTS:\n`;
    data.compliance_requirements.forEach(req => {
      text += `  [ ] ${req}\n`;
    });
    text += `\n`;
  }

  // Workflow Stages
  text += `WORKFLOW STAGES:\n`;
  institutionConfig.workflow.forEach(stage => {
    text += `  [ ] Stage ${stage.stage}: ${stage.name}\n`;
  });
  text += `\n`;

  // Key Contacts
  text += `KEY CONTACTS:\n`;
  if (institutionConfig.contacts.osp.email) {
    text += `  OSP: ${institutionConfig.contacts.osp.email} | ${institutionConfig.contacts.osp.phone}\n`;
  }
  if (institutionConfig.contacts.irb.website) {
    text += `  IRB: ${institutionConfig.contacts.irb.website}\n`;
  }
  if (institutionConfig.contacts.iacuc.website) {
    text += `  IACUC: ${institutionConfig.contacts.iacuc.website}\n`;
  }
  if (institutionConfig.contacts.controller.website) {
    text += `  Controller/Rates: ${institutionConfig.contacts.controller.website}\n`;
  }
  text += `\n`;

  // Current Rates Reference
  text += `CURRENT INSTITUTIONAL RATES (${institutionConfig.fringeRates.fiscalYear}):\n`;
  text += `  F&A: ${institutionConfig.faRates.onCampusResearch.rate * 100}% on-campus research (${institutionConfig.faRates.onCampusResearch.base})\n`;
  text += `  Fringe: Faculty ${institutionConfig.fringeRates.faculty * 100}%, Staff ${institutionConfig.fringeRates.staff * 100}%, GSR ${institutionConfig.fringeRates.graduateStudents * 100}%\n`;
  text += `  Equipment threshold: $${institutionConfig.policies.equipmentThreshold.toLocaleString()}\n`;
  text += `  Subaward MTDC threshold: First $${institutionConfig.policies.subawardMTDCThreshold.toLocaleString()} per subaward\n`;

  return text;
};

Implementation Architecture

React Component Structure

jsx
import React, { useState } from 'react';
import { Upload, FileText, Calendar, DollarSign, CheckSquare, 
         AlertTriangle, Download, Copy, Edit, Settings } from 'lucide-react';

export default function NOFOProcessor() {
  const [file, setFile] = useState(null);
  const [url, setUrl] = useState('');
  const [inputType, setInputType] = useState('pdf');
  const [processing, setProcessing] = useState(false);
  const [results, setResults] = useState(null);
  const [error, setError] = useState(null);
  const [editing, setEditing] = useState(false);
  const [editedResults, setEditedResults] = useState(null);
  const [selectedDeadlineIndex, setSelectedDeadlineIndex] = useState(0);
  const [institutionConfig, setInstitutionConfig] = useState(null);
  const [showConfigModal, setShowConfigModal] = useState(false);
  
  // ... implementation
}

API Integration Pattern

javascript
const analyzeContent = async (type, data, institutionConfig) => {
  const analysisPrompt = buildAnalysisPrompt(institutionConfig);
  
  let messageContent;
  if (type === 'pdf') {
    messageContent = [
      {
        type: 'document',
        source: { type: 'base64', media_type: 'application/pdf', data: data }
      },
      { type: 'text', text: analysisPrompt }
    ];
  } else {
    messageContent = [
      { type: 'text', text: `Fetch and analyze: ${data}\n\n${analysisPrompt}` }
    ];
  }

  const response = await fetch('https://api.anthropic.com/v1/messages', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 4000,
      messages: [{ role: 'user', content: messageContent }]
    })
  });
  
  const responseData = await response.json();
  let cleanedText = responseData.content[0].text.trim();
  cleanedText = cleanedText.replace(/```json\n?/g, '').replace(/```\n?$/g, '');
  return JSON.parse(cleanedText);
};

const buildAnalysisPrompt = (config) => {
  return `Analyze this grant solicitation and extract information.

INSTITUTIONAL CONTEXT:
Institution: ${config.name}
Current F&A Rates:
- On-campus Research: ${config.faRates.onCampusResearch.rate * 100}% ${config.faRates.onCampusResearch.base}
- Off-campus: ${config.faRates.offCampusResearch.rate * 100}% ${config.faRates.offCampusResearch.base}
- Instruction: ${config.faRates.instruction.rate * 100}% ${config.faRates.instruction.base}

Fringe Benefit Rates (${config.fringeRates.fiscalYear}):
- Faculty: ${config.fringeRates.faculty * 100}%
- Staff: ${config.fringeRates.staff * 100}%
- Graduate Students: ${config.fringeRates.graduateStudents * 100}%

Key Policies:
- Equipment threshold: $${config.policies.equipmentThreshold}
- Subaward F&A: First $${config.policies.subawardMTDCThreshold} per subaward
- Cost sharing: ${config.policies.costSharingPolicy}

IMPORTANT: Check if sponsor's F&A policy conflicts with institutional rates.

Respond ONLY with valid JSON (no markdown, no preamble):
{
  "title": "Full title of the solicitation",
  "sponsor": "Funding agency name",
  "program": "Program or mechanism name",
  "deadlines": [
    {"type": "Type", "date": "YYYY-MM-DD", "notes": "optional"}
  ],
  "eligibility": {
    "institution_types": [],
    "pi_requirements": "",
    "geographic_restrictions": "",
    "other": ""
  },
  "budget": {
    "max_total": "",
    "max_per_year": "",
    "indirect_cost_policy": "",
    "cost_sharing_required": "",
    "restrictions": []
  },
  "required_documents": [],
  "page_limits": [{"document": "", "limit": ""}],
  "compliance_requirements": [],
  "special_requirements": [],
  "policy_flags": [],
  "recommended_resources": [],
  "helpful_hints": []
}`;
};

PDF Handling

javascript
const processPDF = async (file) => {
  const base64Data = await new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result.split(',')[1]);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
  return analyzeContent('pdf', base64Data, institutionConfig);
};

Clipboard Operations with Fallback

javascript
const copyToClipboard = (text) => {
  if (navigator.clipboard && navigator.clipboard.writeText) {
    navigator.clipboard.writeText(text)
      .then(() => alert('Copied!'))
      .catch(() => fallbackCopy(text));
  } else {
    fallbackCopy(text);
  }
};

const fallbackCopy = (text) => {
  const textArea = document.createElement('textarea');
  textArea.value = text;
  textArea.style.position = 'fixed';
  textArea.style.left = '-999999px';
  document.body.appendChild(textArea);
  textArea.select();
  document.execCommand('copy');
  document.body.removeChild(textArea);
};

UI Components

Essential Sections

  1. Institution Configuration: Setup modal/section for rates and policies
  2. Input Section: Toggle between PDF upload and URL input
  3. Processing Indicator: Animated spinner with status message
  4. Policy Conflict Warnings: Highlighted alerts at top
  5. Visual Timeline: Chronological display of stages with dates
  6. Organized Results: Cards for each extraction category
  7. Edit Mode: Editable fields for all extracted data
  8. Multiple Deadline Selection: Radio buttons for timeline target
  9. Export Actions: Copy and Download buttons

Configuration UI Component

jsx
const InstitutionConfigModal = ({ config, onSave, onClose }) => (
  <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
    <div className="bg-white rounded-lg p-6 max-w-2xl max-h-[90vh] overflow-y-auto">
      <h2 className="text-xl font-bold mb-4">Institution Configuration</h2>
      
      <div className="space-y-4">
        <div>
          <label className="block font-semibold mb-1">Institution Name</label>
          <input type="text" className="w-full border rounded p-2" />
        </div>
        
        <div className="border-t pt-4">
          <h3 className="font-semibold mb-2">F&A Rates</h3>
          {/* Rate input fields */}
        </div>
        
        <div className="border-t pt-4">
          <h3 className="font-semibold mb-2">Fringe Benefit Rates</h3>
          {/* Fringe rate input fields */}
        </div>
        
        <div className="border-t pt-4">
          <h3 className="font-semibold mb-2">Policy Thresholds</h3>
          {/* Policy threshold input fields */}
        </div>
        
        <div className="border-t pt-4">
          <h3 className="font-semibold mb-2">Key Contacts</h3>
          {/* Contact input fields */}
        </div>
      </div>
      
      <div className="flex justify-end gap-2 mt-6">
        <button onClick={onClose} className="px-4 py-2 border rounded">Cancel</button>
        <button onClick={onSave} className="px-4 py-2 bg-blue-600 text-white rounded">Save</button>
      </div>
    </div>
  </div>
);

Tailwind CSS Classes

jsx
// Warning box for policy conflicts
<div className="bg-amber-50 border border-amber-300 rounded-lg p-4">

// Timeline milestone
<div className="flex items-center gap-3 p-3 bg-blue-50 rounded-lg">

// Section card
<div className="bg-white rounded-lg shadow-lg p-6 mb-6">

// Action button
<button className="flex items-center gap-2 bg-indigo-600 text-white py-2 px-4 rounded-lg hover:bg-indigo-700">

// Configuration button
<button className="flex items-center gap-2 bg-gray-600 text-white py-2 px-4 rounded-lg hover:bg-gray-700">
  <Settings className="w-4 h-4" />
  Configure Institution
</button>

Finding Institutional Rate Information

Common Sources for F&A Rates

  1. Institution's Controller's Office website - Search "[Institution] indirect cost rates" or "F&A rates"
  2. Office of Sponsored Programs - Often has proposal preparation guides with current rates
  3. Federal Rate Agreement - The actual negotiated agreement document
  4. Research Administration website - May have rate sheets or budget preparation tools

Common Sources for Fringe Rates

  1. Budget Office - Often publishes annual fringe rate tables
  2. HR/Benefits Office - May have rate breakdowns by employee category
  3. Proposal Preparation Guidelines - Usually include current fringe rates
  4. Controller's Office - Cost accounting section

Common Sources for Policies

  1. Sponsored Programs Policy Manual - Comprehensive policy documentation
  2. Proposal Preparation Checklist - Institution-specific requirements
  3. Pre-Award Handbook - Detailed guidance documents
  4. Research Compliance Office - For IRB, IACUC, IBC policies

Federal Defaults (If Institution Rates Unknown)

If institutional rates are not available, these federal defaults can be used as placeholders:

  • Equipment threshold: $5,000 (federal standard, though many institutions use $5,000-$10,000)
  • Subaward MTDC threshold: $25,000 (federal standard)
  • F&A rates vary significantly; 50% is a rough median for research universities

Testing Considerations

  • Test with native digital PDFs (not scanned images)
  • Verify date parsing handles various formats
  • Check timeline generation for edge cases (past deadlines, very short timelines)
  • Validate JSON parsing with various response formats
  • Test clipboard operations across browsers
  • Verify configuration persistence (if using browser storage)

Limitations

  • Cannot read tables in scanned/image-based PDFs
  • Requires publicly accessible URLs for web fetch
  • No persistent storage between sessions (unless implemented)
  • Manual verification always recommended
  • Does not submit proposals or write content
  • Institutional rates must be manually configured

Customization Checklist

When implementing for a specific institution:

  • Gather all F&A rates and effective dates
  • Collect fringe benefit rates by employee category
  • Document equipment capitalization threshold
  • Confirm subaward MTDC threshold
  • Define cost sharing policy
  • Map internal workflow stages and timing
  • Collect key contact information
  • Identify any institution-specific requirements

Version Information

  • Skill Version: 1.0 (General)
  • Last Updated: January 2026
  • Compatibility: Any research institution