Asset Data Nexus Who writes here Write to us

Asset Data Nexus · Working notes

Last year's notifications should not cost a trip

When Joule answers from the live system, every answer starts with a trip there, made again each time somebody asks. The trip is the part you can make once per change instead.

2026-09-26 · Karaoglu Ltd

An assistant that answers from the live system goes back to it for every question. Each trip crosses an interface, and each crossing is paid for somewhere: in messages, agent steps, backend load or tokens.

So interface cost grows with the questions: users, times questions, times the calls an agent makes to answer one. Most of those calls fetch records that have not changed since the last person asked.

Turn it round. Consolidate once where the data lives, read each long text once when it changes, and send on only what changed. Then the traffic across the interface follows what changes in the plant, not how many people ask.

Every question is a trip, and every trip is paid for

266 words

Ask an agent built in Joule Studio which pumps in one area had seal damage this quarter, and what the technicians wrote about it. It searches the notifications, opens the long texts that look relevant and checks the equipment each one names: a call to the backend for every step.

Where a call is paid for depends on its route. Joule's delivered skills, where your edition and contract include them, call the backend's OData services directly, under the user's own authorisations, not through Cloud Integration; in the private edition they go through the Cloud Connector. Custom skills and agents call whatever their destinations name, such as an integration flow in Cloud Integration (CPI) or a proxy in API Management.

The integration layer counts what it delivers. In the private edition, Cloud Integration is paid for by the kilobyte: a long text costs more to carry than a status, and every kilobyte a question fetches through an integration flow is billed. Where every interface sits behind API Management, or a custom skill was wired to an integration flow, each question pays for everything its calls carry.

A call around that layer is not a message, and not free either. An agent's steps may be metered in units of their own, depending on your contract; every call is load on the backend while planners work in it; every long text handed to a model costs tokens.

None of it depends on whether anything in the plant changed since somebody last asked. The model still answers every question; the trip to the backend is the part you can move.

Keep status live and move history to a store

147 words
The questionWhat it readsWhere to answer it
The status of one notification, nowOne record, as it stands this minuteLive
Creating or changing a notificationThe live system, under the user's authorisationsLive, always
Which machines had seal damage coded this quarterThe codes on many notifications, most unchanged since yesterdayThe store, from the codes
What technicians wrote about failures like this oneLong texts, read once and taggedThe store

The last two rows are where the calls pile up. A pattern question reads many records to say one thing, nearly all of them read the last time somebody asked. Say a notification was completed last year: every question about that machine fetches it again, pays for it again, and gets the same answer.

So the decision is not live against replicated. It is which questions are allowed to cost a trip.

Consolidate in the source, on top of the standard

268 words

Do the consolidation where the data lives: in the backend, as CDS views in the customer namespace (Z or Y), on top of released standard views.

On top of the standard, not in it. Your own view over a released view depends only on what the vendor has promised to keep stable. A view over the raw tables does not activate in ABAP Cloud; in classic ABAP it does, and the next upgrade shows you what moved.

Let the views carry what an answer needs without a second trip: notification type, status and dates, technical object and location, maintenance plant, planning plant, planner group, item and cause codes and long-text keywords. Keep each view at the grain of its data, a row per notification or per item, and let the flow assemble one entry per notification: a view that aggregates items cannot carry a change-data-capture delta.

Check what your release ships. The latest private-edition and on-premise releases carry released extraction views for a notification's header, items, causes, activities and tasks; earlier releases and the public edition do not, and your system's list of extraction-enabled views (I_DataExtractionEnabledView) shows what yours has. Where they exist, keep your own work for what the standard cannot deliver: the long text. Where they do not, your own views carry the rest as well, and their delta is yours to set up.

What follows assumes the private edition or on-premise. In the public edition, the classic text function modules, change data capture on a view of your own and a hand-built extraction service may not be open to you; check each on your release.

A view cannot read a long text, so store what it says

286 words

A notification's long text is not a column. It is stored compressed, as a cluster; classic ABAP reads it with READ_TEXT, or READ_TEXT_TABLE for many texts in one call, and a CDS view can neither unpack the cluster nor call a function module. A view over the text header table sees that a text exists and when it last changed, but only in classic ABAP, because that table is not released; check every read of it before an upgrade.

No view of your own sees what the text says. Your release may already keep a plain-text copy for enterprise search, readable through I_TextObjectPlainLongText. That view is neither released nor enabled for extraction, so check whether your system fills it for notifications; if it does, the job below reads the copy instead of calling READ_TEXT.

So the evaluation is a step of its own, and the view reads its result. A background job selects the texts changed since its last run by the text header's date and time, reads only those, derives the keywords and writes them to a customer table. Let each run select from a little before the previous one started: the header holds a date and a time, not a timestamp, and a text can be saved while the job runs. Read the texts on items, causes, tasks and activities too if your plant writes there; each has a text object of its own.

READ_TEXT is classified as a classic API and the text header table is not released, so the job is classic ABAP. It moves to ABAP Cloud only if your release's released notification API or business object returns the long text, together with a date that changes when the text does.

Keep the keywords apart from the catalogue codes

166 words

A notification already carries structured keywords. Its items name the object part and the damage, their causes the cause: each a code from the catalogue. A person chose the code, from a list your plant maintains. A program read the keyword out of the text afterwards.

Keep the two in separate fields and never report one as the other. A keyword makes old free text findable for an assistant. It does not make it countable the way a code is, because nobody chose it and nobody checked it.

Derive the keywords from rules, a list of terms mapped to your catalogue codes, or from a model, which reads free text better and costs tokens once per changed text. Let a model pick from the term list rather than invent terms, and write a keyword row only when its content changes: a model asked twice may answer differently, and every rewritten row is a change the delta carries. Keep the term list short, and owned by somebody.

Send what changed, including what was deleted

469 words

Give the keyword view a change-data-capture delta where your release offers one for your own views. The method logs every insert, update and deletion through triggers on the tables the view reads — here one small table of your own, not the notification tables planners write to — so the delta sees only changes to the text.

A notification that is completed, recoded or moved to other equipment without a word of its text changing, or that has no long text, needs a delta of its own: from the standard extraction views where your release has them, from your own views where it does not. Merge the two deltas in the store by notification number. Do not fetch each changed notification with a call of its own; through the integration layer, every call is a message.

Change data capture sees a deleted row only in the table it watches, and a notification is rarely deleted outright: it is marked for deletion and archived later. Carry its status into the store and filter on it. Archiving is a decision of its own: an archived notification has left the database, not the plant's history, so settle with whoever owns retention whether the store keeps it. Let the job remove the keyword rows of every text that no longer exists and of every notification deleted, or blocked under your retention rules, or the store goes on answering about them.

Cloud Integration reads the delta on a timer, whether anybody asks or not, through the extraction framework (ODP) exposed as an OData service, following a delta link from run to run. Keep the new link only once the store has accepted the batch, and write by notification number, replacing rather than appending, so a batch delivered twice does no harm.

Joule has no inbound interface for your records, so the delta goes into a store a Joule agent can search: a grounding collection, a vector store, a data product. Whichever you choose has to filter on fields as well as find similar text. A similarity search returns the few entries closest to the question, not every match. So a question that lists or counts is answered from the codes, through a filter on fields — date, plant, equipment, code — that the agent calls as a tool; a grounding collection that cannot filter needs a table beside it that can.

Send as little as the answer needs. Where Cloud Integration is paid by the kilobyte, as in the private edition, the saving is in what the flow carries: keywords instead of whole long texts, and a delta instead of a full load. The store costs too: each changed entry is indexed once, and every question still searches it. What stops growing with the questions is the trip across the interface to the backend.

What to settle before the first delta

228 words
  • Which route your assistant's calls take today, and what each route counts.
  • Where the delta lands. If a data product you already have covers notifications, check whether it carries the long text; if it does, it replaces most of your own code.
  • Who may see what. A call made under the user's own identity checks the user's authorisations; an integration flow that calls as a technical user does not. The store checks nothing unless every entry carries its notification type, maintenance plant, planning plant, planner group and, where you use one, the technical object's authorisation group, and the search filters on the values the asking user's roles grant before the agent sees a result. Read those values once per session, or replicate them with a delta of their own. Do not leave that filter to the agent.
  • What leaves the system. Where long-text control stamps each entry with a date, a time and a user, strip those lines, the user IDs and any names typed in before a model or a store sees the text.
  • How old an answer may be. An answer from the store is as old as the last run; say so wherever it is read.

The test is not whether the assistant can answer. It is whether the next question about last year's failures is answered without fetching a single notification from the backend.