neqsim-agent-handoff · diff
git:20260406.c9a2a01 to git:20260418.a3c26d6
1 added, 0 removed. Audit A to A.
---
name: neqsim-agent-handoff
description: "Agent-to-agent communication schema for NeqSim. USE WHEN: composing multi-agent pipelines where one agent's output feeds another agent's input. Defines structured result formats for fluid definitions, simulation results, and design outputs that agents can pass to each other."
+ last_verified: "2026-07-04"
---
# NeqSim Agent Handoff Schema
When agents need to pass results to other agents (e.g., `@process.model` output
feeding `@mechanical.design`), use these structured formats to ensure no
information is lost.
## Handoff Principles
1. **Explicit over implicit** — include all parameters, don't assume the receiving agent can infer
2. **Units always included** — every numerical value has a unit
3. **Code-ready** — the receiving agent can directly use the values in NeqSim API calls
4. **Traceable** — include the source agent and any assumptions made
## Schema 1: Fluid Definition Handoff
Pass from `@thermo.fluid` to any other agent:
```json
{
"handoff_type": "fluid_definition",
"source_agent": "thermo.fluid",
"eos_class": "SystemSrkEos",
"mixing_rule": "classic",
"temperature_K": 298.15,
"pressure_bara": 60.0,
"components": [
{"name": "methane", "mole_fraction": 0.85},
{"name": "ethane", "mole_fraction": 0.10},
{"name": "propane", "mole_fraction": 0.05}
],
"multi_phase_check": false,
"characterization": null,
"java_code": "SystemInterface fluid = new SystemSrkEos(298.15, 60.0);\nfluid.addComponent(\"methane\", 0.85);\nfluid.addComponent(\"ethane\", 0.10);\nfluid.addComponent(\"propane\", 0.05);\nfluid.setMixingRule(\"classic\");",
"assumptions": ["Lean gas — no water, no C4+ components"]
}
```
## Schema 2: Process Simulation Handoff
Pass from `@process.model` to `@mechanical.design`, `@safety.depressuring`, etc.:
```json
{
"handoff_type": "process_simulation",
"source_agent": "process.model",
"fluid_definition": { "...": "Schema 1 above" },
"equipment": [
{
"name": "HP Separator",
"type": "Separator",
"inlet_temperature_C": 30.0,
"inlet_pressure_bara": 60.0,
"outlet_gas_temperature_C": 30.0,
"outlet_gas_pressure_bara": 60.0,
"outlet_liquid_temperature_C": 30.0,
"outlet_liquid_pressure_bara": 60.0,
"gas_flow_rate_kg_hr": 42000.0,
"liquid_flow_rate_kg_hr": 8000.0,
"gas_density_kg_m3": 45.2,
"liquid_density_kg_m3": 520.0
}
],
"mass_balance_error_pct": 0.001,
"energy_balance_error_pct": 0.01,
"assumptions": ["Adiabatic separator", "No liquid carryover"]
}
```
## Schema 3: Mechanical Design Handoff
Pass from `@mechanical.design` to `@solve.task` for reporting:
```json
{
"handoff_type": "mechanical_design",
"source_agent": "mechanical.design",
"equipment_name": "HP Separator",
"design_pressure_barg": 72.0,
"design_temperature_C": 100.0,
"material_grade": "SA-516-70",
"wall_thickness_mm": 28.5,
"corrosion_allowance_mm": 3.0,
"weight_empty_kg": 15200.0,
"design_standard": "ASME VIII Div.1",
"company_tr": "Equinor TR2000",
"cost_estimate_usd": 450000.0,
"assumptions": ["Joint efficiency 0.85", "No external loads"]
}
```
## Schema 4: Flow Assurance Handoff
Pass from `@flow.assurance` to `@solve.task` or `@process.model`:
```json
{
"handoff_type": "flow_assurance",
"source_agent": "flow.assurance",
"hydrate_temperature_C": 18.5,
"operating_temperature_C": 25.0,
"subcooling_margin_C": 6.5,
"hydrate_risk": "LOW",
"wax_appearance_temperature_C": -5.0,
"pipeline_pressure_drop_bar": 12.3,
"arrival_temperature_C": 8.5,
"assumptions": ["No MEG injection", "Seawater at 4 C"]
}
```
## Schema 5: Safety Analysis Handoff
Pass from `@safety.depressuring` to reporting:
```json
{
"handoff_type": "safety_analysis",
"source_agent": "safety.depressuring",
"scenario": "Fire case blowdown",
"initial_pressure_bara": 85.0,
"final_pressure_bara": 6.9,
"blowdown_time_minutes": 15.0,
"minimum_temperature_C": -45.0,
"mdmt_C": -46.0,
"mdmt_margin_C": 1.0,
"psv_required_area_cm2": 12.5,
"assumptions": ["API 521 fire case", "Orifice Cd = 0.85"]
}
```
## How to Use Handoff Schemas
### Sending Agent (produces the handoff)
At the end of your work, format results into the appropriate schema:
```python
# In a notebook or agent output
handoff = {
"handoff_type": "process_simulation",
"source_agent": "process.model",
"equipment": [...],
# ... fill all fields
}
# Include in the response to the orchestrating agent
```
### Receiving Agent (consumes the handoff)
When you receive a handoff from another agent:
1. **Validate the handoff** — check all required fields are present
2. **Use the values directly** — temperatures, pressures, flows are ready to use
3. **Preserve assumptions** — carry forward assumptions from the source agent
4. **Add your own assumptions** — append to the assumptions list
### Router Agent (orchestrates handoffs)
The `@neqsim.help` router agent manages handoffs when composing multi-agent pipelines:
1. Runs Agent A, captures handoff output
2. Passes handoff as context to Agent B
3. Agent B uses handoff values as inputs
4. Final results aggregated for user
## Cross-Agent Consistency Checks
When receiving a handoff, verify consistency:
| Check | Rule |
|-------|------|
| Temperature units | Must be in C or K (never mixed) |
| Pressure units | Must be bara (never barg or psia without conversion) |
| Flow rate units | Must include unit string |
| Mass balance | Sum of outlet flows = inlet flow (within 0.1%) |
| Phase consistency | If source says 2 phases, receiving agent should see 2 phases |
If a consistency check fails, alert the user before proceeding.
## Schema 6: Lifecycle State Handoff
Use when passing a complete simulation state between agents — e.g., from a process
simulation agent to a mechanical design agent, or between task iterations.
```json
{
"schema": "neqsim-lifecycle-state",
"version": "1.0",
"handoff": {
"source_agent": "make a neqsim process simulation",
"target_agent": "run neqsim mechanical design",
"state_type": "ProcessSystemState | ProcessModelState",
"state_name": "Gas Processing Base Case",
"state_version": "1.0.0",
"state_json": "<serialized JSON from ProcessSystemState.toJson()>",
"compressed_bytes_base64": "<optional: base64-encoded compressed bytes for large states>",
"validation": {
"is_valid": true,
"checksum": "abc123..."
},
"context": {
"description": "HP/LP separation train for 50 MMSCFD wet gas",
"key_results": {
"gas_export_rate_MSm3_day": 1.2,
"liquid_rate_m3_hr": 45.0
}
},
"assumptions": [
"SRK EOS with classic mixing rule",
"Steady-state operation at plateau rate"
]
}
}
```
### Lifecycle State Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| state_type | string | Yes | `ProcessSystemState` (single area) or `ProcessModelState` (multi-area) |
| state_name | string | Yes | Human-readable name for the state |
| state_version | string | Yes | Semver version string |
| state_json | string | Yes | Serialized JSON from `state.toJson()` |
| compressed_bytes_base64 | string | No | Base64-encoded compressed bytes for large states |
| validation.is_valid | boolean | Yes | Result of `state.validate().isValid()` |
| validation.checksum | string | No | Integrity checksum from the state object |
| context.description | string | Yes | What the process does |
| context.key_results | object | No | Summary of important results |
### Creating a Lifecycle State Handoff
```java
// Source agent creates the state
ProcessSystemState state = ProcessSystemState.fromProcessSystem(process);
state.setName("Gas Processing Base Case");
state.setVersion("1.0.0");
String stateJson = state.toJson();
boolean isValid = state.validate().isValid();
// For large states, use compressed bytes
byte[] compressed = state.toCompressedBytes();
String base64 = java.util.Base64.getEncoder().encodeToString(compressed);
```
### Consuming a Lifecycle State Handoff
```java
// Target agent loads the state
ProcessSystemState loaded = ProcessSystemState.fromJson(handoff.state_json);
ProcessSystemState.ValidationResult result = loaded.validate();
assert result.isValid();
// For multi-area states
ProcessModelState modelState = ProcessModelState.fromJson(handoff.state_json);
```
### Version Comparison Across Handoffs
When multiple agents produce states at different design iterations, compare them:
```java
ProcessModelState v1 = ProcessModelState.fromJson(handoff1.state_json);
ProcessModelState v2 = ProcessModelState.fromJson(handoff2.state_json);
ProcessModelState.ModelDiff diff = ProcessModelState.compare(v1, v2);
// diff.getModifiedParameters(), diff.getAddedEquipment(), diff.getRemovedEquipment()
```