Skip to content

Repository files navigation

SMARTS — Subsurface Multi-agent Assessment, Recovery & Targeting System

Python 3.10+ License: MIT tests

A reusable, multi-agent system that assesses oil & gas fields — primarily on the Norwegian Continental Shelf (NCS) — and produces a grounded recommendation on whether to rejuvenate, develop, or explore them. It pairs specialist agent skills (markdown) with a field-agnostic Python engine that loads any field's data, runs subsurface analytics, applies a transparent 4-gate decision framework, and writes the recommendation with a full uncertainty spread and an independent assurance (red-team) review.

Built and validated on the Volve public dataset (Equinor); ships with a synthetic field so it runs end-to-end on a fresh clone with no data download.


What it does

Give it a field (production history + optionally a simulation model + reports) and it returns:

  • Updated recovery assessment — OOIP, recovery factor, remaining oil in place, EUR, decline, waterflood diagnostics.
  • Ranked pathways with uncertainty — bypassed/attic oil, infill, waterflood optimization, EOR, well interventions — each with P90/P50/P10 volumes, EMV, breakeven price, and flip threshold.
  • A recommendation via a 4-gate framework (Volume → Access → Economics → Risked), with an explicit confidence level.
  • An assurance (red-team) review — an independent agent attacks the case before the verdict finalizes, flagging load-bearing assumptions, single points of failure, and the price/volume at which the recommendation reverses.

Example output (excerpt from fields/volve/assessment/)

# Volve — SMARTS Assessment (rejuvenation mode)
*Sodir resource class context: RC3–RC5 (contingent + possible resources)*

## Recommendation: REJUVENATE (CONDITIONAL) (confidence: medium)

| Gate | Question | Result | Evidence |
| G1 Volume | material recoverable volume? | ✅ PASS | remaining OIP 11,986,597 sm3, P50 prize 6,472,762 sm3 |
| G2 Access | physically reactivatable? | ⚠️ CONDITIONAL | decommissioned; host likely removed; wells likely P&A'd |
| G3 Economics | a pathway NPV-positive? | ✅ PASS | best=waterflood_optimization, EMV $38M, breakeven $23/bbl |
| G4 Risked | risked EMV > do-nothing? | ✅ PASS | risked EMV $88M |

### Sensitivity & uncertainty
- Price flip threshold: weakest pathway turns negative below $23/bbl (margin $47).
- Leading pathway NPV spread: P90 $36M | P50 $60M | P10 $84M (EMV $38M).

### Assurance review — grade: medium
- Single point of failure: bypassed-oil volumes rest on field-level FOIP (no region breakdown).
- To raise assurance: re-run sim with ROPR/RWPR to locate bypassed oil.

Architecture

