Contract Extraction Assistant Guide

Overview

The Contract Extraction Assistant (ID: f56c1fcc-564b-48af-abc4-6a0ff596960b) is designed to extract structured information from legal contracts using the Nordic Solar contract schema. It uses Gemini Flash 2.5 to analyze documents and extract key contract details with audit trails.

How to Call the Assistant

API Endpoint

POST /vac/assistant/f56c1fcc-564b-48af-abc4-6a0ff596960b

Minimal CURL Example (Simplified - No Model Class Needed!)

The backend now automatically determines the correct model class based on the schema file:

curl -X POST "http://localhost:1956/vac/assistant/f56c1fcc-564b-48af-abc4-6a0ff596960b" \
  -H "Content-Type: application/json" \
  -d '{
    "user_input": "Please extract the contract from Arrendamento art 514.pdf",
    "isStreaming": false,
    "selectedItems": [
      {
        "type": "file",
        "path": "OneDrive_1_02-09-2025/Arrendamento art 514.pdf",
        "name": "Arrendamento art 514.pdf"
      }
    ],
    "emissaryConfig": {
      "tools": ["file-browser", "structured_extraction"],
      "toolConfigs": {
        "file-browser": {
          "bucketUrl": "aitana-nordic-solar-bucket"
        },
        "structured_extraction": {
          "pydantic_file": "contract_extraction_schema"
        }
      },
      "currentUser": {
        "email": "mark@aitanalabs.com",
        "displayName": "Mark"
      }
    }
  }'

Note: No need to specify pydantic_model anymore! The backend automatically maps:

  • contract_extraction_schemaContractExtraction (Nordic Solar)
  • generic_contract_schemaGenericContractExtraction
  • invoice_extraction_schemaInvoiceExtraction
  • meeting_minutes_schemaMeetingMinutesExtraction
  • financial_statement_schemaFinancialStatementExtraction

Alternative Schema Examples

Generic Contract (Not Nordic Solar Specific)

"structured_extraction": {
  "pydantic_file": "generic_contract_schema"
}

Invoice Extraction

"structured_extraction": {
  "pydantic_file": "invoice_extraction_schema"
}

Meeting Minutes

"structured_extraction": {
  "pydantic_file": "meeting_minutes_schema"
}

Custom JSON Schema

"structured_extraction": {
  "pydantic_file": "custom",
  "schema": {
    "type": "object",
    "properties": {
      "vendor": {
        "type": "string",
        "description": "Vendor name"
      },
      "amount": {
        "type": "number",
        "description": "Invoice amount"
      },
      "due_date": {
        "type": "string",
        "description": "Payment due date"
      }
    },
    "required": ["vendor", "amount"]
  }
}

The assistant will:

  1. Use file-browser tool to extract content from the specified file in the GCS bucket
  2. Apply the appropriate structured extraction schema (auto-detecting the model class)
  3. Return the extracted data as structured JSON in the response metadata

Full Request Structure (Optional)

If you want to override the Firebase config or call without Firebase:

{
  "user_input": "[Your contract text or reference to uploaded file]",
  "isStreaming": false,
  "emissaryConfig": {
    "assistantId": "f56c1fcc-564b-48af-abc4-6a0ff596960b",
    "name": "Contract Analyzer",
    "initialInstructions": "You are an expert at analyzing legal contracts and extracting structured information. Focus on identifying parties, obligations, dates, and financial terms.",
    "tools": ["structured_extraction", "file-browser"],
    "toolConfigs": {
      "structured_extraction": {
        "pydantic_file": "contract_extraction_schema",
        "pydantic_model": "ContractExtraction",
        "examples": [/* optional examples array */]
      }
    },
    "currentUser": {
      "email": "user@nordicsolar.com",
      "displayName": "Contract Analyst"
    }
  }
}

Providing Examples (Optional)

You can provide examples to improve extraction quality. Here’s a complete example showing the full expected output format:

Complete Example Output Format

"examples": [
  {
    // Basic contract information
    "contract_type": "Share purchase agreement",
    "contract_type_audit": "SHARE PURCHASE AGREEMENT",
    "primary_legal_entity": "Nordic Solar A/S",
    "primary_legal_entity_audit": "Nordic Solar A/S (the 'Buyer')",
    "other_party_companies": ["Better Energy Management A/S", "P&B Partner ApS"],
    "first_party": "Nordic Solar A/S",
    "first_party_audit": "between Nordic Solar A/S",
    "second_party": "Better Energy Management A/S",
    "second_party_audit": "and Better Energy Management A/S (the 'Seller')",
    "projects_mentioned": ["Nees Project", "Vollerup Project"],
    
    // Important dates
    "latest_signing_date": "2019-06-28",
    "latest_signing_date_audit": "entered into as of 28th June 2019",
    "contract_start_date": "2019-01-01",
    "contract_start_date_audit": "with effect from 1 January 2019",
    "expiration_renewal_date": null,
    "expiration_renewal_date_audit": null,
    
    // Contract conditions
    "has_contingent_liability": true,
    "change_of_control_conditions": false,
    "change_of_control_audit": "change of control of the Companies caused by the Transaction",
    
    // Financial information
    "contract_amount": "Variable",
    "contract_amount_audit": "the Purchase Price as adjusted with the Net Debt as per the Effective Date",
    "currency": "DKK",
    "currency_audit": "DKK",
    
    // Document metadata
    "is_word_document": false,
    
    // Contract details
    "contract_scope": "Sale and purchase of 100% of the shares in P&B Solpark 8 K/S, P&B Solpark 9 K/S and P&B Solpark 11 K/S",
    "contract_scope_audit": "sale of 100% of the shares in P&B Solpark 8 K/S, P&B Solpark 9 K/S and P&B Solpark 11 K/S",
    "contract_subject": "Share purchase for solar park companies",
    "contract_subject_audit": "SHARE PURCHASE AGREEMENT regarding the sale of shares",
    "additional_information": null,
    
    // Complete obligations list
    "obligations": [
      {
        "obligation_type": "Closing Action",
        "obligation_type_audit": "At Closing",
        "clause_number": "6.1",
        "clause_title": "Execution date",
        "clause_text": "On 28th June 2019, the Parties shall meet and execute the Agreement at the Seller's office ('Closing Date').",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-28",
        "milestone_condition": null
      },
      {
        "obligation_type": "Closing Action",
        "obligation_type_audit": "At Closing the Parties shall",
        "clause_number": "7.1.1",
        "clause_title": "Sign O&M agreement",
        "clause_text": "At Closing the Parties shall sign (or cause to have signed by the relevant party, as applicable) the following documents: 7.1.1 the O&M Agreement",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-28",
        "milestone_condition": null
      },
      {
        "obligation_type": "Closing Action",
        "obligation_type_audit": "At Closing the Parties shall",
        "clause_number": "7.1.2",
        "clause_title": "Sign the addendum to the EPC contract",
        "clause_text": "At Closing the Parties shall sign (or cause to have signed by the relevant party, as applicable) the following documents: 7.1.2 an addendum to the EPC contract",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-28",
        "milestone_condition": null
      },
      {
        "obligation_type": "Closing Action",
        "obligation_type_audit": "At Closing, the Seller shall",
        "clause_number": "7.2.2",
        "clause_title": "Sign undated minutes of extraordinary general meetings",
        "clause_text": "At Closing, subject to the Buyer's fulfilment of its obligations provided for in sec. 7.1 and 7.3, the Seller shall: 7.2.2 sign undated minutes of extraordinary general meetings of the Companies for the purposes of 1) changing the name of the Companies to the names instructed by the Buyer, 2) changing the Companies' address to the address instructed by the Buyer, 3) resigning the current directors of the Companies and appointing new directors of the Companies as instructed by the Buyer, and 4) any other corporate changes that might be necessary for Closing as instructed by the Buyer",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-28",
        "milestone_condition": null
      },
      {
        "obligation_type": "Closing Action",
        "obligation_type_audit": "At Closing, the Seller shall",
        "clause_number": "7.2.3",
        "clause_title": "Fund's consent to the change of control",
        "clause_text": "At Closing, subject to the Buyer's fulfilment of its obligations provided for in sec. 7.1 and 7.3, the Seller shall: 7.2.3 deliver documentation of the Fund's consent to the change of control of the Companies caused by the Transaction",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-28",
        "milestone_condition": null
      },
      {
        "obligation_type": "Closing Action",
        "obligation_type_audit": "At Closing, the Buyer shall",
        "clause_number": "7.3.2",
        "clause_title": "Pay the Preliminary Payment",
        "clause_text": "At Closing, subject to the Seller's fulfilment of its obligations provided for in sec. 7.1 and 7.2, the Buyer shall: 7.3.2 pay the Preliminary Payment to the Seller's bank account: 2211-6899477969",
        "amount": "Variable",
        "amount_audit": "the Preliminary Payment",
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-28",
        "milestone_condition": null
      },
      {
        "obligation_type": "CS",
        "obligation_type_audit": "Conditions Subsequent",
        "clause_number": "8.2.1",
        "clause_title": "Documents required for the fund to consent",
        "clause_text": "The conditions in the following sec. 8.2-8.4 (the 'Conditions Subsequent') shall be fulfilled no later than on the Long Stop Date. The Parties shall 8.2.1 sign any documents which the Fund requires to be signed in order to provide its consent to the Transaction",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "NA",
        "milestone_condition": "Other"
      },
      {
        "obligation_type": "CS",
        "obligation_type_audit": "Conditions Subsequent",
        "clause_number": "8.2.2",
        "clause_title": "Sign Land Lease Agreements",
        "clause_text": "The Parties shall cause to have signed by the relevant parties, an amendment to the Land Lease Agreements (i) specifying the annual rent payment for the Nees Project of DKK [amount] and for the Vollerup Project of DKK [amount] to be paid under the Land Lease Agreement and (ii) including a confirmation from the landlords that the Companies are not in breach of the Land Lease Agreements",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "NA",
        "milestone_condition": "Land rights"
      },
      {
        "obligation_type": "CS",
        "obligation_type_audit": "Conditions Subsequent",
        "clause_number": "8.3.1",
        "clause_title": "Pay adjusted Purchase Price",
        "clause_text": "Subject to (i) Buyer's receipt of an updated due diligence report from Bird&Bird regarding the Companies and the Projects in a form acceptable to the Buyer and (ii) the Seller's fulfilment of its obligations provided for in sec. 8.2 and 8.4, the Buyer shall: 8.3.1 pay the Purchase Price as adjusted with the Net Debt as per the Effective Date and deducted the Preliminary Payment and the Retention to the Seller's bank account",
        "amount": "Variable",
        "amount_audit": "the Purchase Price as adjusted with the Net Debt",
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "NA",
        "milestone_condition": "Other"
      },
      {
        "obligation_type": "CS",
        "obligation_type_audit": "Conditions Subsequent",
        "clause_number": "8.4.1",
        "clause_title": "Deliver the Companies' original register",
        "clause_text": "Subject to the Buyer's fulfilment of its obligations provided for in sec. 8.2 and 8.3, the Seller shall: 8.4.1 deliver the Companies' original register of shareholders with the Buyer duly registered as owner of the Shares as per the Closing Date, free and clear of all Third Party Rights save for securities provided to the Fund according to the Loan Agreements",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "NA",
        "milestone_condition": "Other"
      },
      {
        "obligation_type": "Reporting obligation",
        "obligation_type_audit": "draft Closing Memorandum",
        "clause_number": "7.6",
        "clause_title": "Draft of closing memo latest 2 days before closing",
        "clause_text": "Preparation of Closing. No later than 2 (two) Business Days before the Closing Date, the Seller shall send to the Buyer a draft Closing Memorandum together with draft versions of all documents, including the minutes of the general meeting, that shall be executed or delivered on Closing",
        "amount": null,
        "amount_audit": null,
        "is_recurring": false,
        "recurrence_frequency": null,
        "due_date": "2019-06-26",
        "milestone_condition": null
      }
    ],
    
    // Technical Analysis Fields
    "technical_analysis": "Several areas of uncertainty were identified: 1) The Purchase Price is referenced multiple times but never specified with an exact amount, only as 'adjusted with Net Debt' (clauses 8.3.1, 8.4). 2) The Long Stop Date mentioned in section 8.1 is not defined elsewhere in the visible contract. 3) Land lease payment amounts in clause 8.2.2 appear redacted. 4) The distinction between 'Closing' (section 7) and 'Completion' (section 8) could be clearer. 5) The Retention amount mentioned in 8.3.1 is not defined.",
    
    "extraction_confidence_score": 78.5,
    
    "extraction_issues": [
      "Purchase Price amount not specified - only referenced as variable",
      "Long Stop Date referenced but not defined",
      "Land lease amounts appear redacted in clause 8.2.2",
      "Fund entity not clearly identified",
      "Loan Agreement details referenced but not included"
    ],
    
    "data_quality_flags": {
      "contract_amount": "Referenced as 'Purchase Price' but no numerical value provided",
      "expiration_renewal_date": "No contract end date specified - appears to be transaction-based",
      "other_party_companies": "Fund entity mentioned but not specifically named"
    }
  }
]

