DocumentationLogin
Enterspeed logo
Enterspeed Blog
Product

Filling in the gaps: the content enricher pattern with Enterspeed and Speedtrain

Jesper Weber
Jesper Weber
Developer Experience Engineer at Enterspeed
Thumbnail for blog post: Filling in the gaps: the content enricher pattern with Enterspeed and Speedtrain

Your PIM knows that a drill has an 18V motor, 55 Nm of torque and weighs 1.2 kg. What it often doesn't have is a product description a customer wants to read. Or that description in Danish, Swedish and German. Or a SEO title, a meta description, or the right category in the new taxonomy.

Source systems are good at holding facts but applications need more than facts.

Filling that gap by hand works for a few hundred products. At 40,000 products in four languages, it doesn't. And the gap tends to grow, because new products arrive faster than anyone can write about them.

The pattern: content enricher

The content enricher is one of the classic enterprise integration patterns, described by Gregor Hohpe and Bobby Woolf. The problem it solves is simple: a message arrives without all the data the receiver needs.

Short version: the enricher sits between the sender and the receiver, adds the missing data from another resource, and passes on a complete message. The receiver gets what it needs without knowing where the extra data came from, and the sender doesn't have to change.

In the original pattern, the extra resource was typically a database or another system you could look things up in. With AI, the resource can generate the missing data instead of looking it up. That changes a lot of what's possible, and it adds a few new ways for things to go wrong.

Where AI enrichment usually goes wrong

There are two common shortcuts, and both cause problems.

AI in the request path. The website calls a language model when a page is rendered, or the frontend generates a description on the fly. It's quick to build, but every request becomes slower and more expensive, the output can differ from one request to the next, and nobody reviews what customers actually see.

AI writing straight into the source. A script runs a model over the PIM and writes the results back into the product records. Now generated content is mixed with your source data, it's hard to tell which is which, and a bad prompt can overwrite thousands of records before anyone notices.

What's missing in both cases is the same: a place where enrichment happens outside the delivery path, with its output checked before it reaches anyone.

Enterspeed and Speedtrain: enrichment as a round trip

With Enterspeed and Speedtrain, the enricher is placed next to the data supply chain rather than inside it. Data crosses between the two systems twice: out to Speedtrain to be enriched, and back into Enterspeed once it has been approved.

Filling in the gaps: The content enricher pattern with Enterspeed and Speedtrain.png

  1. Your data lands in Enterspeed. Your PIM, ERP or CMS pushes records into Enterspeed as source entities, exactly as it does today. Speedtrain isn't involved yet.

  2. Enterspeed pushes it out to Speedtrain. You set a Speedtrain destination on the schema whose views you want enriched. Only that data crosses over, not the whole environment.

  3. Speedtrain does the work. A task configuration describes the job, for example "write a product description in Danish, Swedish and German". Each output is scored by quality rules and routed through a quality gate. Nothing leaves Speedtrain until it has been approved.

4. Approved content returns to Enterspeed. An Enterspeed destination delivers the accepted content back into an Enterspeed source, where it arrives as source entities like any other input. Your schemas pick it up, and your applications read it through the Delivery API or Query API.

The applications never talk to Speedtrain. From their point of view, the description is just another field on the product view.

That's the content enricher pattern: the source doesn't change, the consumer doesn't change, and the message arriving at the consumer is complete.

What it looks like in the schemas

On the way out, a schema sends product views to a Speedtrain index. The destination is set in the schema's actions:

1/** @type {Enterspeed.FullSchema} */
2export default {
3  triggers: function (context) {
4    context.triggers('pim', ['product']);
5  },
6  actions: function (sourceEntity, context) {
7    context.destination('speedtrain').options({
8      indexAlias: 'products'
9    });
10  },
11  properties: function (sourceEntity, context) {
12    return sourceEntity.properties;
13  }
14};

A tip from the docs: send the raw attributes rather than a pre-written summary. A model does better work from structured fields than from prose someone else already condensed.

On the way back, the approved descriptions arrive as source entities in their own source group. Your product schema can then combine the PIM data with the enriched content using a reference:

1/** @type {Enterspeed.FullSchema} */
2export default {
3  triggers: function (context) {
4    context.triggers('pim', ['product']);
5  },
6  routes: function (sourceEntity, context) {
7    context.url(`/products/${sourceEntity.properties.slug}`);
8  },
9  properties: function (sourceEntity, context) {
10    return {
11      sku: sourceEntity.properties.sku,
12      name: sourceEntity.properties.name,
13      specifications: sourceEntity.properties.specifications,
14      description: context
15        .reference('productDescription')
16        .byOriginId(sourceEntity.originId)
17        .sourceGroup('speedtrain')
18    };
19  }
20};

The facts come from the PIM, and the description comes from Speedtrain. The website makes one request and gets one response. If you read the canonical format post, this should look familiar: enriched content is just one more source feeding the canonical layer.

Because enriched content comes back as source entities rather than finished views, it enters the supply chain at the same point as your original data. The schemas, routing and delivery you already have apply to it unchanged.

Governance: humans on the loop

The reason for routing enrichment through Speedtrain rather than calling a model directly is control. A few things matter here.

Speedtrain never edits your source data. It reads from its index and writes to its destination, and it never writes back into the index it read from. An enrichment job can't overwrite the data it was given, and the PIM stays the source of truth for the facts.

Quality is checked before anything is approved. Each output is scored by quality rules, and deterministic rules come first. If something can be checked with code (a length limit, a forbidden word, a required brand term), it should be. AI-based rules are for the judgement calls. The quality gate that turns the scores into a verdict is plain arithmetic, with no model involved.

People decide what gets through. Outputs that don't pass the gate end up in a review session, where a person accepts, edits or rejects them. The approval policy decides how much goes to a human: everything, nothing, or only what the gate flags. You can start strict and loosen it as you gain confidence in a task.

Task configurations are versioned. Prompts, variants and rules live in a versioned task configuration, so you can see what produced a given output and compare versions. One thing to be aware of: records use whichever version is published when they are processed, so publishing a new version changes what runs for everything that arrives afterwards.

Things to plan for

Enrichment isn't instant. The round trip takes time, especially when a human review is part of it. A new product can go live before its description is approved, so design your views and frontends to handle a missing enrichment.

Garbage in, garbage out still applies. If the PIM data is thin or wrong, the generated description will be too. Enrichment is not a substitute for fixing your source data, and it tends to expose where the source data is weak.

Review capacity is a real constraint. Sending 40,000 products through manual review on day one will create a queue nobody can clear. Start with a smaller batch, tune the quality rules until the gate catches what reviewers would catch, and then scale up.

Decide who triggers enrichment. Views can be sent to Speedtrain as data only, with enrichment started from Speedtrain, or with an actions envelope where the source system requests specific tasks, for example from a button in your own admin. Pick one model per use case so it's clear where enrichment is started.

Summary

Source systems hold the facts, but applications and customers need more than facts. The content enricher pattern adds the missing data on the way through, without changing the sender or the receiver.

With Enterspeed and Speedtrain, enrichment happens outside the delivery path. Data goes out to Speedtrain, AI does the work, quality rules and people decide what's approved, and the result comes back into Enterspeed as ordinary source data. Your applications keep reading from Enterspeed and never need to know that part of the response was enriched from another system.

AI where it helps, with humans on the loop.

A note on labelling AI-generated content: Depending on where you publish and what kind of content it is, you may be required to disclose that content was generated or edited with AI. The EU AI Act includes transparency obligations, and other regions have their own rules. Check what applies in the markets you deliver to. If you need a label, add a field such as aiGenerated to the enriched content and let your frontends show the disclosure where it’s required.

Want to try it? Read how data moves between Enterspeed and Speedtrain and how to set up the Speedtrain destination in our docs.

Remember to check out the other blog posts in this series:

Part 1: The Canonical format

Part 2: The Strangler fig pattern

Jesper Weber
Jesper Weber
Developer Experience Engineer at Enterspeed

Loves building software that makes an impact on businesses. Untalented but happy ice hockey player (the beers just taste better in a locker room after a game...)

Ready to try out Enterspeed? 🚀

Start connecting & combining your services today

Solutions

Product OnboardingPublish-ready product dataGoverned AI contentReplatform and migration
Enterspeed logo

© 2020 - 2026 Enterspeed A/S. All rights reserved.

Made with ❤️ and ☕ in Denmark.