Best for
- USE WHEN: a task needs vendor performance data, mechanical drawings, line-list route hydraulics, water-hammer route/event evidence, trapped-liquid fire r
equinor/neqsim/.github/skills/neqsim-stid-retriever/SKILL.md
Retrieves engineering documents (compressor curves, mechanical drawings, line lists, P&IDs, data sheets, vendor docs, material certificates, fire/PFP documents, piping specs) from document management systems for use in NeqSim engineering tasks. Supports local directories, manual upload, and pluggable retrieval backends (e.g., stidapi for STID). USE WHEN: a task needs vendor performance data, mechanical drawings, line-list route hydraulics, water-hammer route/event evidence, trapped-liquid fire r
Decision brief
Retrieve engineering documents (compressor curves, mechanical drawings, data sheets, vendor reports) for use in NeqSim task-solving workflows.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/equinor/neqsim --skill ".github/skills/neqsim-stid-retriever"Inspect the Agent Skill "neqsim-stid-retriever" from https://github.com/equinor/neqsim/blob/9e4e36d4b6a59404ac9aa629740fbc312610d3c8/.github/skills/neqsim-stid-retriever/SKILL.md at commit 9e4e36d4b6a59404ac9aa629740fbc312610d3c8. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
ALL downloaded documents — STID drawings, PI historian exports, vendor datasheets, P&IDs, literature PDFs — MUST be saved to step1scopeandresearch/references/ within the task folder.
TASKDIR = "tasksolve/YYYY-MM-DDslug" outdir = os.path.join(TASKDIR, "step1scopeandresearch", "references")
outdir = os.path.join(os.path.dirname(file), "..", "figures", "stiddocs") NEVER outdir = "output/stiddocs" NEVER bash python devtools/pdftofigures.py tasksolve/YYYY-MM-DDslug/step1scopeandresearch/references/ \ --outdir tasksolve/YYYY-MM-DDslug/figures/
The task solver checks these sources in order:
Place documents in the task's references folder, filed into per-source subfolders so the collection is self-contained and easy to distribute:
Permission review
The documentation asks the agent to run terminal commands or scripts.
python devtools/pdf_to_figures.py task_solve/YYYY-MM-DD_slug/step1_scope_and_research/references/ \The documentation asks the agent to run terminal commands or scripts.
python devtools/generate_sources_md.py task_solve/YYYY-MM-DD_task_slug --organizeThe documentation asks the agent to read local files, directories, or repositories.
the agent should re-scan the folder if it detects new filesEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 93/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 147 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Retrieve engineering documents (compressor curves, mechanical drawings, data sheets, vendor reports) for use in NeqSim task-solving workflows.
For water-hammer/liquid-hammer tasks, retrieve STID/P&ID route drawings, line lists, stress isometrics, piping specifications, valve data sheets with closure time, pump curves or trip logs, design-pressure basis, and relevant tagreader event exports into the task references folder.
ALL downloaded documents — STID drawings, PI historian exports,
vendor datasheets, P&IDs, literature PDFs — MUST be saved to
step1_scope_and_research/references/ within the task folder.
NEVER download or save task-related files to workspace-level directories like
output/, figures/, or any path outside task_solve/YYYY-MM-DD_slug/.
# CORRECT — saves inside the task folder:
TASK_DIR = "task_solve/YYYY-MM-DD_slug"
out_dir = os.path.join(TASK_DIR, "step1_scope_and_research", "references")
# WRONG — saves outside the task folder:
out_dir = os.path.join(os.path.dirname(__file__), "..", "figures", "stid_docs") # NEVER
out_dir = "output/stid_docs" # NEVER
For PDF-to-PNG conversion: Output to the task's figures/:
python devtools/pdf_to_figures.py task_solve/YYYY-MM-DD_slug/step1_scope_and_research/references/ \
--outdir task_solve/YYYY-MM-DD_slug/figures/
This rule ensures every task is self-contained and portable.
This skill is backend-agnostic — it works with any document source:
The task solver checks these sources in order:
step1_scope_and_research/references/devtools/doc_retrieval_config.yaml — this file is gitignored)This means the workflow works for everyone:
references/ and the same pipeline runsPlace documents in the task's references folder, filed into per-source subfolders so the collection is self-contained and easy to distribute:
task_solve/YYYY-MM-DD_task_slug/
└── step1_scope_and_research/
└── references/
├── SOURCES.md # human-readable summary (auto-generated)
├── collection_manifest.json # machine-readable record (auto-generated)
├── vendor/
│ └── compressor_curves.pdf
├── stid/
│ ├── mechanical_drawing.pdf
│ └── equipment_datasheet.pdf
└── manual/ # user-provided docs
Source subfolders: stid/, pepr/, tr2000/, maintenance/, servicenow/,
tagreader/, seeq/, rigga/, vendor/, lab/, literature/, manual/,
other/. After placing documents (or when new ones arrive), run the
dependency-free generator to file any loose files and (re)build the
distributable summary + manifest:
python devtools/generate_sources_md.py task_solve/YYYY-MM-DD_task_slug --organize
SOURCES.md lists, per source, each file with its origin (document number /
tag / action ID / historian tag), retrieval date, classification, relevance,
review status, and a one-line summary — so the whole task folder can be handed
to others and the collected documents reused.
Or point to an existing directory when creating the task:
neqsim new-task "compressor analysis" --type B \
--refs-dir "/path/to/existing/docs"
The task solver will automatically:
references/ (including per-source subfolders)devtools/pdf_to_figures.py)view_imagereferences/SOURCES.md so the collection stays distributableWhen a retrieval backend is configured via devtools/doc_retrieval_config.yaml
(gitignored — never committed), the task solver can auto-fetch documents
by equipment tag. See the config template below for setup instructions.
Use devtools/stid_download.py to download STID documents directly into a
task folder. This ensures all documents end up in the right place:
# Download documents by tag — saves to task's references/ folder
python devtools/stid_download.py --task-dir task_solve/2026-04-16_my_task \
--inst MYINST --tags 30PT0001 30PT0002 33AI0001
# Download + convert to PNG for AI analysis
python devtools/stid_download.py --task-dir task_solve/2026-04-16_my_task \
--inst MYINST --tags 30PT0001 --convert-png
# Download specific document numbers
python devtools/stid_download.py --task-dir task_solve/2026-04-16_my_task \
--inst MYINST --docs E001-AS-P-XB-00001-01 E001-AS-BI000-DS-00001
The helper:
step1_scope_and_research/references/ inside the task folderstid_retrieval_manifest.json for traceabilityfigures/ directory# Generic retrieval interface used by the task solver:
from devtools.doc_retriever import retrieve_documents
docs = retrieve_documents(
tags=['35-KA001A'],
doc_types=['CE', 'AA', 'MD', 'DS'],
output_dir='step1_scope_and_research/references/'
)
# Returns list of downloaded file paths, or [] if no backend configured
| Code | Type | When Relevant |
|---|---|---|
CE | Performance Curves / Calculations | Compressor, pump, turbine analysis |
DS | Data Sheet | Any equipment analysis |
AA | General Arrangement Drawing | Physical layout, sizing |
MD | Mechanical Drawing | Detailed dimensions, nozzles |
RV | Vendor Manual / Report | Operating procedures, maintenance |
RE | Report | Background reference |
ER | Assembly / Erection Drawing | Installation, coupling details |
PL | Parts List | Spare parts, BOM |
PI | P&ID | Process topology |
PF | PFD | Process flow overview |
IN | Instrument Data Sheet | Control system design |
SP | Specification | Material/piping requirements |
LL | Line list / route table | Piping hydraulic route models with PipingRouteBuilder |
MC | Material certificate / material class sheet | Pipe grade, SMYS/SMTS, heat number, toughness, temperature limits |
FP | Fireproofing / PFP specification | Required fire endurance, protection type, inspection/condition evidence |
FC | Fire or consequence study | Fire zone, heat flux, exposed length/area, escalation and source-term basis |
The task solver filters documents by relevance to avoid wasting time on irrelevant content. Only documents above the relevance threshold are extracted and analyzed:
DOC_RELEVANCE = {
'compressor_analysis': {
'CE': 1.0, # Performance curves — essential
'DS': 0.9, # Data sheet — essential
'AA': 0.7, # General arrangement — useful
'MD': 0.6, # Mechanical drawing — useful
'ER': 0.6, # Assembly drawing — useful
'RV': 0.5, # Vendor manual — background
'RE': 0.4, # Report — background
'PL': 0.2, # Parts list — skip
'SP': 0.3, # Specification — skip
},
'heat_exchanger_analysis': {
'DS': 1.0, 'CE': 0.9, 'AA': 0.7, 'MD': 0.6, 'RV': 0.5,
},
'separator_analysis': {
'DS': 1.0, 'AA': 0.9, 'PI': 0.8, 'MD': 0.6, 'IN': 0.7,
},
'pipeline_design': {
'LL': 1.0, 'DS': 1.0, 'SP': 0.9, 'PI': 0.8, 'CE': 0.7, 'MD': 0.6,
},
'trapped_liquid_fire_rupture': {
'PI': 1.0, # P&ID / STID isolation boundaries
'LL': 1.0, # Line list, ID, wall, design P/T, material class
'SP': 0.95, # Piping spec, flange/gasket/bolt/material class
'MC': 0.95, # Material certificate or material class sheet
'FP': 0.90, # PFP/fireproofing requirement and condition
'FC': 0.90, # Fire/consequence study heat flux and exposed area
'DS': 0.75, # Equipment/piping datasheets
'MD': 0.70, # Mechanical arrangements and dimensions
'IN': 0.60, # Instruments, alarms, trips, relief availability
'RE': 0.55, # Prior reports or technical notes
},
'general': {
'DS': 1.0, 'CE': 0.9, 'AA': 0.7, 'PI': 0.7, 'MD': 0.6,
'RV': 0.5, 'RE': 0.4, 'ER': 0.4, 'IN': 0.5, 'SP': 0.4,
'PL': 0.2, 'PF': 0.6,
},
}
def filter_relevant_docs(doc_list, task_type, min_relevance=0.5):
"""Filter documents by relevance to the task type.
Args:
doc_list: List of dicts with at least 'docType' or 'doc_type' key
task_type: One of the keys in DOC_RELEVANCE
min_relevance: Minimum score to keep (default 0.5)
Returns:
(relevant, filtered_out) — two lists
"""
relevance_map = DOC_RELEVANCE.get(task_type, DOC_RELEVANCE['general'])
relevant, filtered_out = [], []
for doc in doc_list:
dtype = doc.get('docType') or doc.get('doc_type', '')
score = relevance_map.get(dtype, 0.0)
if score >= min_relevance:
relevant.append({**doc, '_relevance': score})
else:
filtered_out.append({**doc, '_relevance': score,
'_reason': f'Below threshold ({score} < {min_relevance})'})
return relevant, filtered_out
For tasks involving trapped liquid, blocked-in liquid, no pressure relief,
fire exposure, PFP demand, pipe rupture, or flange failure, use task type
trapped_liquid_fire_rupture and search for this evidence pack:
Write retrieval attempts, missing documents, and fallback assumptions into the
manifest so neqsim-trapped-liquid-fire-rupture can include them in the final
evidence matrix.
After documents are in references/, convert to images for AI analysis:
import fitz # pymupdf
def pdf_to_pngs(pdf_path, output_dir, dpi=200):
"""Convert PDF pages to numbered PNG images."""
import os
doc = fitz.open(pdf_path)
base = os.path.splitext(os.path.basename(pdf_path))[0]
paths = []
for i, page in enumerate(doc):
pix = page.get_pixmap(dpi=dpi)
out = os.path.join(output_dir, f"{base}_page{i+1}.png")
pix.save(out)
paths.append(out)
doc.close()
return paths
Or use the built-in utility:
python devtools/pdf_to_figures.py step1_scope_and_research/references/ --outdir figures/
Then use view_image on extracted PNGs to read compressor curves,
mechanical drawings, and data sheets.
After retrieval/classification, create a manifest for traceability:
manifest = {
"source": "local" | "backend" | "manual",
"retrieval_date": "2026-04-16",
"task_type": "compressor_analysis",
"tags_searched": ["35-KA001A", "35-KA001B"],
"documents_retrieved": [
{
"filename": "performance_curves.pdf",
"doc_type": "CE",
"title": "Performance Curves Compressor B",
"relevance": 1.0,
"pages": 41,
"used_in_analysis": True
}
],
"documents_filtered_out": [
{
"filename": "parts_list.pdf",
"doc_type": "PL",
"title": "Spare Parts List",
"relevance": 0.2,
"reason": "Below relevance threshold (0.5)"
}
]
}
# Save as step1_scope_and_research/retrieval_manifest.json
The task solver uses this manifest to:
When retrieved STID documents include line lists, E3D route tables, stress
isometrics, or P&IDs with enough line geometry, hand off the extracted route to
PipingRouteBuilder for the NeqSim hydraulic model. This is the preferred path
for compressor suction/discharge pressure-drop studies and debottlenecking tasks.
Required extraction fields:
| Field | Purpose |
|---|---|
segment_id | Stable line-list row id or generated route segment id |
from_node, to_node | Equipment/nozzle/node topology |
length, length_unit | Straight pipe length |
internal_diameter, diameter_unit | Hydraulic diameter for PipeBeggsAndBrills |
wall_thickness, wall_thickness_unit | Optional metadata and generated pipe wall thickness |
elevation_change, elevation_unit | Static head contribution |
minor_losses | Fittings/valves/reducers as K values |
source_ref | Drawing number, page, row, or isometric reference |
Save the extracted route table and route.toJson() in the task folder. See
docs/process/piping_route_builder.md for the full builder workflow.
## Data Sources
- **Equipment tags:** 35-KA001A, 35-KA001B (export compressors)
- **Document source:** Local directory / Auto-retrieval / User-provided
- **Key documents used:**
- performance_curves.pdf: Vendor performance maps (41 pages)
- as_built_curves.pdf: Shop test results (4 pages)
- general_arrangement.pdf: GA drawing with dimensions
- **Documents filtered out:** 8 (parts lists, generic specs — below relevance)
# Load retrieval manifest to know what's available
import json
manifest_path = TASK_DIR / 'step1_scope_and_research' / 'retrieval_manifest.json'
if manifest_path.exists():
with open(manifest_path) as f:
manifest = json.load(f)
# Work only with relevant documents
curve_docs = [d for d in manifest['documents_retrieved']
if d['doc_type'] == 'CE' and d['used_in_analysis']]
print(f"Analyzing {len(curve_docs)} performance curve documents")
{
"data_sources": {
"retrieval_method": "local",
"documents_retrieved": 13,
"documents_analyzed": 5,
"documents_filtered_out": 8,
"key_documents": [
"performance_curves.pdf — Vendor Performance Maps",
"as_built_curves.pdf — Shop Test Results"
]
}
}
from neqsim import jneqsim
# Create compressor with performance curves from extracted data
compressor = jneqsim.process.equipment.compressor.Compressor("Export Comp", feed)
# If curve data has been digitized from the images:
chart = compressor.getCompressorChart()
chart.setHeadUnit("kJ/kg")
chart.setUseCompressorChart(True)
# Add speed curves (extracted from performance map)
for speed, points in curve_data.items():
curve = jneqsim.process.equipment.compressor.CompressorCurve(speed)
for flow, head, eff in points:
curve.addCurveDataPoint(flow, head, eff)
chart.addCurve(curve)
Users can always add documents manually to references/, even when a
retrieval backend is configured. The two approaches coexist:
step1_scope_and_research/references/
├── [auto-retrieved] performance_curves_35KA001A.pdf (from backend)
├── [auto-retrieved] datasheet_35KA001A.pdf (from backend)
├── [manual] vendor_email_attachment.pdf (user dropped in)
├── [manual] field_test_report_2025.xlsx (user dropped in)
└── [manual] photo_nameplate.jpg (user dropped in)
The retrieval manifest tracks the source of each document:
{
"documents_retrieved": [
{"filename": "performance_curves.pdf", "source": "backend", "doc_type": "CE"},
{"filename": "vendor_email_attachment.pdf", "source": "manual", "doc_type": "RE"},
{"filename": "field_test_report_2025.xlsx", "source": "manual", "doc_type": "DS"}
]
}
Rules:
references/ at any time;
the agent should re-scan the folder if it detects new filesThe initial retrieval in Step 1 may not cover everything. During Step 2 (analysis), the agent may discover it needs additional documents — for example:
When the agent identifies a data gap during analysis, it follows this protocol:
Log the gap — record what's missing and why in the notebook:
# DATA GAP: Need mechanical drawing (AA) for 35-KA001A to get
# nozzle sizes for piping stress analysis. Current docs only have
# performance curves (CE) and datasheet (DS).
Attempt auto-retrieval (if backend configured):
# Mid-analysis retrieval for additional document types
from devtools.doc_retriever import retrieve_documents
additional = retrieve_documents(
tags=['35-KA001A'],
doc_types=['AA', 'MD'], # specifically what's missing
output_dir='step1_scope_and_research/references/'
)
if additional:
print(f"Retrieved {len(additional)} additional documents")
# Re-extract PNGs for new documents
# Update retrieval manifest
Ask the user if auto-retrieval is unavailable or returned nothing:
**Data gap identified:** I need the General Arrangement drawing (AA) for
35-KA001A to extract nozzle dimensions. Options:
- Drop the PDF into `step1_scope_and_research/references/` and I'll continue
- Provide the dimensions directly (suction nozzle OD, discharge nozzle OD)
- Skip this analysis (I'll use typical values with a note on uncertainty)
Update the manifest with the new retrieval:
manifest['iterative_retrievals'] = manifest.get('iterative_retrievals', [])
manifest['iterative_retrievals'].append({
"phase": "step2_analysis",
"reason": "Need nozzle dimensions for piping stress",
"doc_types_requested": ["AA", "MD"],
"tags": ["35-KA001A"],
"documents_found": ["general_arrangement_35KA001A.pdf"],
"source": "backend" # or "manual" or "user_provided_value"
})
Continue analysis with the new data, or proceed with documented assumptions if the document isn't available.
The agent should check for data gaps at these points:
| Trigger | Example Gap | Action |
|---|---|---|
| Missing physical dimensions | No GA/MD drawing → can't size equipment | Request AA/MD docs |
| Missing operating conditions | No datasheet → unknown design pressure | Request DS docs |
| Upstream/downstream unknown | No P&ID → can't model recycles | Request PI docs |
| Control system needed | No instrument sheets → can't set PID params | Request IN docs |
| Parallel equipment | Only train A data, need train B comparison | Request docs for tag B |
| Material unknown | No material cert → can't check corrosion | Request SP/material cert |
| Vendor corrections needed | Shop test vs predicted curves differ | Request test report (RE) |
Standard tag naming for Norwegian continental shelf installations:
| Prefix | Equipment Type |
|---|---|
KA | Compressor |
PA | Pump |
VA | Valve |
FA | Fan |
HA | Heat exchanger |
DA | Vessel / Separator |
BA | Tank |
GA | Generator |
MA | Motor |
XA | Special equipment |
To enable auto-retrieval, create devtools/doc_retrieval_config.yaml.
This file is in .gitignore and never committed to the public repo.
# devtools/doc_retrieval_config.yaml
# THIS FILE IS GITIGNORED — contains organization-specific configuration
#
# Supported backends:
# stidapi — STID document management (requires stidapi package + network)
# local — just reads from a local directory
# none — disabled (user must provide docs manually)
backend: none # change to: stidapi, local
# Backend-specific settings (only needed for auto-retrieval):
# stidapi:
# auth_method: azure_ad_sso
# default_inst_code: YOUR_INST_CODE
If this file doesn't exist, the task solver works normally — it just
expects documents in references/ instead of auto-fetching them.
When STID retrieval identifies equipment tags (e.g., 35-KA001A), the
same tags can be used to read operating data from the plant historian
(OSIsoft PI / Aspen IP.21) via tagreader, and the data should be
saved as CSV inside the task folder for reproducibility.
The full pipeline is documented in the neqsim-plant-data skill:
STID (tag search) → Tagreader (historian read) → CSV (snapshot) → NeqSim (simulation)
See the "STID → Tagreader → CSV → NeqSim Pipeline" section in that skill for the complete end-to-end example with CSV persistence, data quality filtering, and digital twin comparison — all saved to the task folder.
Frequently asked questions
Retrieve engineering documents (compressor curves, mechanical drawings, data sheets, vendor reports) for use in NeqSim task-solving workflows.
The source record exposes this install command: npx skills add https://github.com/equinor/neqsim --skill ".github/skills/neqsim-stid-retriever". Inspect the command and pinned source before running it.
Static rules flagged exec-script, read-files in the source; the page lists the matching lines and excerpts.
Alternatives
enuno/unifi-mcp-server
Specialized guide for adding new MCP tools to the UniFi MCP Server following project standards, UniFi API patterns, and test-driven development practices. Use when implementing new UniFi Network Controller features as MCP tools.
NintendaDev/unikit-ai
Generate and maintain the project's TECHNICAL documentation from its codebase — scans the project structure, tech stack, and module boundaries, then writes a lean README landing page plus detailed topic pages (architecture, modules, setup, build, APIs), only the docs that are relevant. Use whenever the user wants to create, update, or validate documentation of the CODE or the project itself, e.g. "generate documentation", "create docs", "write the README", "update the project docs", "document th
vasilyu1983/AI-Agents-public
Scans public GitHub repos for agent skills, dev practices, and code patterns. Use when enriching skills, setting team policy, or researching a build domain.
SerendipityOneInc/ZooData-Skills
API endpoint reference for the ZooData data platform: the 12 commerce endpoints plus 10 keyword-intelligence endpoints (categories, markets, products, competitors, realtime ASIN, AI review analysis, raw reviews, price band, brand, history, and the keyword detail/trend/extends/search/ market-profile/product-traffic/competitor-keywords/traffic-profile/ traffic-timeline family) — their inputs/outputs, parameter quirks, Quick Start (auth, base URL), how credits are tracked (meta.creditsConsumed), an