Key Extraction Fields

Contract Information

  • contract_type - Type from predefined list (e.g., “Service agreement”, “Share purchase agreement”)
  • primary_legal_entity - Nordic Solar entity from dropdown
  • first_party / second_party - Full legal names with suffixes
  • contract_amount - Numerical value or “Variable” or “NA”
  • currency - Three-letter code (EUR, USD, DKK, etc.)
  • latest_signing_date - YYYY-MM-DD format
  • contract_start_date - When obligations begin
  • expiration_renewal_date - When contract ends
  • change_of_control_conditions - true/false/null
  • contract_scope - Brief description of services/goods

Obligations Array

Each obligation includes:

  • obligation_type - From predefined list
  • clause_number - As it appears in contract
  • clause_title - Short descriptive title (max 100 chars)
  • clause_text - Full text of the obligation
  • amount - If monetary obligation
  • is_recurring - true/false
  • recurrence_frequency - If recurring: “Monthly”, “Quarterly”, “Bi-annually”, “Annually”
  • due_date - YYYY-MM-DD or “NA” if event-driven
  • milestone_condition - Triggering event if applicable

Audit Fields

Most fields have corresponding _audit fields that capture the exact source text:

  • contract_type_audit
  • primary_legal_entity_audit
  • first_party_audit
  • second_party_audit
  • contract_amount_audit
  • currency_audit
  • etc.

Technical Analysis Fields

These fields capture extraction quality and issues:

  • technical_analysis - Detailed narrative of confusion, questions, and uncertainties
  • extraction_confidence_score - 0-100 score based on:
    • Contract language clarity (30%)
    • Information completeness (25%)
    • Consistency across clauses (20%)
    • Presence of defined terms (15%)
    • Extraction certainty (10%)
  • extraction_issues - List of specific problems encountered
  • data_quality_flags - Dictionary mapping field names to their quality issues

Response Structure

{
  "answer": "Natural language analysis of the contract...",
  "metadata": {
    "structured_output": {
      "contract_type": "Service agreement",
      "contract_type_audit": "SERVICE AGREEMENT",
      "primary_legal_entity": "Nordic Solar A/S",
      "primary_legal_entity_audit": "Nordic Solar A/S ('Service Provider')",
      "first_party": "Nordic Solar A/S",
      "first_party_audit": "between Nordic Solar A/S",
      "second_party": "ABC Corporation",
      "second_party_audit": "and ABC Corporation ('Client')",
      "contract_amount": "50000",
      "contract_amount_audit": "EUR 50,000 annually",
      "currency": "EUR",
      "currency_audit": "EUR 50,000",
      "contract_start_date": "2025-02-01",
      "contract_start_date_audit": "shall commence on February 1, 2025",
      "expiration_renewal_date": "2027-01-31",
      "expiration_renewal_date_audit": "expiring on January 31, 2027",
      "obligations": [
        {
          "obligation_type": "Reporting obligation",
          "obligation_type_audit": "monthly performance reports",
          "clause_title": "Monthly performance reports",
          "is_recurring": true,
          "recurrence_frequency": "Monthly"
        }
      ],
      // ... other fields
    },
    "extraction_metadata": {
      "schema_used": "ContractExtraction",
      "model": "gemini-2.5-flash",
      "success": true
    }
  }
}

