Turn an operation into an executable model, stress-test possible futures, and compare interventions before committing capital.
SimForge is an AI-assisted operations modelling and decision-support application. A user describes a physical process in plain language, reviews the extracted assumptions, runs a stochastic baseline simulation, and compares three editable intervention scenarios.
The language model structures the problem and suggests scenarios. Deterministic Python code validates the inputs, runs the simulation, calculates every metric, and ranks the results.
The simulator owns the numbers. The AI does not invent them.
The current model family is buffer_logistics:
Continuous inflow → finite buffer/storage → scheduled outbound removal
This pattern covers operations such as:
- captured CO₂ entering tanks before tanker collection;
- process water entering holding tanks before removal;
- grain entering silos before outbound dispatch; and
- custom materials or items following the same flow pattern.
A model uses one quantity unit throughout: tonnes, kilograms, litres, cubic_metres, or items. SimForge does not silently convert or mix units.
- Natural-language requirements extraction with Gemini
- Targeted clarification questions for missing parameters
- Structured, validated
ModelSpecoutput - Visible provenance for user values and assumptions
- CO₂, process-water, grain, and custom-process inputs
- Seeded, reproducible Monte Carlo simulation
- Local execution or isolated Daytona sandbox execution
- Three validated and editable AI-suggested interventions
- Operational ranking when costs are unavailable
- Optional user-supplied financial ranking with CAPEX, OPEX change, annual value, and payback
- Interactive metrics, events, scenario comparison, and selectable chart series
- Backward-compatible CO₂ parameter aliases and response fields
Operation description
↓
Gemini requirements extraction
↓
Validated ModelSpec + provenance review
↓
Baseline Monte Carlo simulation
↓
Three reviewed scenario interventions
↓
Local Python or Daytona sandboxes
↓
Operational / financial comparison
↓
Recommendation with simulator-produced evidence
Gemini is used for requirements extraction and scenario suggestions. Python remains authoritative for schema validation, physical constraints, stochastic execution, metrics, and ranking. The web application does not execute arbitrary Gemini-generated simulation code.
- Python 3.10 or newer; Python 3.12 is recommended
- A Gemini API key for live requirements extraction and scenario suggestions
- A Daytona API key only if simulations should run in remote sandboxes
git clone https://github.com/Seveyus/SimForge.git
cd SimForge
python3.12 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .envAdd your credentials to .env:
GEMINI_API_KEY=your-gemini-key
GEMINI_MODEL=gemini-3.5-flash-lite
# Optional: omit this to run simulations locally.
DAYTONA_API_KEY=your-daytona-keyNever commit .env or API keys.
Start the application:
uvicorn app.main:app --host 127.0.0.1 --port 8000Open http://127.0.0.1:8000. The FastAPI service hosts both the API and the static frontend.
Without a Gemini key, the simulation API remains usable but live requirements extraction and scenario suggestions return gemini_unavailable. Without a Daytona key, simulation requests run locally.
- Start the server with the command above and open
http://127.0.0.1:8000. - Leave Live API selected.
- Describe an operation, or select a CO₂, process-water, grain, or custom-process example.
- Select Build model, answer any clarification questions, and review the extracted values and assumptions.
- Select Approve ModelSpec, then Run baseline.
- Select Generate scenario ideas and edit the suggested labels or parameter overrides if needed.
- To compare economics, enable Include economics, then enter the confirmed value per unit, amortisation period, baseline outbound-event cost, and each scenario's CAPEX, fixed annual OPEX change, and outbound-event cost. Leave it disabled for operational ranking.
- Select Compare reviewed scenarios. Financial outputs are calculated by Python only when every required economic input is present.
- Use the time-series labels above the chart to show or hide individual lines. The accessible data table always retains the complete result.
The local web server still uses your configured Gemini and Daytona services when their keys are present. If DAYTONA_API_KEY is omitted, baseline and scenario simulations run in the local Python process instead.
For interface development or a deterministic walkthrough without Gemini or Daytona, open:
http://127.0.0.1:8000/?mode=mock
This uses bundled contract fixtures and is visibly labelled as demo data. It is not live simulation output.
Environment variables take precedence over values in .env.
| Variable | Required | Purpose |
|---|---|---|
GEMINI_API_KEY |
For live AI | Gemini API key. GOOGLE_API_KEY is also accepted. |
GEMINI_MODEL |
For live AI | Gemini model used for extraction and suggestions. |
DAYTONA_API_KEY |
No | Enables Daytona execution when the request uses automatic execution. |
DAYTONA_API_URL |
No | Overrides the default Daytona API endpoint. |
DAYTONA_TARGET |
No | Selects a Daytona target or region configuration. |
SIMFORGE_SNAPSHOT |
No | Overrides the content-addressed Daytona snapshot name. |
SIMFORGE_REQUEST_TIMEOUT_S |
No | API simulation timeout in seconds; defaults to 180. |
Baseline and comparison endpoints accept an execution query parameter:
?execution=auto
?execution=local
?execution=daytona
autouses Daytona whenDAYTONA_API_KEYis configured and otherwise runs locally.localruns the deterministic simulator in the application environment.daytonarequires Daytona and fails explicitly if sandbox execution is unavailable.
If Daytona is configured but a remote run fails, SimForge does not silently present a local result as a sandbox result.
Daytona works without a pre-built snapshot, but a snapshot reduces cold-start time. Build one after configuring DAYTONA_API_KEY:
python scripts/build_snapshot.pySnapshot names include a hash of the simulator files. After changing the simulator or sandbox entry point, run the command again. A missing current snapshot falls back to uploading the current files rather than executing stale code.
| Method | Route | Purpose |
|---|---|---|
GET |
/api/health |
Liveness and active execution backend |
POST |
/api/requirements |
Natural language to a validated or clarifying ModelSpec |
POST |
/api/simulations/baseline |
Run the approved baseline model |
POST |
/api/scenarios/suggest |
Return exactly three validated scenario suggestions |
POST |
/api/scenarios/compare |
Run reviewed interventions and return a recommendation |
Use /api/health?deep=1 for a one-off Daytona round-trip check. A deep check provisions a real sandbox and should not be configured as a frequent platform health probe.
The simulator input is a validated ModelSpec:
{
"objective": "minimise lost process output",
"process_family": "buffer_logistics",
"material": {
"name": "process water",
"quantity_unit": "cubic_metres"
},
"time": {
"simulation_days": 3,
"timestep_minutes": 10
},
"parameters": {
"inflow_rate": {
"value": 12,
"unit": "cubic_metres/hour",
"source": "user"
}
}
}Simulation responses preserve the stable shape:
{
"timeseries": [],
"metrics": {},
"events": [],
"metadata": {}
}Financial comparison is optional. When supplied, the comparison request adds operation-wide economics and a complete cost set for every scenario:
{
"economics": {
"value_per_unit_gbp": 150,
"capex_amortisation_years": 10,
"baseline_cost_per_outbound_event_gbp": 400
},
"scenarios": [
{
"id": "more-buffer",
"label": "Add buffer capacity",
"parameter_overrides": {"buffer_count": 3},
"economics": {
"capex_gbp": 80000,
"annual_opex_delta_gbp": 1500,
"cost_per_collection_gbp": 400
}
}
]
}annual_opex_delta_gbp is signed, so a negative value represents an annual
saving. SimForge does not fill incomplete financial requests with demo cost
assumptions. Without a complete financial context, generic models retain the
deterministic operational ranking.
Scenario comparison responses contain:
{
"baseline": {},
"scenarios": [],
"recommendation": {}
}Financial recommendations are produced only when usable costs are confirmed. Otherwise metadata.ranking_mode is operational, using this deterministic order:
- Lowest P95 lost output
- Lowest expected lost output
- Lowest failure probability
- Scenario ID as the tie-breaker
SimForge deploys as one Python ASGI web service. The frontend is served by the same FastAPI process, so no separate frontend build or hosting service is required.
Use these settings on a Python-capable platform such as a container service or buildpack-based web host:
Runtime: Python 3.12
Build command: pip install -r requirements.txt
Start command: uvicorn app.main:app --host 0.0.0.0 --port $PORT
Health path: /api/health
Set the required environment variables in the platform's secret manager rather than uploading .env.
- Configure
GEMINI_API_KEYandGEMINI_MODEL. - Optionally configure Daytona credentials.
- Deploy the repository with the build and start commands above.
- Confirm
GET /api/healthreturnsstatus: "ok". - If using Daytona, run one manual
GET /api/health?deep=1check. - Submit one requirements request and one small baseline before opening access to users.
For a Daytona-backed demonstration, warming the sandbox once before presenting avoids the first-run image and snapshot startup delay.
The current application does not include user authentication, tenant isolation, persistent storage, or application-level rate limiting. Do not expose cost-incurring Gemini and Daytona endpoints publicly without adding access control and request limits at the application or gateway layer.
Run the complete automated suite:
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 python -m pytest -qCheck the browser JavaScript syntax:
node --check static/app.jsThe current suite covers simulation invariants, reproducibility, unit validation, legacy CO₂ compatibility, API contracts, scenario ranking, partial failures, and Daytona cleanup/equivalence behaviour.
The decision pipeline can also be run without the browser:
python demo.py --execution local --runs 200
python demo.py --execution daytona --runs 200
python demo.py --execution local --json result.jsonapp/
main.py FastAPI routes and static hosting
models.py Pydantic request and response contracts
requirements_agent.py Gemini extraction and scenario suggestions
api_contract.py ModelSpec-to-simulator mapping and response shaping
pipeline.py Local/Daytona execution boundary
daytona_runner.py Sandbox lifecycle and result validation
monte_carlo.py Seeded stochastic aggregation
scenario_runner.py Scenario execution and comparison
finance.py Financial metrics and ranking inputs
reference/
buffer_logistics.py Generic simulator facade
co2_simulation.py Validated compatibility kernel
static/
index.html Application interface
styles.css Responsive visual system
app.js Requirements, chart, and comparison interactions
scripts/
build_snapshot.py Content-addressed Daytona snapshot builder
tests/ Automated simulation and integration tests
demo.py Command-line decision-pipeline demo
- SimForge models buffer-logistics operations, not arbitrary physical systems.
- Every model uses one quantity unit; automatic conversion is intentionally unsupported.
- Gemini availability and quotas affect extraction and scenario suggestions.
- Native Daytona sandbox forking depends on account and region support. When it is unavailable, scenarios use independent isolated sandboxes and report that execution mode.
- The deployed application needs authentication and rate limiting before public production use.
- AI-generated simulator code is not executed by the web workflow.
- The simulator owns every reported number.
- Python validation is authoritative over model output.
- Assumptions and provenance remain visible to the user.
- Baseline and interventions share the same underlying model and seeded futures.
- Remote execution must be isolated, validated, and honestly labelled.
- Operational recommendations must not imply unconfirmed financial value.