Work / P-03 · Jul – Sep 2026 · Dochak, 2026

A
guardrailed
AI
agent
that
edits
and
runs
traffic
simulations

A web dashboard for PTV VISSIM where an agent edits and runs simulations in plain language — and every edit passes a validation layer and one human approval before it touches the model.

Role
Product developer at Dochak, remote · frontend, agent tools, validation layer
Recognition
Built in eight weeks · 482 commits, July 16 – September 9, 2026
Stack
Next.js · React · FastAPI · PTV VISSIM (COM) · Claude · d3 · Leaflet
Outcome
117 constraints at three stages; one approval equals one run; nothing touches the original file

Demo, scene by scene

Demo, Aug 2026
Step 01 / 7

Network generation from a map

Name a region. Prism fetches the road network from OpenStreetMap, projects it, checks connectivity, drafts demand and signals, and emits a VISSIM file. The validation gates run before anything is saved; this is the pipeline that refused our own network on 11 August.

Genesis · Overpass → osm → project → connectivity → draft → demand → signals → compose → emit → gate (V1–V9)

Step 02 / 7

How an edit actually happens

A request goes to the agent. It picks from a registry of 87 typed tools with strict dispatch. Every write is checked against 117 named constraints, each with a reason code. Nothing is written without an approval card, and one approval runs exactly once.

tool registry (87) · constraint catalogue (117) · human approval · single-use, bound to the call

Step 03 / 7

Data intake

Models and observations come in as files: the .inpx itself, count workbooks, existing result tables. Prism profiles them, maps columns, and flags what is missing before any calibration starts, so a gap shows up here rather than in a report.

.inpx · observed counts · result databases · column mapping · health check without a VISSIM install

Step 04 / 7

The simulation is real

PTV Vissim 2026 is driven over COM in a fresh instance. The run is queued, seeds progress one by one, and the result databases are read back and cross-checked against each other. This is not a mock.

COM automation · queued run · seeds 1…5 · result DBs read back · post-run cross-check

Step 05 / 7

Dashboard curation

Instead of printing every chart, an LLM picks the ones that answer the question you asked, and says why. Ask why the average speed is low and you get the two charts that explain it, not forty.

question → chart selection → short rationale · scenario comparison · KO / EN / JA

Step 06 / 7

Validation and calibration surface

GEH checks against observed counts, and the thirteen steps of the client authority’s operational-modelling ladder, visible in the UI as a status rail. The honest limit, stated on the slide: not yet tested against a real-world project.

GEH base-model validation · 13-step MRWA ladder as a status rail · limit: no real-world test yet

Step 07 / 7

Reports inherit a firm’s own format

Upload a past report as .docx and Prism extracts a style profile: palette, font ladder, page size and margins, heading numbering, table header fill. New reports are rendered in that style, so the output looks like the firm wrote it.

.docx → style profile → rendered report · palette · fonts · margins · numbering · table styles

Demo, Aug 202601 · Network generation from a map
01 / 7 · Network generation
117
constraints checked before, after edit and after run
482
commits in eight weeks
87
agent tools
825
real VISSIM networks in the validation corpus

Context

Jul – Sep 2026
01 — Problem

VISSIM fails silently

Traffic engineers calibrate VISSIM models by hand: cycle lengths, time-sliced demand, route splits, conflict priorities. A wrong edit does not crash. It produces plausible numbers, and the error surfaces weeks later in a report.

Handing those edits to a language model makes the speed problem better and the silent-failure problem worse. The product question was never whether an AI could edit a network. It was how an engineer could trust that it had.

02 — Approach

The validation layer is the product

Every request follows one path: draft the edit, run pre-checks, show an approval card with a mini-map of what will change, execute once per approval, read the file back to verify, then report. Approvals are signed and single-use.

Edits happen on a working copy and land by atomic swap, so the original is never touched. After a run, Prism cross-checks result files, vehicle arrivals and evaluation tables against each other — we called it lie detection. The guiding rule: an edit rejected with a clear reason beats one completed with wrong numbers.

00

Context

Dochak builds digital-twin tools around PTV VISSIM for traffic engineers. Calibration is skilled and slow: an engineer edits signal timings, demand and route splits by hand, runs a batch of seeds, and reads the tables. A wrong edit never crashes. It produces plausible numbers.

I joined remotely in July 2026 with one question: could an agent do the edits without making that silent-failure problem worse? Eight weeks and 482 commits later the answer was a validation layer with the agent behind it, not the other way round.

How it works

Fig. — Edit pipeline, one request
Step 01 / 8

Request in plain language

An engineer asks for a change: shorten the cycle at node 7 from 120 to 90 seconds. The agent reads the live network over the backend, never from memory.

Next.js chat → FastAPI → agent tools (87) · read signal phases, demand, routes, conflict areas

Step 02 / 8

Draft the edit

The agent proposes a concrete parameter change with the object ids it will touch. Nothing is written yet.

draft = { tool, params } · canonical JSON · shown with a mini-map of affected objects

Step 03 / 8

Pre-check rejects the first draft

The constraint catalog runs before any write. The first draft violates a minimum green time and is refused with the reason, not silently clamped.

117 constraints · 94 preflight · 52 refuse / 65 warn · reason attached to the refusal

Step 04 / 8

Redraft passes

The agent revises within the limits and the pre-check passes. Only now does an approval card appear.

preflight ✓ · approval card: before / after values, objects, expected effect

Step 05 / 8

One approval, bound to the call