flowchart TD
    FP[Field pack<br/>fields/&#60;name&#62;/field.yml] --> LOAD[field_loader<br/>validate + load]
    LOAD --> DQ[(data-quality-agent<br/>grade A–D)]
    DQ --> ENGINE{analysis_engine<br/>recovery • decline • waterflood}
    ENGINE --> AGENTS[Specialist agents]
    AGENTS --> RES[reservoir]
    AGENTS --> GEO[geoscience]
    AGENTS --> PROD[production]
    AGENTS --> FAC[facilities]
    AGENTS --> ECON[economics]
    AGENTS --> NCS[ncs-context]
    RES & GEO & PROD & FAC & ECON & NCS --> ASSUR[(assurance-agent<br/>red-team)]
    ASSUR --> GATES[4-gate framework]
    GATES --> G1[G1 Volume]
    G1 --> G2[G2 Access]
    G2 --> G3[G3 Economics]
    G3 --> G4[G4 Risked]
    G4 --> REC[Recommendation<br/>+ uncertainty + risk register]
    REC --> OUT[assessment.md / --json]
Loading

The developer agents build the case; the assurance agent breaks it; the integration logic weighs both into the final verdict. This two-team (develop / challenge) pattern mirrors an independent peer assist at a decision gate.


The 4-gate decision framework

A rejuvenation/development/explore decision is a cascade of gates. Fail an early gate and later ones are moot.

Gate Question asked Pass criterion "Conditional" means
G1 Volume Is there material recoverable volume? remaining OIP > 0.5 MM sm³ or P50 rejuvenation prize > 0.5 MM sm³ volume present but basis is analytical-only (no OOIP) → lower confidence
G2 Access Can it physically be reactivated? field is producing/shut-in with active infrastructure field decommissioned → host/wells status must be surveyed before capital
G3 Economics Is at least one pathway value-positive? ≥1 pathway with NPV > 0 at base price and EMV > 0 only marginal pathways positive → recommendation hinges on price
G4 Risked Does risked EMV beat do-nothing? best pathway EMV (+ decom deferral credit) > 0 EMV barely positive → price-sensitive, flag in risk register

A hard fail at any gate drives the verdict. The recommendation verb changes with --mode: rejuvenate / develop / explore.

The Finding block (inter-agent contract)

Every agent emits a structured Finding block — the only coupling between agents. This is what makes each agent independently testable and replaceable:

### Finding: reservoir-engineering-agent
Confidence: high
Key numbers:
  OOIP: 21967456 sm3            # (method: simulation)
  RF_to_date: 45.4 %
  remaining_OIP: 11986597 sm3
  drive_mechanism: waterflood
  waterflood_VRR: 0.93
  EUR_business_as_usual: 10972353 sm3
Opportunities:                 # ranked, each with P90/P50/P10 + capex class
  - {mechanism: bypassed_attic_oil, P90: 1438392, P50: 2996649, P10: 3955577, capex_class: high}
Blockers:
  - region-level OIP not in summary vector — needs model re-run
Hand-off: geoscience-model-agent

The same structure is emitted as JSON via --json (see CLI & machine-readability).


Quick start

# 1. Clone & install (Python 3.10+)
git clone https://github.com/ojaogezi/Subsurface-Agent.git
cd Subsurface-Agent
python -m venv .venv && source .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -e .

# 2. Assess the in-repo synthetic field (needs no data download)
smarts-assess fields/nordkapp_beta
# equivalent:  python -m smarts.assess fields/nordkapp_beta

# 3. (Optional) fetch the real Volve data, then assess it
python scripts/get_volve_data.py     # check / instructions
smarts-assess fields/volve

Output is written to fields/<name>/assessment/<name>-assessment.md.

Using it in your own code

from smarts import load_field, assess_recovery, decline_analysis

field = load_field("fields/volve")
rec = assess_recovery(field)
print(f"OOIP {rec.ooip_sm3:,.0f} sm3, RF {rec.rf_to_date_pct:.1f}%")

CLI & machine-readability

smarts-assess fields/<name> [options]
  --mode {rejuvenation,development,exploration}   # scope of the recommendation
  --price 65                                      # override oil price (USD/bbl)
  --discount-rate 0.08                            # override real discount rate
  --decom-liability-usd 500000000                 # for decom-deferral credit
  --json                                          # emit structured JSON to stdout

--json emits the full dossier (gates, technical picture, pathways with P90/P50/P10, economics with EMV + flip thresholds, data-quality grade, assurance review) — so SMARTS can be used as a tool by other agents or pipelines. The structured output is the natural basis for an MCP server (see Roadmap).


Assessment modes & the Sodir resource classification

SMARTS spans three use cases, mapped to the Sodir (former NPD) resource classification so outputs resonate with an NCS audience:

Mode Use case Sodir RC context
rejuvenation late-life / brownfield / decommissioned field RC3–RC5 (contingent + possible resources in a discovered field)
development a discovered accumulation pending development RC2–RC3 (contingent resources)
exploration a prospect (no production history) RC6–RC7 (prospective resources — GRV/CoS based)

Honest scope note: the engine is fully built out for rejuvenation/development (production history + simulation results). The exploration mode is framed and the decision logic applies, but volumetric-from-GRV and chance-of-success tooling is on the roadmap — see below.


The agents

Each agent is an independently-usable skill in agents/. The orchestrator (skills/SKILL.md) routes a field question through them.

Agent Role
data-quality grades input completeness/quality (A–D) before specialists run
reservoir-engineering OOIP, RF, material balance, PVT, decline, waterflood
production-wells per-well decline, water cut, interventions
geoscience-model static model, faults, contacts, bypassed-oil targets
facilities-integrity facilities, integrity, reactivation feasibility
economics-commercial capex/opex, NPV/EMV, price thresholds
ncs-context NCS fiscal regime, infrastructure, regulatory, analogs
assurance independent red-team — attacks the case before the verdict
integration-decision 4-gate framework, final recommendation + risk register

Repository layout

smarts/                        Importable Python package (the engine)
  field_loader.py              Load + validate a field pack (data contract)
  analysis_engine.py           Analytics: recovery, decline, waterflood,
                               opportunities, economics, data-quality, assurance
  assess.py                    Orchestrator → assessment + recommendation + JSON
config/
  field_data_contract.md       The data contract any field must conform to
  field.yml.template           Copy this to add a new field
fields/
  volve/                       Volve pack (config only; data via scripts/)
  nordkapp_beta/               Synthetic field — ships in-repo, proves reusability
agents/ + skills/SKILL.md      9 specialist agent skills + orchestrator
tests/                         Reusability regression (pytest + standalone)
.github/workflows/tests.yml    CI: runs the synthetic regression on push
scripts/get_volve_data.py      Fetch/verify the public Volve dataset
ncs_reference/                 NCS fiscal/regulatory/infrastructure reference

⚠️ Data governance: the real Volve dataset is ~1.8 GB (Eclipse binaries) and is not committed. If you add proprietary/licensed field data, never commit it.gitignore excludes fields/*/data/ and fields/*/assessment/, so put licensed production/model data under fields/<name>/data/ (and point field.yml there), not directly in the pack root. Keep only field.yml (configs) in git. The in-repo nordkapp_beta data is synthetic and safe to ship.

Adding a new field

  1. mkdir fields/<your_field> and copy config/field.yml.templatefield.yml.
  2. Fill in identity, lifecycle, and column mapping (so your production file's columns map to the contract).
  3. Add data under fields/<name>/ (or point field.yml paths at shared data).
  4. Run smarts-assess fields/<your_field>.

The system is tolerant of partial data: no simulation model → analytical-only mode; no per-region vectors → flags the gap; missing PVT → uses correlations. Missing data degrades the data-quality grade and confidence, never crashes.


Tests

tests

pip install -e ".[dev]"
pytest

CI runs the synthetic nordkapp_beta regression on every push (Python 3.10–3.12). The Volve test is a validation claim: when the ~1.8 GB data is present, it asserts cumulative oil matches the published figure (~63 MMbbl, tolerance ±3) and that history ↔ simulation agree to <2%. It auto-skips on a fresh clone.

Field Region Drive Status Result
Volve (real) North Sea waterflood decommissioned REJUVENATE (CONDITIONAL) — gated on facilities
Nordkapp Beta (synthetic) Norwegian Sea gas-injection producing REJUVENATE — late-life optimization

Roadmap

  • Exploration mode tooling — GRV/N:G/φ/Sw volumetrics with Monte-Carlo, geological chance of success, EMV-based drilling decisions (RC6–RC7).
  • Tornado / parameter sweeps — full sensitivity output per pathway (currently a one-line summary).
  • MCP server — expose SMARTS as a tool other agents can call (the --json output is the basis).
  • OPM/interSECT runner — execute open-source simulation (not just read existing results).

Scope & honest limits

  • SMARTS is a screening tool, not FID-grade. Economics are indicative; capex classes are analog ranges.
  • The proprietary ECLIPSE E100 solver is not run here; the engine reads existing simulation results via resdata and falls back to analytical-only when no model exists. To locate bypassed oil precisely, re-run the model with region summary keywords (the assurance agent flags this gap).
  • NCS fiscal terms (78% default) are configurable and dated — verify against the field's licence vintage before relying on them.
  • Geomechanics, drilling, seismic inversion, compositional EoS — named and routed in the agent skills, not solved by the engine.

License

MIT — see LICENSE. The Volve dataset (Equinor) and libraries used (pyResToolbox, pyscal, resdata) retain their own licences; download data and dependencies separately.

About

SMARTS — Subsurface Multi-agent Assessment, Recovery & Targeting System. Reusable multi-agent system to assess oil & gas fields (NCS) for rejuvenation, development & exploration decisions.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages