← Blog

AI agents

RFQ-agent voor een semicon-leverancier: van €4,12 naar €0,38

Een inkoper plakte vrijdag om 16:52 een STEP-bestand in Teams en vroeg een offerte voor maandag. Achter dat bestand: een 12 jaar oude Plex-ERP en 16 openstaande RFQ's.

Jacob Molkenboer· Oprichter · A Brand New Company· 24 feb 2026· 9 min
Antiek koperen schakelbord met stoffen kabels, offerteformulier met groene memo, koperen bel, potlood op ivoorkleurig papier.

Een inkoper bij een van Europa's grotere fabless-klanten plakte vrijdag om 16:52 een STEP-bestand in Teams, vroeg een offerte "liefst maandagochtend" en ging naar huis. De shop floor lead bij onze klant, een semicon-toelevering van 28 man in Eindhoven, had er al zestien openstaan. Een offerte van begin tot eind kostte haar vijfenveertig minuten op een goede dag en een uur op een slechte. Haar week zat al vol.

Die ene paste in Teams was de derde RFQ die we die middag voorbij zagen komen. Aan het eind van het bezoek hadden we er 164 geteld over de week. Op jaarbasis ziet dezelfde shop ruwweg 42.000 tekeningaanvragen per jaar. De kosten per offerte, volledig belast, bedroegen €4,12. De acceptatiegraad op offertes die na de maandagdeadline terugkwamen was 11 procent. Op offertes binnen zes uur 38 procent. Het rekensommetje op dat gat bekostigde het hele project.

Wat de inkoper eigenlijk opstuurt

Een semicon-tekeningaanvraag is geen één bestand. In een typische week komt het binnen als een STEP- of IGES-geometrie, een 2D PDF met GD&T-callouts, een tolerantie-spec die verwijst naar een klantspecifieke tekeningstandaard, en een vrij geformuleerde mail die zegt: "we hebben er 12 nodig, zwart geanodiseerd, maar de tapgaten zijn H7, niet H8 zoals vorige keer." De chat-agent hoeft niet te offreren. Hij moet de offertecontext samenstellen, de inkoper de drie vragen stellen die toch altijd gesteld worden, en een complete RFQ-envelop bij de shop floor lead afleveren.

Dat goed doen vereiste dat het STEP-bestand gelezen werd. Dat stuk leefde tot april in een SolidWorks-macro op een Windows-VM in de hoek van het kantoor.

Waarom de SolidWorks-brug eraan moest

De vorige opzet was, vriendelijk gezegd, een Heath-Robinson-constructie. SolidWorks draaide in een Windows-VM. Een C#-macro opende elk nieuw STEP-bestand, mat bounding box, oppervlak, gatenaantal en wanddikte, en schreef een JSON-blob naar een gedeelde folder. Een Python-script pikte de blob op, riep een eigen PostgreSQL stored procedure aan die feature counts mapte naar routing-bewerkingen (boren, frezen, EDM, oppervlaktebehandeling), en produceerde een conceptofferte.

Het werkte. Het kostte een SolidWorks-licentie van €4.800 per jaar, plus de Windows-VM, plus het feit dat elke wijziging aan de macro een ontwikkelaar vereiste die zowel SolidWorks-API-eigenaardigheden als de routing-conventies van de firma kende. Er waren twee zulke mensen in het pand. Eén had ouderschapsverlof. Toen de macro op een zaterdag om 02:00 's nachts crashte, wat dankzij Windows Update ongeveer eens per maand gebeurde, was er niemand bereikbaar.

Het diepere probleem was bereik. De brug kon alleen de vragen beantwoorden waar de macro voor geschreven was. Een inkoper die vroeg "wat als we de H7 naar H8 brengen, schuift de prijs dan?" had iemand nodig die SolidWorks opende, het model wijzigde, opnieuw exporteerde en opnieuw doorrekende. Dat heen-en-weer doodde de same-day acceptatiegraad.

CadQuery als parser

CadQuery is een Python-library bovenop de OpenCascade-kernel. Hij leest STEP en IGES, geeft je een echte B-Rep-boom en laat je features programmatisch bevragen. We kozen het om drie redenen: het draait overal waar Python draait, er zijn geen licentiekosten, en zijn API is voldoende werkwoord-vormig dat Claude er via tool use mee uit de voeten kan zonder veel handhouden.

De vervanging is een kleine FastAPI-service die precies de delen van CadQuery aanbiedt die de agent nodig heeft:

import tempfile
from fastapi import FastAPI, UploadFile
import cadquery as cq

app = FastAPI()

@app.post("/inspect")
async def inspect(file: UploadFile):
    with tempfile.NamedTemporaryFile(suffix=".step", delete=False) as tmp:
        tmp.write(await file.read())
        path = tmp.name

    body = cq.importers.importStep(path)
    solid = body.val()
    bbox = solid.BoundingBox()
    return {
        "bbox_mm":      [bbox.xlen, bbox.ylen, bbox.zlen],
        "volume_mm3":   solid.Volume(),
        "surface_mm2":  solid.Area(),
        "hole_count":   len([f for f in solid.Faces()
                             if f.geomType() == "CYLINDER"]),
        "thin_walls_mm": thin_wall_scan(solid, threshold=1.5),
    }