The engineer approves once. The approval is bound to that exact tool call and is consumed on use. One click runs one job, never six.

identity = tool + canonical sorted JSON (not a cryptographic signature) · single-use · reviewer or admin role

Step 06 / 8

Run on a working copy

VISSIM is driven over COM in a fresh instance, on a copy of the file. A batch of seeds runs; the original is never opened for writing.

SaveNetAs <stem>_saving.inpx → os.replace · new VISSIM instance, never the user’s open GUI · seeds 1–5

Step 07 / 8

Read back, then cross-check

After the write the file is read back and compared to what was requested. After the run, result files, vehicle arrivals and evaluation tables are checked against each other.

postwrite 8 checks · postrun 12 checks · we called the post-run step lie detection

Step 08 / 8

Report, with rollback

The engineer gets a KPI summary and trajectories, a versioned .inpx to download, and a one-step rollback.

reports in KO / EN / JA · versioned downloads · GEH base-model validation

Fig. — Edit pipeline, one request01 · Request in plain language
dataapprovalrejected1 approval = 1 runsingle-use approval, bound to the exact callrollbackEngineerAgent draftPre-checkApproval cardRunRead-backCross-checkReportConstraint catalogWorking copyVISSIM (COM)Original filestage 1 / 8
user
Traffic engineer in the Prism web UI · reviewer or admin role required to approve
draft
Claude via the backend planning loop · 87 tools · reads phases, demand, route splits, conflict areas, reduced-speed zones
check
backend/services/agent/constraints.py · 117 Constraint dataclasses in 7 sections
approve
pending_approval.json · identity = tool + canonical JSON, not a cryptographic signature · deleted on validation · PreapprovedWriteGate discards after first grant
run
PTV VISSIM 2026 over COM · fresh instance per run · progress per seed
readback
Written value vs read-back value vs saved file must agree
cross
Result files · vehicle arrivals · evaluation tables cross-checked · SIMULATIONRUN row trusted
report
KPI summary · trajectories (.fzp replay) · scenario comparison · KO / EN / JA
catalog
preflight 94 · postwrite 8 · postrun 12 · dataset 3 · refuse 52 / warn 65
copy
Edits land on a working copy and are swapped in atomically
vissim
PTV VISSIM 2026 · COM automation · FastAPI :8001
original
Never opened for writing · versioned downloads · rollback

Deep dive

05
03 — Result

The checks caught our own mistakes first

The validation gates rejected the team’s own generated network for eight isolated zones across 150 links before any user saw it. An evaluation harness runs 15 tasks with injected faults, with and without the guardrails, to measure what the layer actually prevents.

Prism also ships a model health check that needs no VISSIM install, a network renderer for eleven element types with trajectory replay, GEH-based base-model validation, and reports in Korean, English and Japanese.

04 — Architecture

A thin agent on a thick validation layer

Next.js 16 and React 19 in front, FastAPI behind, PTV VISSIM 2026 driven over COM. The agent is a planning loop around Claude with 87 tools, each of which reads or writes through the same gates a human edit would. Storage is files only: the .inpx, its working copies, result tables and a JSON log per approval.

The constraint catalog is the product. It grew from about fifty rules in the README to 117 dataclasses in code, grouped into pre-flight, post-write, post-run and dataset checks, each marked refuse or warn.

05 — Rules and guardrails

Why approvals are single-use

Early on, one approval click launched six 300-second simulation runs. That incident produced the current design: an approval is bound to the exact tool call, stored once, deleted when validated, and discarded by the write gate after its first use. Every edit happens on a copy and lands through an atomic rename; the user’s open VISSIM window is never attached to.

Genesis’s own validation gates rejected our generated network on 11 August 2026 for eight isolated zones across 150 links, before anyone else saw it.

06 — Evaluation

Measuring silent failure

An evaluation harness runs fifteen tasks: reads, edits, refusals, runs and one clarification. Five fault injectors corrupt the agent’s behaviour on purpose, from a wrong parameter name to a hallucinated object id to a clamped or ignored write. A detector then scores whether the failure would have reached the user unnoticed.

With the guardrails on, sixty percent of injected silent failures were caught; with them off, none were, over eighty trials. The blind spot that remained is recorded in the harness. A promising calibration result, GEH 7.53 to 4.19, was retracted when we found it had edited an observed entrance input against a synthetic workbook. The product now refuses that edit by name, and the case is a regression test.

07 — Beyond the agent

What else shipped in eight weeks

A model health check that needs no VISSIM install. A network renderer for eleven element types with trajectory replay. GEH-based base-model validation against observed counts. Genesis, which builds a VISSIM network from OpenStreetMap through connectivity, demand and signal stages. A calibration status rail that tracks the thirteen-step Main Roads Western Australia ladder, not yet tested against a real-world project.

Specification

08
Stack
Next.js 16 · React 19 · Tailwind 4 · d3 · Leaflet · FastAPI · PTV VISSIM 2026 (COM) · Claude
Scale
482 commits · 126 API routes · 19 pages · 87 agent tools · ~5,400 tests
Constraints
117 in code: preflight 94 · postwrite 8 · postrun 12 · dataset 3 · refuse 52 / warn 65
Evaluation
15 tasks · 5 fault injectors · silent-failure detector · 60% caught with guardrails vs 0% without (N = 80)
Validation corpus
825 real .inpx networks
Timeline
16 July – 9 September 2026, remote
Role
Product developer at Dochak: frontend, agent tools, validation layer, demo parts B, C, E, F
Status
Private product; no client data shown