Shared Models
The AEGIS shared library at shared/src/aegis_shared/ provides Pydantic v2 models, database helpers, and utilities used across all Python services. Every service depends on this library via a Poetry path dependency.
Location and Structure
shared/
├── pyproject.toml # Library metadata and dependencies
└── src/
└── aegis_shared/
├── __init__.py
├── models/
│ ├── __init__.py # Re-exports all public models
│ ├── common.py # AegisBase, AegisEntity, TenantEntity, enums
│ ├── oilgas.py # Oil & gas domain entities
│ ├── agent.py # Agent config, state, messages
│ ├── compliance.py # Compliance status and matrix models
│ ├── checklist.py # Filing checklist workflow models
│ ├── rules.py # Rule versioning and lifecycle models
│ ├── entity_resolution.py # ResolvedEntity + MatchedOn (R34 entity resolution)
│ ├── events.py # Operational event system models
│ └── event_types.py # Custom event type builder models
└── db/
├── postgres.py # PostgresPool (asyncpg wrapper)
├── redis.py # RedisManager (async Redis wrapper)
└── kafka.py # Kafka producer managerBase Classes (common.py)
All models derive from one of three base classes:
AegisBase
The root base class for all Pydantic models. Provides common configuration:
class AegisBase(BaseModel):
model_config = ConfigDict(
from_attributes=True, # Allow creating from ORM objects / dicts
populate_by_name=True, # Allow field aliases
str_strip_whitespace=True, # Auto-strip string whitespace
)Use AegisBase for:
- API request/response models
- Value objects and DTOs
- Any model that does not need an
idor timestamps
AegisEntity
For persistent entities that need a unique identifier and timestamps:
class AegisEntity(AegisBase):
id: UUID = Field(default_factory=uuid4)
created_at: datetime = Field(default_factory=datetime.utcnow)
updated_at: datetime = Field(default_factory=datetime.utcnow)TenantEntity
For entities scoped to a specific tenant (multi-tenancy support):
class TenantEntity(AegisEntity):
tenant_id: strMost domain entities (wells, leases, operators, etc.) extend TenantEntity.
Shared Enums (common.py)
The common module defines core enums used across multiple services:
| Enum | Values | Used By |
|---|---|---|
AgentType | rule_37, rule_32, compliance_monitor, flaring_monitor | Orchestration engine, agent configs |
ExecutionStatus | pending, running, awaiting_hitl, completed, failed, cancelled | Orchestration engine, approval service |
ApprovalStatus | pending, approved, rejected, modified | Approval service |
HITLCheckpointType | pre_filing, data_validation, cost_threshold, regulatory_submission, exception_request | Approval service, orchestration engine |
Model Files
oilgas.py — Oil and Gas Domain Entities
The largest model file, containing all RRC regulatory domain entities:
| Model | Parent | Key Fields |
|---|---|---|
Operator | TenantEntity | name, rrc_operator_id, p5_number |
Field | TenantEntity | name, rrc_field_id, district, county |
Formation | TenantEntity | name, depth_top_ft, depth_base_ft |
Lease | TenantEntity | name, rrc_lease_id, operator_id, field_id |
Well | TenantEntity | api_number, well_name, well_type, status, spacing distances, production data |
Permit | TenantEntity | permit_number, permit_type, status, Rule 37 exception details |
Regulation | AegisBase | rule_id, title, requirements, related_forms |
Hearing | TenantEntity | docket_number, hearing_type, status, decision details |
Filing | TenantEntity | filing_type, form_number, status, HITL review data |
Equipment | TenantEntity | equipment_type, name, capacity, well/lease associations |
FlaringAuthorization | TenantEntity | authorization_number, max_volume_mcf_per_day, expiration_date |
FlaringEvent | TenantEntity | event_type, cause_category, volumes, repair obligation, RRC/EPA reporting |
Wellpad | TenantEntity | name, pad_id, location |
Facility | TenantEntity | name, facility_type, capacity |
PipelineRoute | TenantEntity | name, diameter_inches, length_miles, from/to facility |
InfrastructureProject | TenantEntity | project_type, name, timeline, gas capture estimates |
Domain-specific enums include WellStatus, WellType, PermitStatus, HearingStatus, FilingStatus, FlaringDispositionCode, EquipmentType, FacilityType, ProjectType, and flare event enums (FlareEventType, FlareEventCauseCategory, FlareEventSource, VolumeSource, RRCReportStatus).
agent.py — Agent Configuration and State
| Model | Parent | Purpose |
|---|---|---|
SkillManifest | AegisBase | Lightweight skill descriptor (id, name, triggers, domain tags) |
HITLPolicy | AegisBase | When HITL approval is required (checkpoint type, reviewer strategy) |
BudgetConfig | AegisBase | Token and cost limits per execution and per day |
AgentConfig | AegisBase | Full agent definition (system prompt, skills, HITL policies, budget) |
Message | AegisBase | Single conversation message (role, content, tool calls) |
HITLCheckpoint | AegisBase | Pending approval checkpoint (state snapshot, reviewer info) |
AgentState | AegisBase | Core state flowing through LangGraph (messages, injected context, active skills, budget tracking) |
compliance.py — Compliance Dashboard
| Model | Parent | Purpose |
|---|---|---|
ComplianceStatus | AegisEntity | Single entity x domain compliance record |
ComplianceSummary | AegisBase | Dashboard summary card counts (overdue, due soon, anomalies) |
ComplianceMatrixRow | AegisBase | One row in the entity x domain matrix |
ComplianceMatrixResponse | AegisBase | Paginated matrix response |
DeadlineChartEntry | AegisBase | Deadline bar chart data point |
ComplianceTrendEntry | AegisBase | Compliance trend line data point |
FilingStatusEntry | AegisBase | Filing status donut chart data point |
FlaringChartEntry | AegisBase | Flaring volume vs authorization chart data point |
Enums: ComplianceDomain (rule_37, rule_32, form_pr, flaring_monitor, epa_oooo), ComplianceStatusCode (compliant, action_needed, overdue, not_applicable, in_review).
checklist.py — Filing Checklist Workflow
| Model | Parent | Purpose |
|---|---|---|
ChecklistItemDefinition | AegisBase | Item template (name, type, completion method, agent/user roles) |
ChecklistTemplate | AegisEntity | Template for a compliance domain’s checklist |
ChecklistItemState | AegisBase | Current state of a checklist item (status, summary, data) |
FilingChecklist | AegisEntity | Checklist instance for entity + domain |
ChecklistArtifact | AegisBase | Generated document or file linked to a checklist item |
CreateChecklistRequest | AegisBase | API request to create a checklist |
UpdateChecklistItemRequest | AegisBase | API request to update an item |
SubmitForReviewRequest | AegisBase | API request to submit for HITL review |
CreateArtifactRequest | AegisBase | API request to create an artifact |
Enums: ChecklistStatus, ChecklistItemStatus, ChecklistItemType, CompletionMethod, ArtifactType, GeneratedBy.
rules.py — Rule Versioning
| Model | Parent | Purpose |
|---|---|---|
RuleVersion | AegisEntity | Immutable versioned rule (rule data, effective date, source) |
FilingRuleSnapshot | AegisBase | Frozen copy of a rule at filing initiation |
RuleChangeAlert | AegisBase | Alert for rule changes affecting in-flight filings |
CreateRuleVersionRequest | AegisBase | API request to create a rule version |
AcknowledgeRuleChangeRequest | AegisBase | API request to acknowledge a rule change |
Enums: RuleType (statewide, field_specific, notice), RuleDomain (spacing, density, flaring, reporting, environmental), RuleStatus, RuleSource.
events.py — Operational Events
| Model | Parent | Purpose |
|---|---|---|
OperationalEvent | TenantEntity | Unified event record for all 5 MVP event types |
DuplicationRule | TenantEntity | Duplication prevention rules per event type |
DuplicationCheckResult | AegisBase | Result of the duplication rules engine check |
Enums: EventType (flare_event, production_interruption, equipment_failure, spill_release, permit_exceedance, custom), Severity, EventStatus, SourceType, DupRuleType, DupAction.
event_types.py — Custom Event Type Builder
| Model | Parent | Purpose |
|---|---|---|
EventTypeDefinition | TenantEntity | Event type with lifecycle management (draft/preview/active/inactive/archived) |
EventTypeFieldDefinition | AegisEntity | A field within an event type form |
ConditionalRule | AegisEntity | Show/hide logic for fields |
GuardRule | AegisEntity | Submission guard rule with versioning |
GuardRuleVersion | AegisBase | Versioned snapshot of a guard rule’s conditions |
Database Helpers (db/)
PostgresPool
Wraps asyncpg with connection pool management:
from aegis_shared.db.postgres import PostgresPool
pg = PostgresPool(dsn="postgresql://aegis:aegis_local@localhost:5432/aegis")
await pg.connect()
# Convenience methods
row = await pg.fetchrow("SELECT * FROM agents WHERE id = $1", agent_id)
rows = await pg.fetch("SELECT * FROM compliance_status WHERE tenant_id = $1", tenant_id)
await pg.execute("INSERT INTO audit_logs (id, event_type) VALUES ($1, $2)", log_id, event_type)
# Direct connection access
async with pg.acquire() as conn:
rows = await conn.fetch("SELECT * FROM agents")
await pg.disconnect()RedisManager
Wraps redis.asyncio with key-value and injection ledger helpers:
from aegis_shared.db.redis import RedisManager
rm = RedisManager(url="redis://localhost:6379")
await rm.connect()
# Key-value operations
await rm.set("key", "value", ex=3600) # with TTL
val = await rm.get("key")
await rm.delete("key")
# Injection ledger (Redis Hash at skill:ledger:{conversation_id})
await rm.ledger_mark("conv-1", "skill:spacing-calc", "1")
has = await rm.ledger_has("conv-1", "skill:spacing-calc") # True
items = await rm.ledger_get_all("conv-1") # {"skill:spacing-calc": "1"}
await rm.disconnect()How to Add New Models
Step 1: Choose the Right File
- Oil and gas domain entities:
oilgas.py - Agent-related models:
agent.py - Compliance dashboard models:
compliance.py - Checklist/filing workflow:
checklist.py - Regulatory rules:
rules.py - Entity-resolution results:
entity_resolution.py - Operational events:
events.py - Event type definitions:
event_types.py - Core enums/base classes:
common.py - Entirely new domain: create a new file
Step 2: Define the Model
Choose the appropriate base class:
# For a request/response DTO
class MyRequest(AegisBase):
entity_id: str
action: str
# For a persistent entity without tenant scope
class MyEntity(AegisEntity):
name: str
status: str = "active"
# For a tenant-scoped persistent entity (most domain objects)
class MyDomainEntity(TenantEntity):
name: str
entity_type: str
data: dict[str, Any] = Field(default_factory=dict)Step 3: Follow Pydantic v2 Conventions
from enum import StrEnum
from datetime import date, datetime
from typing import Any
from uuid import UUID
from pydantic import Field as PydanticField
from aegis_shared.models.common import AegisBase, TenantEntity
class MyStatus(StrEnum):
ACTIVE = "active"
INACTIVE = "inactive"
ARCHIVED = "archived"
class MyEntity(TenantEntity):
# Required fields
name: str
entity_type: str
# Optional fields with None default
description: str | None = None
parent_id: str | None = None
# Enum fields with default
status: MyStatus = MyStatus.ACTIVE
# Date fields
effective_date: date | None = None
expires_at: datetime | None = None
# Collections -- always use Field(default_factory=...)
tags: list[str] = PydanticField(default_factory=list)
metadata: dict[str, Any] = PydanticField(default_factory=dict)
# Numeric fields
score: float | None = None
count: int = 0When the parent class defines a Field import from Pydantic and your model file also needs it, use an alias to avoid shadowing: from pydantic import Field as PydanticField. This pattern is already used in oilgas.py and events.py.
Step 4: Export from init.py
Add your new models to shared/src/aegis_shared/models/__init__.py:
from aegis_shared.models.my_module import MyEntity, MyStatus
__all__ = [
# ... existing exports ...
"MyEntity",
"MyStatus",
]This allows services to import directly from the top-level package:
from aegis_shared.models import MyEntity, MyStatusStep 5: Re-install in Dependent Services
After modifying the shared library, re-install it in any service that uses it:
cd services/orchestration-engine
poetry installSince the shared library is installed with develop = true, Python will use the live source code. However, Poetry needs to know about new dependencies if you added any to the shared pyproject.toml.
Design Principles
-
Models are immutable representations — they describe data shape, not behavior. Business logic belongs in service modules, not model methods.
-
Rule versions are never updated — create a new version instead. This is enforced by the
RuleVersionmodel design and database constraints. -
Use StrEnum for all enumerations — this ensures JSON serialization produces readable strings, not integer codes.
-
Prefer explicit fields over inheritance — AEGIS models use flat field definitions rather than deep inheritance hierarchies.
AegisBase -> AegisEntity -> TenantEntityis the deepest chain. -
Request/response models are separate from domain models —
CreateChecklistRequestis not the same asFilingChecklist. API models may have fewer fields, different validation, or different defaults. -
The
__init__.pyis the public API — services should import fromaegis_shared.models, not from individual files. This allows internal reorganization without breaking imports.