Dat endpoint is één van de negen die de agent kan aanroepen. De rest dekt doorsnedeanalyse, tolerantie-extractie uit de PDF (via een aparte OCR-stap die in dezelfde loop draait), het opzoeken van klantspecifieke tekeningstandaarden, en het uitlezen van routing-regels uit Postgres.

De Claude tool-use loop

De orkestrator is een Claude tool-use loop in de geest van Anthropic's tool-use docs. De agent ontvangt het Teams-bericht, de bijlagen en een system prompt die hem de "RFQ-voorbereider" van de firma noemt. Hij plant vervolgens, roept tools aan, stelt de inkoper vervolgvragen wanneer de geometrie ambigu is, en levert uiteindelijk een complete envelop bij de shop floor lead in Plex af.

tools = [
    {"name": "inspect_step",                "input_schema": {...}},
    {"name": "extract_tolerances_from_pdf", "input_schema": {...}},
    {"name": "lookup_routing",              "input_schema": {...}},
    {"name": "lookup_customer_standard",    "input_schema": {...}},
    {"name": "draft_quote_in_plex",         "input_schema": {...}},
    {"name": "ask_buyer",                   "input_schema": {...}},
    {"name": "check_account_status",        "input_schema": {...}},
]

resp = client.messages.create(
    model="claude-sonnet-4-5",
    system=SYSTEM_PROMPT,
    tools=tools,
    messages=conversation,
    max_tokens=4096,
)

while resp.stop_reason == "tool_use":
    tool_results = run_tools(resp.content)
    conversation.append({"role": "assistant", "content": resp.content})
    conversation.append({"role": "user",      "content": tool_results})
    resp = client.messages.create(
        model="claude-sonnet-4-5",
        system=SYSTEM_PROMPT,
        tools=tools,
        messages=conversation,
        max_tokens=4096,
    )

Twee designkeuzes doen ertoe. Eén: draft_quote_in_plex schrijft naar een staging table, nooit naar de productie-offertetabel. Een mens in Plex klikt nog steeds op "release." Twee: ask_buyer is een tool, geen fallback. De agent wordt aangemoedigd om in helder Nederlands dezelfde drie vragen te stellen die de shop lead zou hebben gesteld: bevestig materiaal, bevestig batchgrootte, bevestig oppervlakteafwerking. Inkopers vinden het prettig. De conversie op door de agent gestelde verduidelijkingen ligt hoger dan op de vrij ingevoerde spec van de inkoper zelf.

Aansluiten op een 12 jaar oude Plex-installatie

Plex is een productie-ERP uit de late jaren 2000, tegenwoordig eigendom van Rockwell Automation. De installatie waar wij mee werkten had sinds 2014 geen grote upgrade gezien. Zijn REST-API bestaat, maar is voor de helft van de endpoints die wij nodig hadden niet gedocumenteerd. De routing-data leefde in een aparte zelfgebouwde PostgreSQL-database die de firma in 2017 had opgezet omdat Plex' routing-module niet aansloot op hoe ze hun bewerkingen daadwerkelijk sequentieerden.

We hebben Plex niet aangeraakt. We schreven een kleine read/write-adapter die via een service account met zijn database praat, plus een Postgres-adapter voor de routing-DB. Beide adapters worden als tools aan de agent aangeboden. Alles wat de agent schrijft gaat naar een staging table die de nachtelijke job van Plex oppikt. Faalt de staging-rij in de Plex-validatie, dan krijgt de agent de error terug als tool result en krijgt hij één retry voordat hij de shop lead oppiept.

Waarschuwing

Weersta de aandrang om "eerst het ERP te moderniseren". Elk project dat we hebben zien beginnen met "we migreren Plex even" duurde achttien maanden en bereikte de AI-stap nooit. Wikkel, vervang niet.

De cijfers, eind week twaalf

De agent ging op een maandag in maart live. Eind week twaalf verwerkte hij 820 tekeningaanvragen per week, krap negentig procent van de totale instroom. De shop floor lead reviewde elke offerte in de eerste maand, en ging daarna over op steekproeven van één op vijf.

De unit economics:

  • Kosten per aanvraag daalden van €4,12 naar €0,38. Ongeveer €0,21 daarvan is Claude API-tokens; de rest is de FastAPI-service, OCR voor de PDF's, en een plak Postgres.
  • Het percentage offertes dat dezelfde dag terugging steeg van 24 naar 87 procent.
  • De acceptatiegraad op same-day-offertes bleef op 38 procent. We hadden verwacht dat hij zou zakken omdat de agent agressiever offreert. Dat gebeurde niet.
  • De SolidWorks-licentie is weg. De Windows-VM is weg. De zaterdag-on-call-rota voor de macro is weg.

