Skip to content
Kiran
← Work

Prototype to platform, deliberately

Shipment Milestone Tracking Agent

Two generations live in one repository and the gap between them is the point. The prototype is a script with three-layer intent classification (keywords, then semantic similarity, then a model) over a flat file. The second generation is the same runtime contracts, access layer, middleware seam, skills directory and multi-graph registration as the enterprise platform, with a written migration plan between them. The detail I would point at is a middleware guard that strips SQL from the final answer even though the system prompt already forbids it, with bounded regex repetition so a long response cannot trigger catastrophic backtracking.

2025–2026agenticplatformsecurity

What I owned

Sole author of both generations and of the migration plan between them.

Rows in the tracking dataset
~344KcodeRows in the tracking dataset
Intent classification layers in the prototype
3codeIntent classification layers in the prototype
Output-guard patterns
3codeOutput-guard patterns
Built onLangGraph with a deep-agent frameworkA declarative semantic layer definitionRole-based access and an output guard

The problem

What was actually wrong

Operations needed to ask about shipment milestones conversationally, over a dataset of several hundred thousand rows and around 150 columns.

The prototype answered the question and could not be extended: intent classification was hand-rolled, the data was a flat file, and there was no access control, no middleware seam and no way to evaluate it.

Before this existed

A single-page prototype application over a flat file export.

Constraints

The conditions the design had to hold under

Constraints are the interesting part of an architecture. Without them any diagram looks reasonable.

The prototype was already in use
A rewrite that arrives late and different is a failed rewrite. The migration needed to be planned and staged rather than attempted in one jump.
Answers must never contain SQL
The user is an operations analyst. Internal query text in an answer is both confusing and a disclosure.

My role

Sole author of both generations and of the migration plan between them.

Designed

  • The second-generation architecture: runtime contracts, access layer, middleware, skills and multi-graph registration
  • A written migration plan from prototype to platform

Built

  • Both generations, the role-based access layer, the semantic layer definition, and the SQL output guard

Decisions

The calls I would defend

Each one with the alternatives I rejected, what the choice cost, and how it turned out.

Decision

An after-agent middleware strips SQL from the final answer, even though the system prompt already forbids it.

Context

Prompt instructions are honoured most of the time, which is a different thing from being enforced.

Alternatives, and why not

  • Rely on the system promptAn instruction is a strong prior, not a control. For a property that must hold every time, a prior is not enough.

Rationale

Three patterns, each commented with its reasoning: a select-from construction where requiring the from clause avoids false positives on ordinary phrases like 'select an option', common table expressions, and fenced code blocks. Repetition is bounded so a long response cannot cause catastrophic backtracking.

What it cost

A guard that can, in principle, strip legitimate content. Bounded and tested, and the failure direction is a slightly terse answer rather than a leak.

Outcome

The same instinct as enforcing read-only at the database connection: treat the prompt as advisory and put a deterministic control behind it.

Impact

What changed, and how it is known

Every figure carries its basis. Nothing here is rounded up, and nothing modelled is presented as a result.

~344Kcode
Rows in the tracking datasetAcross around 150 columns.
3code
Intent classification layers in the prototypeKeyword, semantic similarity, then model.
3code
Output-guard patternsEach with bounded repetition to avoid catastrophic backtracking.
Engineering
An independent, sole-authored implementation of the same platform architecture used across the wider agent estate: same runtime contracts, same access layer, same middleware seam, same skills directory, same read-only posture.
People using it
Operations analysts can ask about shipment milestones directly, with role-scoped access and no query internals in the answer.

Leadership and hindsight

What I influenced, and what I would change

What I would do differently

  • The prototype's three-layer intent classifier was more machinery than the problem needed, and the second generation replaced it with routing. I would reach for the simpler thing earlier now.
  • Both generations are in one repository, which was useful during migration and is now just confusing. The prototype should have been retired once the platform version shipped.

Stack

What it is built on, and why that

A technology list without reasons is a list of things I have heard of.

LangGraph with a deep-agent framework
The second-generation agent and its multi-graph registration.Same structure as the enterprise platform, so knowledge and tooling transfer.
A declarative semantic layer definition
Describing the queryable surface.The same argument as everywhere else: domain structure belongs in a reviewable artefact, not in a prompt.
Role-based access and an output guard
Scoping answers and stripping query text from responses.Two independent controls, neither of which depends on the model cooperating.

3 more sections are written and hidden: constraints, leadership, stack.