Development of AI System for Automation of Permits and Licenses Issuance
Permitting activities of government agencies is one of the most bureaucratically loaded processes. Construction permits, medical practice licenses, trade permits — each type has its own regulations, document package, deadlines, and refusal grounds. An AI system automates completeness checking, compliance verification, and decision generation.
Permit System Architecture
The permit issuance process consists of several stages, each automated differently:
Application Receipt and Registration — verification of applicant correctness (ESIA), registration with number assignment, calculation of review deadline per administrative regulations.
Completeness Check — AI verifies presence and compliance of each document from the list provided by regulations. Automatic notification to applicant about missing documents.
Inter-agency Requests — automatic formation and sending of SMEV requests to related agencies (Tax Service, State Registry, Interior Ministry, SROs, etc.).
Legal Review — verification of application compliance with regulatory requirements, identification of refusal grounds.
Decision Generation — draft permit or motivated refusal.
Document Completeness Check
class DocumentRequirement(BaseModel):
doc_type: str # document type
is_mandatory: bool
conditions: list[str] # under what conditions required
validity_period_days: int | None # document validity period
acceptable_formats: list[str] # formats (pdf, jpg, ...)
issuing_authority: str | None # issued by
class CompletenessCheck(BaseModel):
is_complete: bool
missing_documents: list[str]
expired_documents: list[str] # documents with expired validity
suspicious_documents: list[str] # suspicious / unreadable
can_obtain_via_smev: list[str] # what can be requested inter-agency
def check_completeness(
application: Application,
uploaded_docs: list[UploadedDocument],
regulation: PermitRegulation
) -> CompletenessCheck:
results = []
for req in regulation.required_documents:
# Check applicability condition
if not req.applies_to(application):
continue
# Find document among uploads
matched = find_matching_document(uploaded_docs, req)
if matched:
# Check validity, authenticity (QR-code, signature)
validity = check_document_validity(matched, req)
results.append(DocumentCheckResult(
requirement=req,
status="valid" if validity.ok else "expired",
document=matched
))
elif req.is_mandatory and not req.can_be_obtained_via_smev():
results.append(DocumentCheckResult(
requirement=req,
status="missing"
))
return CompletenessCheck.from_results(results)
Data Extraction from Documents
Applicants upload documents in different formats: PDF scans, photos, digital documents with qualified signatures. Extraction tasks:
Property Documents: extraction of address, area, purpose, owner — for verification with State Registry.
Medical Licenses and Certificates: specialization, validity period, professional name — for verification in medical worker registry.
Company Registration Extracts: registration date, industry codes, founders — automatically requested from Tax Service via SMEV, extraction from response.
Technical Documents: structured extraction of technical parameters for comparison with standards.
class BuildingPermitData(BaseModel):
applicant_inn: str
object_address: str
land_plot_cadastral: str # cadastral number
construction_type: str # new construction / reconstruction
object_category: str # residential / non-residential / linear
total_area: float | None
floors: int | None
project_organization: str # project organization
project_sro_number: str | None # SRO approval number
Legal Review and Refusal Grounds
For each permit type, system maintains knowledge base of refusal grounds (from law and administrative regulations). LLM checks application against each ground:
def legal_review(application: Application, docs: list) -> LegalReviewResult:
grounds_for_refusal = load_refusal_grounds(application.permit_type)
checks = []
for ground in grounds_for_refusal:
result = llm.parse(
f"""Check if refusal ground applies:
Ground: {ground.description}
Legal reference: {ground.legal_reference}
Application data: {application.to_text()}
Documents: {summarize_docs(docs)}
Answer: ground applies (yes/no/requires clarification) and explain.""",
response_format=GroundCheck
)
checks.append(result)
refusals = [c for c in checks if c.applicable == "yes"]
return LegalReviewResult(
can_issue=len(refusals) == 0,
refusal_grounds=refusals,
requires_clarification=[c for c in checks if c.applicable == "requires_clarification"],
draft_decision=generate_decision_draft(application, refusals)
)
Inter-agency Interaction
SMEV requests are formed automatically based on application data. System knows what information can be requested for each permit type:
| Permit Type | Source | Requested Information |
|---|---|---|
| Construction | State Registry | Rights to land plot, encumbrances |
| Construction | Tax Service | Legal entity data |
| Medical License | Health Ministry | Medical workers registry |
| Retail Trade | Consumer Protection | Directives, violations |
| Alcohol License | Federal Alcohol Agency | License history, violations |
Applicant Notifications and Personal Cabinet
Applicant tracks status in real-time: "Documents accepted", "Inter-agency requests sent", "Under review", "Decision made". All notifications via state services portal or email/SMS. Automatic notification about need to submit documents with detailed specification of what and in what format.
Implementation Timeline
Month 1-2: Develop completeness check module for one permit type (pilot)
Month 3-4: Integration with SMEV (State Registry, Tax Service), applicant personal cabinet
Month 5-6: Legal review module, decision draft generation
Month 7-8: Add second permit type, administrative analytics
Month 9-10: Full coverage of agency permit types, EPGU integration







