Typed, unit-aware definitions
Declare tags, direction, engineering units, magnitude and rate limits. The policy engine validates every call against them.
The Pulpum SDK is typed Python. Tools declare their tags, units and limits; agents declare their goal, tool set and autonomy level; the policy engine enforces all of it at call time. Every run is replayable against a new model before that model goes near a machine.
Live example: Grade change PM4 · 135 gsm kraftliner → 110 gsm testliner, no break, ≤14 min off-spec
The Pulpum SDK is typed Python. Tools are declared with schemas and limits; the policy engine enforces them at call time — not in a review meeting.
# Bound the dryer agent to six steam groups on PM4.
from pulpum import Agent, Tool, Limit, Autonomy
steam = Tool(
name="dcs.steam_schedule",
tags=["PM4.DRY.G1..G6.PRESS_SP"],
limits=[Limit(max_step="0.15 bar", per="30s")],
)
dryer = Agent(
id="agent.dry_coat",
goal="reel moisture 7.4% +/-0.5, min steam",
tools=[steam, Tool("qcs.read_moisture", read_only=True)],
# bounded writes; humans still gate ramps
autonomy=Autonomy.L3,
# simulate on the twin before every write
verify="twin",
)
run = dryer.start(machine="PM4", grade="TL-110")
for step in run.stream():
print(step.name, step.status, step.duration)
The same run engine, the same policy checks, the same audit trail — from the terminal, the HMI or the SDK.
$ pulpum run "grade change PM4 to TL-110" --autonomy L3
→ plan composed 10 steps · 1 approval gate
→ twin.simulate 48 candidates · best #31 · risk 0.07
→ policy.evaluate 9 writes permitted · 1 held for human
→ executing stock.refine ... ok 2m10s
→ executing wetend.dose .... ok 1m26s
→ executing form.headbox ... ok 1m05s
→ executing dry.steam ...... ok 3m18s
! approval required speed_ramp 1180 → 1245 m/min
→ approved J. Okonkwo · machine tender · 04:57:12
→ run complete 11m42s · off-spec 6.2 t · breaks 0
$ pulpum runs show run_8f21c4 --format genealogy
Enough to extend the platform; not enough to bypass its guardrails.
Declare tags, direction, engineering units, magnitude and rate limits. The policy engine validates every call against them.
An agent is a goal statement, a bounded tool set, a verification strategy and an autonomy level. Nothing more implicit than that.
Levels, approval chains and tag classes are versioned files, reviewed in a pull request like any other change.
Run a candidate recipe against a local twin snapshot before it ever reaches a mill-edge node.
Replay any historical run against a new model version and diff the decisions step by step.
Server-sent events for run progression, tool calls and status changes, with the same payloads the console shows.
Three resources: runs, steps and approvals. Everything else is a read on the audit log.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/runs | Start a run from a goal and a machine |
| GET | /v1/runs/{id} | Run record: plan, steps, statuses, durations |
| GET | /v1/runs/{id}/stream | Server-sent events for live progression |
| POST | /v1/runs/{id}/cancel | Stop a run and hand control back to the DCS |
| GET | /v1/approvals | Pending human approval gates |
| POST | /v1/approvals/{id} | Approve or reject, with the approver identity |
| POST | /v1/twin/simulate | Rank candidate recipes without executing |
| GET | /v1/reels/{id}/genealogy | Full reel record for release and audit |
| GET | /v1/audit | Append-only log, filterable and exportable |
A run record is exactly what the console renders — no privileged view, no hidden fields.
Mill Orchestrator — Pulled the 110 gsm testliner spec, customer tolerances and the standing energy budget from mill MES; locked the target envelope for the run.
Mill Orchestrator — Simulated 48 candidate transition recipes on the as-run paper-machine twin — forming, press, dryer and calender — and ranked them on off-spec tonnes, break risk and steam.
Pulp-and-Stock — Stepped refiner specific edge load 1.9 → 1.4 Ws/m and pushed freeness toward 412 CSF while consistency held at 3.4%.
Wetend-and-Chemistry — Retention aid trimmed to 214 g/t and sizing to 1.1 kg/t against live charge and turbidity; first-pass retention recovered to 78% inside 90 seconds.
Form-and-Press — Re-cut the slice profile across 78 actuators and set jet-to-wire to 0.994 to hold formation index through the basis-weight ramp.
Form-and-Press — Nip load reduced 620 → 540 kN/m to protect the lighter web; post-press dryness landed at 47.1%.
Dry-and-Coat — Re-phased the steam schedule across 6 dryer groups and rebalanced the hood; reel moisture converged to 7.4% ±0.19 2σ at 6.1% less steam than the standing recipe.
Defect-and-Inspect — 18 line-scan cameras streaming; two edge-crack precursors detected at the drive side and cleared by a 40 kN/m nip trim before either propagated.
Mill Orchestrator — Speed ramp 1,180 → 1,245 m/min exceeded the site autonomy threshold. Held for the machine tender; approved by J. Okonkwo at 04:57:12.
Quality-and-Conformance — Reel R-24188 released: full genealogy written (furnish, chemistry, CD profiles, defect map, operator actions) and checked against grade spec.
The SSE payloads are the same records shown here, one event per tool call and result.
Plan → thought → action → observation, exactly as the orchestrator recorded it.
Move PM4 from 135 gsm kraftliner to 110 gsm testliner with zero breaks and under 14 minutes of off-spec production.
Simulate the transition on the twin first. Lead with stock and chemistry so the furnish is right before the basis weight ramps, then trim forming and press, then re-phase drying. Watch the web continuously; hold the speed ramp for a human.
The standing recipe drops basis weight and speed together. On the twin that produces a 3-minute moisture excursion because the dryer section unloads faster than the steam schedule can follow. Sequencing the steam re-phase ahead of the basis-weight ramp removes it.
twin.simulate(candidates=48) → recipe #31 re-phases steam 40 s before the basis-weight ramp and holds nip load until post-press dryness confirms.
Recipe #31 estimates 6.4 t off-spec against 9.8 t for the standing recipe, with break risk 0.07. Two candidates scored lower on steam but raised break risk above the 0.15 site limit and were discarded.
Execute recipe #31 under autonomy level L3: nine setpoint writes permitted, speed ramp routed to the machine tender.
Edge-crack precursor at 1,412 mm drive side at 04:56:41. Nip trim of −40 kN/m in press-2 cleared it in 16 s without a break.
Run complete in 11 m 42 s. 6.2 t off-spec, zero breaks, 6.1% less dryer steam than the standing recipe. Reel R-24188 released with full genealogy.
The path a new agent or model takes before it can write to production.
Write the tool definitions and the agent goal. Limits are mandatory; there is no unbounded write tool to fall back on.
Run against a local twin snapshot and a library of historical scenarios, including rare break and upset cases.
Re-run 90 days of historical runs and diff every decision against the incumbent model. Unexplained divergences block promotion.
Golden datasets plus LLM-as-judge on the reasoning traces, gated in CI. A failing evaluation fails the build.
Deploy to the mill edge in shadow mode. It records what it would have done and writes nothing.
Advisory, then supervised, then bounded — each step gated by the site, with one-command rollback by model version.
A mill does not go from manual to unattended in one step. Pulpum makes the level explicit, auditable and reversible at any time.
| Level | What the agent does | What the human does | Typical time to reach |
|---|---|---|---|
| L1 · Advisory | Recommends setpoints and explains why | Enters every change manually | Week 1 |
| L2 · Supervised | Proposes a write; it executes on approval | Approves each write in the HMI | Week 3–6 |
| L3 · Bounded | Writes inside tag, rate and magnitude limits | Approves ramps and grade releases | Month 2–4 |
| L4 · Unattended | Runs the envelope without prompting | Sets the envelope; reviews the shift record | Month 6+ [ASPIRATIONAL] |
Two agents will want the same actuator. The orchestrator arbitrates on the run goal, not on who asked first — and the handoff is logged like any other step.
Form-and-Press wants to hold nip load to protect post-press dryness.
Defect-and-Inspect wants to reduce nip load to clear an edge-crack precursor.
Break risk 0.62 outranks a 0.4-point dryness loss under the run goal "zero breaks". Defect-and-Inspect wins the actuator for 120 s.
Actuator returned; Form-and-Press recovers dryness with vacuum instead. Post-press dryness lands at 47.1%.
Pulpum reads and writes through the systems already on the floor. No rip-and-replace, no parallel historian, no new HMI to learn.
Valmet IQ, ABB 800xA QCS, Honeywell Experion MX
Profiles, scans, lab results
ABB 800xA, Valmet DNA, Honeywell Experion, Siemens PCS 7
Setpoint reads and guarded writes
WIS/WMS line-scan, IR and transmission cameras
Frames, defect maps, break replays
SAP PP/QM, ABB cpmPlus, custom historians
Orders, grades, reel genealogy
OSIsoft PI, Aspen IP.21, InfluxDB
Time-series backfill and replay
NVIDIA Isaac, winder and wrapper PLCs
Reel, roll and clamp-truck motion
Azure AD, Okta, on-prem LDAP
SSO, RBAC, named approvers
NVIDIA Jetson Orin, IGX, on-prem GPU
Sub-100 ms inference at the machine
Pulpum writes to production equipment. Every capability is scoped, every write is policy-checked, and every action is written to an append-only audit log the mill owns.
| Standard | Scope | Status |
|---|---|---|
| SOC 2 Type II | Cloud control plane | RUNNING In progress [ASPIRATIONAL] |
| ISO 27001 | Company-wide ISMS | QUEUED Planned [ASPIRATIONAL] |
| IEC 62443 | Mill-edge OT security | RUNNING Design-aligned |
| GDPR | Operator data | SUCCEEDED Compliant |
| ISO 9001 / FSC | Quality + chain of custody records | SUCCEEDED Supported |
The questions mill managers and process engineers actually ask in the first meeting.
Python is the first-class SDK. Everything the SDK does is available over the REST API, so any language can start runs, read records and respond to approvals.
Yes, within the platform's guardrails. You define tools with limits and an agent with a goal and autonomy level; you cannot define a tool without limits or bypass the policy engine.
The local twin harness ships with anonymised machine snapshots and a scenario library, including rare break and formation-upset cases.
Every model is pinned by version per machine. Rollback is a single command and takes effect at the next scan cycle.
Yes — a hosted sandbox with a simulated PM4 that runs the same orchestrator, policy engine and audit log as production.
Run progression, approvals and audit entries are available as server-sent events and as outbound webhooks with signed payloads.
Get SDK access, the sandbox mill and the tool-definition reference.
↑↓ navigate↵ openesc close