hashintel/hash/petrinaut
- community
Checking that the SKILL.md file is still in the repository.
Using the Petrinaut tools and writing net code. Use before the first net change, before writing lambda, kernel, dynamics, visualizer, metric or scenario code, before drafting or creating an experiment, and when the USER asks how something in the Petrinaut UI works.
Install
npx vskill@latest install hashintel/hash/petrinautSKILL.md
Petrinaut
Routing
When the USER asks how a Petrinaut UI workflow works, or you need to confirm a UI detail before instructing them, read references/docs.md for the user-guide pages readPetrinautDoc can return.
When you need a worked example of a complete net definition (coloured tokens, stochastic and predicate transitions, kernels with distributions, continuous dynamics, parameters, visualizer code, metrics and scenarios), read references/examples.md.
Before drafting or creating an experiment, read references/experiments.md for the request's fields and limits and what the draft and run tools do.
Tools
Make every net change through the mounted tools; never emit free-form net JSON. They use Petrinaut's raw mutation interfaces, so include stable IDs, full entity objects where required, and canvas positions for places and transitions. The mounted schemas, not this prose, govern exact payload fields.
You can check current TypeScript compilation diagnostics at any point using the getNetCompilationErrors tool, and rename the net using the setNetTitle tool.
Reading the net
Three tools read the current net, each returning { title, definition, extensions }: the user-visible net title, the SDCPN, and the active extension capabilities for this document.
readNetOutlineleaves out code and expressions (including parameter overrides, component parameter values and scenario initial states beyond the shape of an ad-hoc one), canvas positions and visual settings.readNetStructureadds that code and those expressions.getLatestNetDefinitionreturns the complete definition, including positions and visualizer code.
A change is refused unless a read of the net is in context, so read it before the first change. Don't reread at the start of an exchange in case the USER edited the net: a change against an edited net is refused without starting, and the refusal tells you to read again. After a step of changes, use the last result's netAfterChanges instead of rereading. Read again only for code or fields netAfterChanges omits, before a live explanation, and at delivery. Consult extensions before authoring extension-specific content, and title when deciding whether the net needs a more descriptive name.
Making changes
Send one bounded connected fragment in one step, as parallel mutation calls in dependency order: the types, parameters and differential equations it needs; then places and transitions; then arcs. The host runs a step's calls in that order. You choose every new ID, so the calls that build one fragment do not depend on each other's results. References to existing elements, endpoints and experiment inputs use identifiers observed in a read, never IDs guessed from names.
The host owns immutable binding, protocol correlation, document-base checks, persistence and record attachment. Never copy document hashes, document revisions, observation call IDs or Ledger record IDs into tool inputs.
On a failure, a no-op or an unknown outcome, inspect the result and the current net, then submit only the correction. Never repeat a change that succeeded or may have.
Keep incidental choices small
Required x and y are provisional presentation values: place new nodes on a rough grid, then use layout. For a new type, iconSlug: "circle" and a simple CSS displayColor are sufficient. Optional metadata and port fields are unnecessary for a simple root-net fragment; use them only when the task needs their capability.
For separately wired transitions, start with empty inputArcs and outputArcs, then use addArc operations. Uncoloured places use colorId: null; disabled dynamics use dynamicsEnabled: false and differentialEquationId: null. Keep code strings empty only where their schema permits the built-in behaviour; coloured outputs or a meaningful guard or rate require the corresponding code. Arc weights are token multiplicities, never branch probabilities.
Acceptance
An accepted call establishes conformance to its input schema, and nothing more. After each step check that:
- every intended call was accepted, or its rejection remains explicitly unresolved;
netAfterChangescontains each accepted element under the ID you supplied or the tool returned;- every referenced endpoint exists;
- arc weights are positive;
- no later step depends on a rejected or absent change.
Describe this result as tool-schema accepted, not valid, runnable or simulated.
Extensions
- Check the active
extensionsfrom your latest read before using optional SDCPN features. If an extension is disabled, do not create or rely on its data. - Coloured-token types require
extensions.colors. - Parameters require
extensions.parameters. - Stochastic transition lambdas, for rate-based firing, require
extensions.stochasticity. - Use predicate transition lambdas for boolean firing conditions when
extensions.stochasticityis true, or whenextensions.colorsis true and the transition has at least one standard or read input arc from a coloured place. - Leave transition lambda code empty when neither stochasticity nor coloured standard/read inputs are available; the runtime treats the transition as always enabled once its arc weights are satisfied.
- Use transition kernels to transform or generate coloured output tokens. Use stochastic distributions in kernel outputs only when
extensions.stochasticityis true. Leave kernel code empty when the transition has no coloured output places. - Differential equations require both
extensions.colorsandextensions.dynamics, and apply only to places whose coloured tokens have continuous dynamics.
Writing net code
Lambda, kernel, and dynamics code is a plain function body ending in return — no module, no export default, no wrapper — with the input object and parameters available ambiently. (The legacy export default Lambda((input, parameters) => …) / TransitionKernel(…) / Dynamics(…) module form is still accepted, but write new code as a bare body.)
Every code surface except visualizers accepts only a small TypeScript subset: const bindings, destructuring, guard-style if … return, ternaries, arithmetic, comparison and logic, Math.*, .length, .map(...), record and array literals, and in metrics also .reduce(...) and .concat(...). Loops, let and var, mutation such as .push(...), spread and other helper calls are rejected. To build n tokens, write Array.from({ length: n }, (_, index) => ({ … })) instead of a loop.
Code surfaces
The exact shapes the runtime expects:
- Transition lambda (
transition.lambdaCode): function body returning the firing condition;inputandparametersare ambient. Available when stochasticity is enabled OR when colours are enabled and the transition has at least one standard or read input arc from a coloured place.input.PlaceNameis a tuple sized to the input arc weight for coloured standard and read input arcs; token attributes are typed by the colour element: real/integer → number, boolean → boolean, uuid → bigint, string → string (plain JS strings everywhere, compared by value). Read arcs expose tokens ininputbut do not consume them when the transition fires. Inhibitor arcs and uncoloured input places are NOT ininput. Predicate → return a boolean; stochastic → return a non-negative rate in firings per simulation second (0 disables, Infinity always fires). Must be deterministic. If unavailable or empty, the runtime uses true for predicate-style transitions and Infinity for stochastic-style transitions. Example:return input.Queue[0].priority > parameters.threshold;. - Transition kernel (
transition.transitionKernelCode): function body returning{ OutputPlaceName: [token, …] }sized to the output arc weight;inputandparametersare ambient. Available only for transitions with coloured output places. Include only coloured output places; uncoloured output places are auto-populated. Output values must match element types: real/integer use numbers, boolean uses booleans, string uses plain strings (REQUIRED in the token type; a missing/undefined value becomes the empty string"", and non-string values are stringified viaString(value)). uuid attributes are OPTIONAL in output tokens: omit them to auto-generate a fresh UUID deterministically from the seeded simulation RNG, useUuid.generate()for an explicit fresh UUID,Uuid.from(value)to derive one from a number or arbitrary string, use a UUID string directly, or forward an input token's uuid bigint unchanged. Plain non-UUID values must be wrapped inUuid.from(...); supplying them directly is a type error. When stochasticity is enabled, real attributes may useDistribution.Gaussian(mean, sd)/Distribution.Uniform(min, max)/Distribution.Lognormal(mu, sigma)(never integer/boolean/uuid/string attributes), and chained.map(fn)on the same distribution shares one draw. When stochasticity is disabled, kernel outputs must use plain values only. Leave empty when no coloured outputs exist. Example:return { Processed: [{ id: input.Queue[0].id, done: true }] };. - Differential equation (
differentialEquation.code): function body returning the derivatives array;tokensandparametersare ambient.tokensis THIS place's tokens only. Return an array of the same length whose entries provide derivatives for real-valued elements only (i.e. dx/dt, not the new value); integer, boolean, uuid, and string elements are discrete and remain unchanged by dynamics (they can be read from input tokens but never written). The equation'scolorIdMUST match every referencing place'scolorId. Example:return tokens.map(({ level }) => ({ level: -level * parameters.decay_rate }));. - Place visualizer (
place.visualizerCode):export default Visualization(({ tokens, parameters }) => <JSX/>). Classic React runtime — do NOT import React, do NOT use<>…</>fragments, do NOT use hooks. Convention: return a sized<svg viewBox="0 0 W H">…</svg>. - Metric (
metric.code): a plain function body — NOT a module, noexport default, no wrapper.stateis in scope, and netparametersare available ambiently (read them asparameters.<variableName>). Mustreturna finite number. Example:return state.places.Infected.count / (state.places.Susceptible.count + state.places.Infected.count + state.places.Recovered.count);.scenarioparameters are NOT available inside metrics (only net parameters are). - Scenario per_place initial state:
contentkeys are place IDs; uncoloured values are expressions withparametersandscenarioin scope; coloured values are row arrays in colour element order using numbers and booleans; string columns take literal text; uuid columns accept UUID strings (any other text converts deterministically to a UUID via UUIDv5). - Scenario code-mode initial state: function body returning
{ PlaceName: tokens }keyed by NAME (asymmetric with per_place IDs); unknown names are silently dropped. - Scenario parameter wiring: a
per_placeinitial-state expression reads a scenario parameter asscenario.<identifier>, andparameterOverridesmaps an existing net parameter ID to such an expression. A value that transition code reads throughparameters.<variableName>therefore needs both the net parameter and the override. Metrics cannot read scenario parameters. - Parameter access in any code surface: use
parameters.<variableName>where<variableName>is the parameter's lower_snake_casevariableNamevalue (e.g.parameters.crash_threshold, neverparameters.crashThreshold).
Durations
A stochastic lambda's rate makes the time to firing exponentially distributed, with mean 1 / rate. Use a rate only for what is random in time, such as arrivals or breakdowns. For a fixed or otherwise distributed duration, count it down on the token instead:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingapps/brunch-agent/src/agents/petrinaut/skills/petrinaut/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/hashintel/hash/petrinaut)