Best Practices

1. Provide Clear Contract Text

  • Upload the full contract PDF or provide complete text
  • Ensure OCR quality for scanned documents
  • Include all schedules and attachments referenced

2. Use File Browser Tool

  • If referencing an uploaded file:
    "tools": ["file-browser", "structured_extraction"]
    
  • The file-browser will extract content first, then structured extraction runs

3. Minimal Examples

  • Don’t send entire CSV datasets
  • Provide 1-2 clean JSON examples showing expected format
  • Focus on the most complex obligation types as examples

4. Handle Special Cases

  • Variable amounts: Use “Variable” or “NA - to be calculated”
  • Event-driven dates: Use “NA” with milestone_condition
  • Multiple projects: List as array in projects_mentioned
  • Missing entities: Check if in Nordic Solar entity list first

Testing the Extraction

Python Test Script

import requests
import json

BASE_URL = "http://localhost:1956"
ASSISTANT_ID = "f56c1fcc-564b-48af-abc4-6a0ff596960b"

def extract_contract(contract_text):
    url = f"{BASE_URL}/vac/assistant/{ASSISTANT_ID}"
    
    payload = {
        "user_input": contract_text,
        "isStreaming": False,
        "emissaryConfig": {
            "assistantId": ASSISTANT_ID,
            "name": "Contract Analyzer",
            "initialInstructions": "Extract contract information",
            "tools": ["structured_extraction"],
            "toolConfigs": {
                "structured_extraction": {
                    "pydantic_file": "contract_extraction_schema",
                    "pydantic_model": "ContractExtraction"
                }
            },
            "currentUser": {
                "email": "test@nordicsolar.com",
                "displayName": "Test User"
            }
        }
    }
    
    response = requests.post(url, json=payload)
    if response.status_code == 200:
        data = response.json()
        return data.get("metadata", {}).get("structured_output")
    return None

Common Obligation Types

  • Closing Action - Actions required at contract closing
  • CS (Conditions Subsequent) - Conditions to fulfill after closing
  • CP (Conditions Precedent) - Conditions before closing
  • Reporting obligation - Regular reporting requirements
  • Termination notice - Notice periods for termination
  • Milestone payment - Payments tied to milestones
  • Covenant - Ongoing obligations
  • Change of control - Restrictions on ownership changes

Troubleshooting

Low Extraction Quality

  • Provide 1-2 relevant examples in toolConfigs
  • Ensure contract text is complete and readable
  • Check that all referenced schedules are included

Missing Nordic Solar Entity

  • Entity must be in the predefined list
  • If not found, it will be listed in other_party_companies

Date Formatting Issues

  • Always use YYYY-MM-DD format
  • Use “NA” for event-driven dates
  • Specify milestone_condition when applicable