Op jaarbasis is de kostenbesparing op alleen het offreren ongeveer €157.000. De omzetbesparing — offertes die anders te laat geweest en afgewezen zouden zijn — is lastiger vast te pinnen, maar een conservatieve inschatting komt op ruwweg €1,1 miljoen extra geaccepteerd werk in het eerste jaar.

Wat in de eerste drie weken kapotging

De agent zat in week twee fout op de wanddikte van een dunwandige aluminium behuizing. CadQuery's heuristiek op basis van de bounding box miste een interne pocket. De shop lead ving het op in review. We voegden een tweede tool toe, thin_wall_scan, die rays door het model schiet en de dunste wand terugmeldt. De agent roept die tool nu aan zodra het materiaal aluminium, magnesium of titanium is.

De agent was in week één te gretig met verduidelijkingsvragen. Inkopers klaagden. We zetten de system prompt strakker: vraag alleen wanneer de geometrie echt ambigu is, niet als veiligheid. Tool-use loops zullen standaard te veel vragen. Je moet ze de andere kant op duwen.

De agent stuurde een offerte naar een inkoper wiens bedrijf die ochtend in een betalingsgeschil zat met de firma. Niemand had de agent dat verteld. We voegden check_account_status toe als de eerste tool die op elk gesprek wordt afgevuurd, en gemarkeerde accounts routen we nu naar een mens. De agent weet niet wat je CFO weet. Vertel het hem.

Wat de shop lead nu daadwerkelijk doet

Voor dit project bracht de shop floor lead haar week door met kopiëren en plakken tussen Teams, SolidWorks, Plex en de routing-database. Ze besteedt 'm nu aan het werk dat de agent niet kan: over de vloer lopen, praten met de inkopers van die paar RFQ's die de agent escaleert, en routing-regels heronderhandelen met de operators als er iets nieuws door de deur komt. De agent legde in de eerste maand zes routing-regels bloot die waren weggedreven van wat de operators daadwerkelijk op de vloer deden; zij heeft ze gefikst. Haar werk werd zwaarder in de interessante richting.

Waarom dit soort project nu pas vliegt

Dit project zou twee jaar geleden niet gevlogen hebben. Tool-use loops waren niet betrouwbaar genoeg. CadQuery's STEP-importer had bugs die inmiddels gefikst zijn. Claude's instruction-following op meertraps engineering-taken haalde ergens eind 2025 een drempel. Drie eerdere prototypes die we in 2024 op dezelfde klanteisen draaiden, strandden steeds op hetzelfde loop-betrouwbaarheidsprobleem dat het huidige model schoon afhandelt. De vierde poging was degene die live ging.

Toen wij dit voor de Eindhovense shop bouwden, liepen we steeds tegen hetzelfde aan: de agent moest weten wat een menselijke offrant als volgende zou vragen, niet wat het bestand bevatte. De fix was geen slimmer model. Hij was de daadwerkelijke routing-regels van de firma als tools aanbieden en de loop ze laten aanroepen. Als jouw team de week kwijt is aan context verzamelen vóór het echte werk begint, is dat het gat waar een AI-agent zijn geld verdient.

De vijfminutenaudit: tel de inkomende RFQ's, tickets of facturen van vorige week. Vermenigvuldig met de belaste kosten van de persoon die ze afhandelt. Komt het antwoord boven €40.000 per jaar uit, dan heb je een project dat het scopen waard is.

Kern

Wikkel het verouderde ERP, vervang het niet. Een Claude tool-use loop die RFQ-context samenstelt verdient meer dan een offertemodel dat getraind is om te prijzen.

FAQ

Waarom CadQuery in plaats van de SolidWorks-API?

CadQuery draait overal waar Python draait, kent geen licentiekosten, en zijn werkwoord-vormige API is makkelijk als agent-tool aan te bieden. De SolidWorks-brug vereiste een Windows-VM en een ontwikkelaar die zowel de SolidWorks-API als de routing-regels van de firma kende.

Offreert de agent autonoom?

Nee. Hij schrijft naar een staging table binnen Plex. Een mens in Plex klikt nog steeds op release. De taak van de agent is de offertecontext samenstellen, niet zich aan een prijs committen.

Wat was de kostenopbouw per offerte na de verbouwing?

€0,38 per RFQ van begin tot eind. Ongeveer €0,21 is Claude API-tokens. De rest is de FastAPI-service, OCR voor de PDF's, en het stuk Postgres dat de routing-adapter aanraakt.

Daalde de acceptatiegraad doordat de agent sneller offreert?

Nee. De acceptatiegraad op same-day-offertes bleef op 38 procent en het volume van same-day-offertes is bijna verviervoudigd, dus het totaal geaccepteerde werk ging fors omhoog.

Waarom niet eerst van Plex af migreren?

ERP-migraties duren 12 tot 18 maanden en houden AI-werk op. Plex omwikkelen met read/write-adapters en een staging table kreeg de agent in twaalf weken live, zonder het ERP zelf aan te raken.

ai agentscase studyautomationintegrationsarchitectureoperations

Iets bouwen?

Start een project