abap-agent-runtime
An ABAP-native MCP endpoint inside the SAP system: an agent reads the screen of an opted-in abap2UI5abap2UI5One ABAP class implementing z2ui5_if_app is the whole app: the browser loads a generic UI5 shell once, and every interaction after that is an HTTP roundtrip back into ABAP.community org, abap app as structured data, fills its fields and fires its events as the logged-on SAP user.
An abap2UI5 app's whole conversation with the browser is one JSON request in and one JSON response out, and the abap2UI5 headless frontendabap2UI5 headless frontendPlays the frontend's side of the abap2UI5 request/response contract in ABAP, so an app class is driven and asserted on from a plain ABAP Unit test.community org, abap plays the browser side of that protocol inside ABAP. This addon puts an MCP server in front of it: app_list, app_start, app_describe and app_act hand an agent the agent snapshot v1 of a screen (fields, actions, tables, messages) and take values and event names back through the app's own main( ), so the same draft, the same validation and the same AUTHORITY-CHECKs run as in the browser and no second API is written per app. Nothing is reachable until an administrator switches the endpoint on and an app opts in by implementing z2ui5_if_agent_app or being allowed in the settings; events the app or the settings classify confirm or forbidden are never fired by an agent, and every call is written to the audit table. Beside the endpoint it runs three features on the same snapshot engine inside the system: a language model client, generative UI that builds an abap2UI5 view from a sentence against a closed vocabulary, and an in-app copilot grounded in the screen the user is on. It installs with abapGitabapGitA Git client written in ABAP that runs inside the system, so objects are cloned, pulled and pushed without leaving it; with no package manager in ABAP, a cloned repository is how code is distributed.community org, abap from a standard or a cloud branch, because the two HTTP entry classes cannot both activate on one system.
Facts
Where it sits
Who is behind it
In the atlas: maintains 21@abap2UI5-addonsmaintaineroblomov-devContributes to this
In the atlas: maintains 4, contributes to 44@oblomov-dev1 contributor
Before choosing this
Conditions
PracticalFunctional boundary
Stateful apps cannot be operated: a stateful session lives in one HTTP request and an MCP call is one request, so app_start refuses them. The repository carries no release yet and states the addon has not been run in production use, the 7.02 downport is lint-only with no 7.02 system having run it, and the ABAP Cloud HTTP service setup is written down but still to verify on your own system.
PolicySAP API Policy 4.2026a§ 1.1, 1.2, 2.2.2from Serve your application over MCPAn MCP server exposes an SAP API, or uses SAP APIs to supply tools, resources or data to an agent.
- § 1.1 Published APIs. Published APIs are made available for the documented purposes identified by SAP, including integration, extensions and data exchange.
- § 1.2 Non-Published APIs. Customer and third-party applications must not access non-published APIs except where documentation permits it or SAP otherwise authorizes it.
- § 2.2.2 AI call sequences and data extraction. Outside SAP-endorsed architectures, data services or expressly identified pathways, the policy prohibits specified agentic API use and systematic or large-scale extraction.
MCP does not replace the API's documented-use boundary. Check that every endpoint is published for the intended use and whether the policy's AI-call or extraction provisions apply to the design.
SAP API Policy 4.2026a →What it declares
Every artifact
- Type
- MCP server
- Origin
- By a community org
As an MCP server
- Transport
- HTTP
Connections
Calling a language model with tenant and credential handling solved
Exposing application data and operations to agents over MCP
Anthropic's hosted API for the Claude models, reached at https://api.anthropic.com/v1/messages with a key or through a destination. For the things here it is the model endpoint an ABAP system posts to, under the organisation's own agreement with Anthropic.
UI5 apps written as one ABAP class, rendered by a generic shell
Drives abap2UI5 app classes from ABAP Unit tests
Git client written in ABAP that runs inside the system
Download
Architecture
Download
z2ui5_cl_agent_llm_anthropic is configured with a key, a destination or a URLREADME
quoted from abap2UI5-addons/abap-agent-runtime under MIT, readabap-agent-runtime
Status: experimental - not yet in a release; details can still change. Everything described here is on
mainand in the generatedstandard/cloudbranches, and is what the first release (0.1.0, CHANGELOG.md) will carry. What works: the MCP endpoint with the four app tools, the agent snapshot v1 (byte-identical with the reference on its recorded sessions), opt-in, policy and audit, the language model client, generative UI and the in-app copilot. How it is verified: the ABAP Unit tests of every class run on abap2UI5's transpiled Node runtime (ABAP_UNIT), the sources lint as ABAP Standard 7.50 and ABAP Cloud (ABAP_STANDARD,ABAP_CLOUD), and the 7.02 downport is lint-only (ABAP_702- no 7.02 system has run it). It has been pulled into a 7.5x on-premise system (the activation fixes of 2026-10-08 came from that), not yet run in production use, and the ABAP Cloud HTTP service setup is written down but still to verify on your system (Installation). The API -z2ui5_if_agent_app, the tool arguments, thepolicysnapshot extension, the settings - may change before 1.0; CHANGELOG.md says when it does.
Every abap2UI5 app is agent-operable. An ABAP-native
MCP endpoint inside your SAP system: AI
agents - Claude, Copilot Studio, Joule, any MCP client - read the screen of an
abap2UI5 app as structured data, fill its fields and fire its events. As the
real SAP user, through the app's own main( ), with the app's own validation
and authority checks. No Node, no browser, no screen scraping.
Part of abap2UI5-addons - addons and apps for abap2UI5, installed with abapGit.
agent: app_start { "app": "z2ui5_cl_agent_demo" }
<- { "session": "8F3A...", "title": "Travel requests",
"fields": [ { "id": "f1", "path": "/NAME", "label": "Name", "kind": "text", "editable": true, ... }, ... ],
"actions": [ { "id": "a5", "event": "ADD", "label": "Add", ... },
{ "id": "a6", "event": "SUBMIT", "label": "Submit", "policy": "confirm", ... } ],
"tables": [ { "id": "t1", "path": "/T_REQUEST", "rowCount": 2, "rows": [ ... ], "selectionField": "SELKZ" } ], ... }
agent: app_act { "session": "8F3A...", "values": { "NAME": "Carol", "f2": "ROM" }, "event": "ADD" }
<- the next snapshot - the toast "Request 3 added", the table with three rows, a new session id
agent: app_act { "session": "...", "event": "SUBMIT" }
<- isError: "event SUBMIT needs a human - agents never fire it (the app classifies it confirm).
Hand over to the user: open /sap/bc/z2ui5#/app/Z2UI5_CL_AGENT_DEMO/<draft> in the browser ..."
Why
An abap2UI5 app is one ABAP class, and its whole conversation with the outside world is one JSON request in, one JSON response out. The browser is not the only thing that can hold up its end: the headless frontend simulator plays the browser side of that protocol inside ABAP. This addon puts an MCP server in front of it, so an agent operates an app semantically - by model path, label and event name - the way a user operates it in the browser, and never past it:
- No second API. No OData service, no RAP action, no RPC wrapper per app. Whatever the app lets a user do on a screen, it lets an agent do - and nothing more.
- The real user. The endpoint runs as the SAP user of the HTTP request. There is no technical user and no privilege escalation: an agent can never do what its user could not do in the browser.
- The app's own logic. Every act is a real roundtrip through
main( )- the same draft, the same validation, the sameAUTHORITY-CHECKs. - Opt-in, classified, audited. Only apps that opt in are reachable; events that need a human are never fired by an agent; every call is logged.
On top of the endpoint, the addon brings AI at runtime into the SAP system - three features built on the same snapshot engine, settings and audit log (AI at runtime):
- a language model client - the Claude Messages API out of the box, any provider of your own (SAP AI Core, Bedrock, a gateway) by class name;
- generative UI - an abap2UI5 view from a sentence, over data the app hands over, validated against a closed vocabulary before it is built;
- an in-app copilot - "ask this screen" for any opted-in app, grounded in the agent snapshot of the screen the user is on, with proposed steps the user confirms.
Installation
Requirements
- ABAP Cloud (BTP ABAP environment, S/4HANA Cloud Public Edition) or ABAP
Standard 7.50 or higher (on-premise, S/4HANA, NetWeaver); the 7.02
downport is linted in CI (
ABAP_702) - abap2UI5 and abap2UI5/headless-frontend, the simulator this addon runs on - installed first, see the steps
Steps - in this order, each with abapGit:
- abap2UI5 - the framework
- abap2UI5/headless-frontend -
the simulator this addon runs on (
resume( ),get_state( ),get_layers( ),set_json( )andclose_layer( )) - this repository - from the branch of your platform:
| Platform | Branch | Contains |
|---|---|---|
| ABAP Standard (on-premise, S/4HANA, NetWeaver 7.50+) | standard | packages 01-03, the ICF node /sap/bc/z2ui5_agent |
| ABAP Cloud (BTP ABAP environment, S/4HANA Cloud Public Edition) | cloud | packages 01, 02, 04 |
main holds all four packages; abapGit pulls a whole repository, and the two
HTTP entry classes cannot both activate on one system (if_http_extension
does not exist in ABAP Cloud, if_http_service_extension not on 7.50), so
.github/workflows/publish-branches.yaml generates standard and cloud from
every push to main. The branches move with main; a release tags them as
X.Y.Z-standard and X.Y.Z-cloud (RELEASING.md), and
abapGit pulls a tag like a branch - pin one to install a fixed version.
There is no release yet (see Status at the top); the
installed version is z2ui5_if_agent_app=>version, which abapGit shows for
the repository.
Start - the endpoint is disabled after installation - every tool call is refused until an administrator enables it.
- Add the first agent administrator - once, in the system, as a developer:
execute
z2ui5_cl_agent_settings=>admin_add( '<USER>' )and commit, e.g. from a small console class (if_oo_adt_classrun, ABAP Cloud and S/4HANA) or SE24 → Test (ABAP Standard). Further administrators are added in the app. - Open the settings app
?app_start=z2ui5_cl_agent_app_admin(through your usual abap2UI5 ICF node or launchpad tile) and switch Agents may operate apps on. Here you also allow or deny app classes, classify events, mark sensitive fields, set the handover page and clean up the audit log. A rule longer than the settings table holds (60 characters for the app and the event or field, 255 for a value) is refused, not cut short. - Make the HTTP endpoint reachable:
- ABAP Standard: abapGit creates the ICF node
/sap/bc/z2ui5_agentwith the handlerZ2UI5_CL_AGENT_HTTP. In transactionSICF, activate it and check its logon procedure (standard logon: Basic, SSO, certificates, as your system allows). If your abapGit version does not create the node, create it by hand: SICF →default_host/sap/bc→ new sub-elementz2ui5_agent, handler listZ2UI5_CL_AGENT_HTTP. - ABAP Cloud (steps to verify on your system): in ADT create an HTTP
Service (New → Other ABAP Repository Object → Connectivity → HTTP
Service), e.g.
Z2UI5_AGENT, and enterZ2UI5_CL_AGENT_HTTP_CLOUDas its handler class (ADT may generate its own handler class - then let itshandle_requestcallz2ui5_cl_agent_mcp=>run( req = request res = response )). Expose it through a communication scenario (inbound, with the HTTP service), a communication system and a communication arrangement; the inbound user of the arrangement - or, better, the business user via principal propagation / OAuth - is the user the agent runs as. The HTTP service and its scenario are system-specific objects and are not shipped in this repository.
- ABAP Standard: abapGit creates the ICF node
- Opt your apps in (Opting an app in) - nothing is reachable before that.
Then connect a client (Connecting a client) and ask it
to app_list; z2ui5_cl_agent_demo is a complete opted-in example app.
Usage
Opting an app in
CLASS zcl_sales_order_app DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
INTERFACES z2ui5_if_agent_app.
...
METHOD z2ui5_if_agent_app~describe.
result-description = `Create and change sales orders`.
result-t_event = VALUE #( ( event = `DELETE*` policy = z2ui5_if_agent_app=>cs_policy-forbidden )
( event = `POST` policy = z2ui5_if_agent_app=>cs_policy-confirm ) ).
result-t_sensitive = VALUE #( ( `/MS_PARTNER/IBAN` ) ).
ENDMETHOD.
An empty describe( ) is fine: every event is allowed then. An administrator
can also allow classes that do not implement the interface (an APP rule with
allow, patterns like ZCL_SALES_* work), deny classes that do (deny wins),
and classify events on top of what the app says - the stricter verdict wins.
z2ui5_cl_agent_demo is a complete example.
Connecting a client
The endpoint speaks MCP Streamable HTTP (revisions 2025-11-25, 2025-06-18,
2025-03-26 and 2024-11-05) with JSON responses; any client that supports
remote HTTP servers can connect. The URL is
https://<host>:<port>/sap/bc/z2ui5_agent (add ?sap-client=<client> when
your logon needs it); on ABAP Cloud, the URL of your HTTP service.
Claude Code
claude mcp add --transport http abap2ui5-agent https://host:44300/sap/bc/z2ui5_agent \
--header "Authorization: Basic $(printf '%s' 'USER:PASSWORD' | base64)"
Basic authentication is the simplest start; prefer a token: --header "Authorization: Bearer <token>" with an OAuth access token your SAP system
accepts (OAuth 2.0 client in SOAUTH2 / an ABAP Cloud communication
arrangement). SAP systems do not implement MCP's own authorization discovery,
so pass the credential as a header rather than relying on the client's OAuth
flow. Then ask Claude to app_list and go.
Microsoft Copilot Studio (to verify): add an MCP server tool to the agent (Streamable HTTP transport) with the endpoint URL, and authenticate it with basic or OAuth 2.0 credentials of the SAP user (or via the SAP principal-propagation setup of your landscape).
SAP Joule (to verify): connect the endpoint as an MCP server or as a BTP destination-backed tool of a Joule agent (Joule Studio); the destination carries the authentication (principal propagation recommended, so Joule acts as the logged-on business user).
The tools
| Tool | Input | Answer |
|---|---|---|
app_list | filter? | { count, apps: [{ app, description, source }], hint } - source interface or setting |
app_start | app, values?, max_rows? (0-200, default 20) | snapshot |
app_describe | session, max_rows? | snapshot from the stored session - no roundtrip |
app_act | session, values?, event?, args?, row?, max_rows? | the next snapshot |
The semantics are the specification's: values keys address a field by id,
model path or name, or a table cell as "<table path or id>/<row>/<COLUMN>"
(selecting a row is setting its selectionField); event is an event name or
an action id; row (0-based) fills the row arguments of a row action; args
(positional, null = let the client fill it) supplies what only a browser
computes - except the ${$parameters>/...} arguments of row events, which
are filled from the row (listItem, rowIndex, rowContext, a row action
item's row, and the call shapes views write on them:
.getBindingContext().getProperty('X'), .getPath(), .getCells()[n].getText(),
.getTitle(), ...; a [n] path segment is null, as in the browser's
JSONModel). Without event the values stay pending.
Value helps: the pick. A SelectDialog / TableSelectDialog is a table
of its layer, and its confirm is a row action: app_act({ event: <the confirm>, row: 2 }) picks row 2 as a click in the browser does - the row's
selectionField becomes true (single select: every other selected row's
false), the edits travel with the confirm as the model delta, and the
confirm's selectedItem / selectedItems / selectedContexts are the
selected rows. A multi-select dialog confirms what is ticked (tick rows
through values, row adds one); a single-select dialog with nothing
selected refuses an act without row. @CLOSE_POPUP /
@CLOSE_POPOVER close a dialog locally, as the browser does. Action ids
follow the document order, so values that show or hide a control can renumber
them: an act whose values make its action id name another event, or hide its
action, is refused - fill the values without an event first, then fire it from
the next snapshot. So is an act whose values disable its action
(enabled="{/OPEN}"): the browser cannot press a disabled control.
Every refusal is a tool result with isError: true and a sentence naming what
was wrong and what is allowed - and a refused act sends nothing and changes
nothing.
Architecture
MCP client (Claude Code, Copilot Studio, Joule, ...)
| POST /sap/bc/z2ui5_agent JSON-RPC 2.0, MCP "Streamable HTTP"
| logon: Basic / OAuth / certificate / principal propagation
v
z2ui5_cl_agent_http (ABAP Standard: if_http_extension, ICF node)
z2ui5_cl_agent_http_cloud (ABAP Cloud: if_http_service_extension)
|
z2ui5_cl_agent_mcp initialize, ping, tools/list, tools/call; origin check, audit commit
|
z2ui5_cl_agent_session app_list / app_start / app_describe / app_act
| | \__ z2ui5_cl_agent_settings opt-in, policy (allowed/confirm/forbidden), admins
| | \__ z2ui5_cl_agent_audit Z2UI5_T_AG_LOG
| | \__ Z2UI5_T_AG_SES per session: simulator state, client work,
| | pending values, last snapshot (owner = sy-uname)
| v
| z2ui5_cl_agent_snapshot layers + model -> agent snapshot v1 (+ the index an act needs)
| z2ui5_cl_agent_viewxml view XML, bindings, expressions, event wires
v
z2ui5_cl_frontend_simulator (abap2UI5/headless-frontend) start / resume / set_json / click / close_layer
v
abap2UI5 core: z2ui5_cl_ui5_handler -> your app's main( ) -> draft (Z2UI5_T_01)
Every MCP call is one HTTP request. A session survives between requests as the
abap2UI5 draft (the backend state, owned by the user, expiring with the
draft expiry of your abap2UI5 configuration) plus a row in Z2UI5_T_AG_SES
(what the browser would remember: the view of every layer, the pending
values). app_describe answers from that row without a roundtrip; app_act
resumes the simulator from it.
Packages
| Package | Objects |
|---|---|
src/01 engine | z2ui5_if_agent_app (opt-in), z2ui5_cl_agent_viewxml, z2ui5_cl_agent_snapshot, z2ui5_cl_agent_session, z2ui5_cl_agent_settings, z2ui5_cl_agent_audit, z2ui5_cl_agent_mcp; AI at runtime: z2ui5_if_agent_llm, z2ui5_cx_agent_llm, z2ui5_if_agent_llm_http, z2ui5_cl_agent_llm (factory, checks, audit), z2ui5_cl_agent_llm_anthropic, z2ui5_cl_agent_llm_double, z2ui5_cl_agent_genui, z2ui5_cl_agent_gen_vocab (generated), z2ui5_cl_agent_assist (copilot engine); tables Z2UI5_T_AG_SET (settings), Z2UI5_T_AG_SES (sessions), Z2UI5_T_AG_LOG (audit), Z2UI5_T_AG_MCP (MCP client sessions) |
src/02 apps | z2ui5_cl_agent_app_admin (settings), z2ui5_cl_agent_app_audit (audit log), z2ui5_cl_agent_demo (an opted-in example app, with the copilot), z2ui5_cl_agent_genui_demo (generative UI), z2ui5_cl_agent_copilot (the copilot popup) |
src/03 ABAP Standard entry | z2ui5_cl_agent_http and the ICF node /sap/bc/z2ui5_agent; z2ui5_cl_agent_llm_std (the language model's HTTP call, cl_http_client) |
src/04 ABAP Cloud entry | z2ui5_cl_agent_http_cloud; z2ui5_cl_agent_llm_cloud (the language model's HTTP call, cl_web_http_client_manager) |
What an agent sees: agent snapshot v1
The snapshot is the shared contract of three implementations - the
MCP server (Node, for development),
the VS Code extension, and this addon - specified in
docs/agent-snapshot.md
of the MCP server: fields (id, model path, label, kind, value, required,
editable, choice values), actions (event, arguments with descriptors such as
$row:NAME, label, trigger, enabled, row scope), tables (columns, the first
rows, selection - the selection dialogs SelectDialog / TableSelectDialog
included), messages (toast, message box, MessageStrip, value states, the
app's message table, the items of a MessagePopover / MessageView with
their subtitle and description), texts, unsupported, and pending.
z2ui5_cl_agent_snapshot is an ABAP port of the reference implementation
(lib/viewxml.mjs, lib/snapshot.mjs). Measured against it on the 15
recorded sessions of the MCP server (every step, at 20 and at 2 rows) plus
12 synthetic views (selection dialogs, row event arguments, message lists
among them): 110 of 110 snapshots byte-identical - measured at the
reference's commit 6bd3cc3, whose history has since been squashed; the
reference's changes to the two modules up to its commit dcadb48 (the
parity base in AGENTS.md) are ported, the last one being how a
FormattedText loses its tags. The snapshot validates against the
normative schema, abap2UI5/protocol
schema/snapshot.schema.json
(the unit tests' expected snapshots were checked against it). One deliberate
extension: an action the app or the settings classify confirm or
forbidden carries "policy" - without such a classification the output is
the reference's, key for key.
Security model
- Disabled by default; an administrator switches the endpoint on.
- Opt-in per app: only classes implementing
z2ui5_if_agent_app, or allowed by an administrator, can be listed or started. The addon's own apps (z2ui5_cl_agent_app_*) are never agent-operable, whatever the settings say - every event of theirs isforbidden, also when an operable app navigates there. - The real SAP user, always. Authentication is the logon of the HTTP request (Basic, OAuth, certificates, principal propagation) - nothing custom, no technical user, no user switch. The app runs as that user, with its authority checks.
- Events are classified
allowed,confirmorforbiddenby the app (describe( )) and by the settings; the stricter wins. Agents never fire aconfirmorforbiddenevent. Aconfirmrefusal hands the screen over to a human (below). - Sessions belong to their user: every read filters by
sy-uname, the draft service binds drafts to their creator, and a session expires with its draft. Only the current draft id of a session is accepted - as it was answered: an id with anything appended is unknown, never its prefix. - Audit log (
Z2UI5_T_AG_LOG, appz2ui5_cl_agent_app_audit): timestamp, user, session, app, operation, event, arguments (truncated; values masked for password inputs - and any field on the model path of one - and for fields the app or the settings mark sensitive), outcome, error text, MCP client name and version. Users see their own entries, administrators everybody's. Settings changes are logged too. - AI at runtime is off by default (no key, no destination, copilot off); its model calls are audited without prompt contents, its views are validated against a closed vocabulary, its proposals against the same policy as every agent - see AI at runtime.
- Browser-side abuse is refused: a request with an
Origin(orReferer) of another host gets 403, whatever its method - the check abap2UI5 applies to its own POSTs - and onlyContent-Type: application/jsonis accepted, so a web page cannot drive the endpoint with the user's SSO cookies.
The handover flow
When an agent tries an event classified confirm, app_act refuses and answers
with the abap2UI5 URL of the session's draft, e.g.
/sap/bc/z2ui5#/app/ZCL_SALES_ORDER_APP/8F3A... (the base is the handover
page of the settings, default /sap/bc/z2ui5). The agent passes it to its
user, who opens it in the browser: abap2UI5 restores the very state the agent
prepared - same user, same draft - and the human checks it and presses the
button. Values the agent sent with earlier events are part of the draft;
values still pending are listed in the refusal, so the agent can send them
first with an allowed event or tell the user what to enter. A dialog that was
open is not part of the draft; the app shows its main view.
Limits
What the snapshot cannot see is listed in the specification
(What the snapshot cannot see):
formatters and composite bindings, client-only state (an IconTabBar's open
tab, a selection without a selected binding), named models, custom controls,
frontend actions (.eF wires, OPEN_NEW_TAB, ... - listed, never
performed), nested tables, file uploads. On top of that, in this addon:
- Value helps work, message popovers are read. An F4 help built as a
SelectDialog/TableSelectDialog(abap2UI5'sz2ui5_cl_pop_to_select, the popups addon'sz2ui5_cl_popup_to_select) is operated with the pick above. The items of aMessagePopoverare messages (source: "popover") even while the popover itself only opens in the browser (a frontend action this addon does not perform); aMessageView's aresource: "messageview". At most 50 per list. A control-valued event parameter outside the row events (a MessagePopover's${$parameters>/item}) is marshalled by the browser with all its properties - pass what the app reads inargs. - Stateful apps (
client->set_session_stateful( )) cannot be operated: a stateful session lives in one HTTP request, an MCP call is one request.app_startrefuses them; an app that switches mid-session ends the session. What such an app - or an app whosemain( )failed - left open in the LUW is rolled back, never committed with the call's audit entry. - Event arguments travel as text. Model values go out typed, as the
browser sends them: every pending value is handed to the simulator's
set_json( )at its model path - a boolean astrue/false, amultichoiceas an array of keys, a number as a number - and the simulator builds the frontend's delta from them (a table cell as a row delta, everything else, a structure that holds a table included, as the whole top-level attribute). The positional event arguments (args, the row arguments of a row action) are still text, because the simulator'sclick( )takes them as a string table: a boolean asX/ space, an object or array as its JSON. app_listreads the class directory (SEOMETAREL on ABAP Standard, XCO on ABAP Cloud) through the core's utility. Where it cannot be read it lists only what the settings name;app_startworks either way.- One snapshot shape for every client. Labels, texts and messages are as the app wrote them - in its logon language.
AI at runtime
Three features, all inside the SAP system, all on ABAP Standard, ABAP Cloud and the 7.02 downport, all off until an agent administrator configures a language model. Nothing here gives a model more than the user has: the model never runs ABAP or SQL, never picks data, and never acts without the user's click.
app (genui) / copilot popup
|
z2ui5_cl_agent_genui z2ui5_cl_agent_assist -> z2ui5_cl_agent_session (mode copilot)
\________________ ________/ snapshot, app_check, app_act, policy
v v
z2ui5_cl_agent_llm factory + wrapper: settings, stop reasons, JSON, audit (Z2UI5_T_AG_LOG)
|
z2ui5_if_agent_llm z2ui5_cl_agent_llm_anthropic | your class (AI Core, Bedrock, ...) | the double
|
z2ui5_if_agent_llm_http z2ui5_cl_agent_llm_std (03, cl_http_client) | z2ui5_cl_agent_llm_cloud (04)
Setting up the language model
In z2ui5_cl_agent_app_admin, section Language model (agent
administrators only - every change is audited):
| Setting | |
|---|---|
| API key | sent as x-api-key. Write-only: the app shows set / not set, never the key; Remove key deletes it. A typed key is cleared after every event, so it never stays in the app's draft - only Save stores it. Stored in Z2UI5_T_AG_SET (kind LLM) - protect the table like any credential store, or leave the key empty and let the destination authenticate |
| Destination | ABAP Standard: an SM59 destination of type G (host api.anthropic.com, port 443, SSL active, client identity ANONYM or DFAULT, proxy if your landscape needs one); the URL field is then the path (default /v1/messages). ABAP Cloud: a communication arrangement as SCENARIO/SERVICE_ID (or SCENARIO/SERVICE_ID/COMM_SYSTEM) - a customer communication scenario with an outbound HTTP service whose system points at https://api.anthropic.com (to verify on your system) |
| URL | without a destination the full URL, default https://api.anthropic.com/v1/messages (ABAP Standard: the server certificate chain must be in the ANONYM PSE, STRUST; ABAP Cloud: cl_http_destination_provider=>create_by_url) |
| Model / effort | default claude-opus-5-5 / low (thinking is always on for this model and is never configured; output_config.effort is the only control - low keeps generated views and answers interactive) |
| Max tokens / timeout | default 16000 / 300 s (never below 120 s) |
| Refusal fallback / beta header | default on / server-side-fallback-2026-07-01: the request carries "fallbacks":"default" and the beta header, so a refusal is retried server-side on a fallback model |
| Provider class | default z2ui5_cl_agent_llm_anthropic; a class of your own implementing z2ui5_if_agent_llm (public constructor without mandatory parameters) routes every call through SAP AI Core / Generative AI Hub, Bedrock or a gateway - the checks, the JSON parsing and the audit stay the addon's |
| Audit keeps prompts and answers | default off (below) |
| Generative UI: sample rows / repair round | default off / on |
| In-app copilot / may propose actions | default off / off |
Test call sends one short message and shows the model, the answer and the
tokens. The request is the Messages API, non-streaming:
POST /v1/messages with content-type: application/json, x-api-key,
anthropic-version: 2023-06-01 (+ anthropic-beta for the fallback), body
{"model","max_tokens","system":[{"type":"text","text","cache_control":{"type":"ephemeral"}}],"messages","output_config":{"effort","format":{"type":"json_schema","schema"}},"fallbacks":"default"}
- the system prompt as a cached block (the generative UI's vocabulary is the
same on every call);
effortonly for a model that takes it (not Claude Haiku 4.5, Sonnet 4.5 or older),fallbacksand its header only for the Fable, Mythos, Opus 5 and Sonnet 5.5 lines. The answer is the firsttextblock;stop_reasonis checked first - onlyend_turnandstop_sequenceare an answer: arefusal, amax_tokens, amodel_context_window_exceededor any other reason raisesz2ui5_cx_agent_llmand is never parsed. HTTP 408, 429, 5xx and 529 raise it withretryable = abap_true, other errors without; the addon does not retry on its own.
Your own provider:
CLASS zcl_llm_ai_core DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_agent_llm.
ENDCLASS.
CLASS zcl_llm_ai_core IMPLEMENTATION.
METHOD z2ui5_if_agent_llm~chat.
" is_request-system, -t_message, -schema (JSON schema text, or empty), -effort, -max_tokens
" -> call your service; answer text (the JSON for a schema), stop_reason, usage
" -> RAISE EXCEPTION TYPE z2ui5_cx_agent_llm EXPORTING kind = `http` http_status = ... retryable = ...
ENDMETHOD.
ENDCLASS.
and enter ZCL_LLM_AI_CORE as the provider class. Unit tests use
z2ui5_cl_agent_llm_double (queued canned answers, recorded requests) via
z2ui5_cl_agent_llm=>set_double( ) - no test calls a model.
Privacy and audit
- Every call is audited in
Z2UI5_T_AG_LOG(written in the caller's LUW - the endpoint,generate( )and the copilot commit it; operationllm, visible inz2ui5_cl_agent_app_audit): user, app, purpose (genui,copilot,test), provider, model, effort, stop reason, input and output tokens, duration in ms, outcome, the error text. No prompt and no answer - unless an administrator switches Audit keeps prompts and answers on (then both are kept - the answer first, it and every prompt cut to 400 characters, so the entry's 2000 never lose the answer; cache tokens are kept too). - Generative UI sends the names, types and labels of the fields the app hands over - no data; a few sample rows (3) only with sample rows on.
- The copilot sends the agent snapshot of the screen - the values the
user sees, so a question about them can be answered - with every password
input (and every other field on its model path) and every sensitive field
(the app's
t_sensitive, the settings'SENSITIVErules) masked as***, in fields, in table columns (a cell bound to several fields or an expression by every field it reads) and in the texts that show one, and without the actions agents may never fire. It never proposes to fill a masked field. - The data goes to the provider you configure; with the shipped one, to the Claude API under your organisation's agreement with Anthropic.
Generative UI
The app decides what data; the model decides only how to show it.
DATA(genui) = z2ui5_cl_agent_genui=>create( client = client app = `ZCL_MY_APP`
)->add_table( name = `flights` val = t_flight description = `flights of the week`
t_label = VALUE #( ( field = `CARRID` label = `Airline` ) )
)->add_structure( name = `header` val = ms_header
)->add_event( event = `ROW_SELECT` description = `the user picks a flight`
t_arg = VALUE #( ( `CARRID` ) ( `CONNID` ) ) ).
DATA(result) = genui->generate( `the open flights as a table grouped by carrier` ).
IF result-ok = abap_true.
client->popup_display( result-xml_popup ). " or view_display( result-xml )
ELSE.
" result-t_issue: why it was rejected, result-t_note: the report
ENDIF.
val is the app's attribute itself - the class binds it with
client->_bind( ), so the generated view binds to the app's model like a
hand-written one and its events arrive in the app's main( ). abap2UI5
rolls back what an app's main( ) leaves uncommitted, so generate( )
commits the LUW after its model calls (their audit entries); pass commit = abap_false when your LUW holds work of its own and commit it yourself. The model
answers a UI tree as structured output (a JSON schema, flat list of nodes -
control, parent, aggregation, properties as literals or field bindings, an
optional list binding, events), never XML, ABAP or SQL. The class validates
the tree and builds the XML itself with z2ui5_cl_ui5_view_builder:
| Checked | Rejected with a reason |
|---|---|
| controls | anything outside the portable view profile v1 of the abap2UI5 protocol (65 controls, z2ui5_cl_agent_gen_vocab); also sap.ui.core.HTML, Shell, Dialog, Popover, CustomData and layout data |
| tree | no or two roots, a missing parent, a cycle, a duplicate id, more than 200 nodes |
| aggregations | an aggregation the parent does not have, a child of the wrong type, two children in a single aggregation, a sap.m.ToolbarSpacer in a sap.m.Bar or a page's headerContent (no flex container before UI5 1.76: it hides what follows it) |
| properties | a property the control does not have at the UI5 1.71 floor (members introduced later are not in the vocabulary); visible on an element that has none (sap.ui.core.Item); a literal of the wrong type - enum values as listed, true/false, integers, numbers with a digit before the point, CSS sizes, icons only as sap-icon://... with a name the SAP icon font has at UI5 1.71 and no later release removed, CSS classes only the sapUi*Margin/Padding helpers; a binding on a property that takes none (URIs, ids); icon, src and href only as icon URIs, whatever the profile types them; a line break or a brace in any literal but a text |
| bindings | a field that is not in the data handed over; relative bindings only inside the row template of a list bound to a table, absolute ones only to a structure; formats integer and decimal (typed bindings) and nothing else - no expressions, no formatters; a field the property cannot take (UI5 throws on it): a boolean property takes a boolean field, an integer or number property a number field, a CSS size or enum property a string field, a format only a number field |
| lists | a list bound to a structure or an unknown dataset, sorting or grouping by an unknown field, not exactly one row template, a list inside a template |
| events | an event the control does not have, an app event not in the app's list, an argument the app did not allow for it, arguments out of the app's order (an app reads them by position: leave out only from the end) |
| texts | never rejected - always rendered as literals (t of the builder: { and \ escaped, XML escaped), so <script>, "/><core:HTML ...> or {/OTHER/PATH} in a text show as text |
Ids, custom data, frontend actions (.eF), custom controls and expression
bindings do not exist in the tree format at all. With repair round on (the
default) a rejected tree goes back to the model once with the reasons; the
second answer is validated the same way. render( json ) validates and builds
a tree an app stored. The vocabulary is generated: .github/genui/portable-v1.json
is a pinned copy of profiles/portable-v1.json of
abap2UI5/protocol, typed with the UI5
metadata of the abap2UI5 linter, the icon names from its icon data; npm run genui:check fails when
z2ui5_cl_agent_gen_vocab is not what the pins generate, npm run genui:drift when the pin is no longer upstream's (the genui-vocab
workflow runs both, weekly as well).
z2ui5_cl_agent_genui_demo is the example: flights in an internal table, a
sentence, Generate, the view in a popup, the validation report below; its
view may fire ROW_SELECT (carrier, connection, date) and REFRESH.
Limits: no filtering in the view (a filter control can fire an app event that takes its value); no nested lists, no NEST slots, no formatters beyond the two number formats; enum values and icon names are checked against the 1.71 floor (icon names against the font in the linter's icon data); the model can still build a poor layout - the validation guarantees safety, not taste.
In-app copilot
"Ask this screen": a popup in any opted-in abap2UI5 app that answers from what the screen shows and can do steps the user confirms. Two lines in the app:
METHOD z2ui5_if_app~main.
IF z2ui5_cl_agent_copilot=>attach( client ) = abap_true.
RETURN.
ENDIF.
...
" in the view, e.g. the page's headerContent:
)->tag( `Button`
)->a( n = `icon` v = `sap-icon://discussion`
)->a( n = `press` v = client->_event( z2ui5_cl_agent_copilot=>c_event ) )
The app must be enabled for agents (it implements z2ui5_if_agent_app or an
administrator allows it) and the copilot switched on. z2ui5_cl_agent_demo
carries both lines.
How it works. The press is an ordinary event of the app; attach( )
answers it with nav_app_call( ) of z2ui5_cl_agent_copilot, a popup app on
top of the screen. That roundtrip saved the caller's draft - with the values
the user had typed, which travel with every event - and the copilot reaches
it as get( )-s_draft-id_prev_app. z2ui5_cl_agent_assist copies that draft
and continues the copy headlessly (z2ui5_cl_agent_session=>app_attach: the
headless frontend's restore roundtrip, the app's main( ) runs
check_on_navigated( )), so the copilot has the agent snapshot v1 of the
very screen - the same snapshot an MCP agent gets, the same session. The
user's own draft is never touched.
Each question sends the masked snapshot, the app's describe( ) description
and the conversation so far; the model answers as structured output
{answer, found, proposal} and is told to say when the screen does not hold
the answer. A proposal (fields to fill, an action to press - only with
may propose actions on) is validated before it is shown:
- an action the screen does not have, a forbidden action (which the model never even sees), or a password / sensitive field: not offered, with the reason;
- everything else exactly as the MCP endpoint's
app_actvalidates it -app_check( )runs the same code without sending (unknown field, a field that is not editable, a choice outside its values, a wrong type). The values of a proposal are text: amultichoicenames its keys separated by commas, and the copilot hands them over as the array of keysapp_acttakes; - nothing runs until the user clicks Do it / Fill in. An allowed
action then runs through the app's own
main( )in the session (app_act); for an action classified confirm the copilot only fills the fields and tells the user to press the button on the screen - agents never fireconfirmorforbiddenevents, the copilot included.
Close returns to the app (nav_app_leave): unchanged when nothing ran;
otherwise in the state the confirmed steps left it (the session's draft,
client->get_app( )), with values that were only filled written into the
app's public attributes by their model path - a date (D) taken as
YYYY-MM-DD or YYYYMMDD, a time (T) as HH:MM, HH:MM:SS or HHMMSS;
a value that is no day of the calendar or time of the clock is not written,
the user enters it - the copilot names such a value when it fills it. The
copilot app itself is never agent-operable, and the copilot event is
classified forbidden on every screen - an agent cannot open it.
Why this integration. abap2UI5 routes every event to the app's own
main( ) (only nav_app_leave is framework-handled), so an app has to hand
the press over - one line. The view XML of the current screen exists only in
the browser and in the app's view_display( ) call; the released API offers
no getter for it, and reading it from the frontend would let the browser
dictate what the validation trusts. Re-rendering a copy of the draft through
the headless frontend gives the server's own view and model, reuses the
snapshot, the policy and the act validation unchanged, and needs only
released API in the apps (nav_app_call, get( ), get_app,
nav_app_leave). Rejected alternatives: a frontend-supplied snapshot (not
trustworthy), a recording z2ui5_if_client implementation (breaks with every
new client method), a monitor exit (one per system, no view).
Limits: a popup the app had open when the copilot was pressed is not
part of its draft, so the copilot sees the main view (as the handover does);
the restore roundtrip runs the app's check_on_navigated( ) branch - an app
that does more than display there does it once more on the copy; stateful
apps cannot be continued; each question is one model call with the whole
snapshot (20 rows per table); copies of drafts expire with the abap2UI5 draft
expiry.
Development
npm ci
npm run lint # abaplint, ABAP Standard 7.50, the strict rule set
npm run lint:cloud # ABAP Cloud
npm run check:abap2ui5 # the abap2UI5 linter on the apps (package 02)
npm run genui:check # z2ui5_cl_agent_gen_vocab is what the pinned profile generates
npm run check:version # package.json, z2ui5_if_agent_app=>version and CHANGELOG.md agree
npm run unit # the ABAP Unit tests on abap2UI5's transpiled runtime
npm run check runs everything but unit. Every user-visible change gets
an entry under ## Unreleased in CHANGELOG.md;
RELEASING.md is how a release is cut from it (one tag,
.github/workflows/release.yaml).
The ABAP_702 workflow downports src/ - together with headless-frontend,
cloned into src/zz_headless_frontend - and lints the result as 7.02 (CI only,
never commit downported source).
Unit tests. npm run unit runs the Z2UI5_CL_AGENT* tests - all of them,
the DANGEROUS ones included - on the transpiled runtime abap2UI5 uses for its
own suite (SQLite behind the database statements); UNIT_FILTER=ltcl_session npm run unit runs only those whose OBJECT: class->method contains the
text. .github/scripts/unit.mjs is the whole recipe, and the ABAP_UNIT
workflow runs the same script on every push and pull request: checkouts of
abap2UI5 main and headless-frontend in .unit/ (git-ignored; cloned on the
first run, refreshed on every later one), npm ci in abap2UI5,
headless-frontend's src/ and this repository's src/01 and src/02 copied
in as extra packages, npm run downport && npm run auto_transpile, then the
generated tests - each one printed, exit code 1 on any failure or when none
ran. The first run takes a few minutes.
Contributing
Issues and pull requests are welcome. See AGENTS.md for the conventions of this repository.
License
MIT - see LICENSE.
Others providing
- abap-ai/mcpabap-ai/mcpAn MCP server SDK written in ABAP to run natively on the ABAP stack, so an ABAP system can expose its own prompts, resources and tools to an agent from inside itself.independent, abapMCP server SDK written in ABAPfrom ABAP
- abap-ai/mcp2abap-ai/mcp2A stateless rewrite of the ABAP MCP server SDK: one ABAP server contract answering both the 2026-07-28 protocol draft and the legacy 2025 versions, with no sessions and no SSE.independent, abapStateless ABAP MCP server SDK for the 2026-07-28 protocol draftfrom ABAP
- API ManagementAPI ManagementAPI proxies in front of backend services, with security and traffic management policies attached to them, and Developer Hub where consumers subscribe.sap official, btpAPI proxies with security and traffic policies and Developer Hubfrom BTP/BAIP
- com.sap.cds:cds-adapter-mcpcom.sap.cds:cds-adapter-mcpThe MCP protocol adapter for CAP Java, serving an @mcp-annotated Application Service as an MCP server with three generated tools, describe, query and call, and data changes only through unbound actions.sap official, capMCP adapter turning a CAP Java service into an MCP serverfrom CAP
- @cap-js/mcp@cap-js/mcpA CAP plugin that serves an @mcp-annotated service over MCP with three generated tools, describe, query and call_action, and writes its endpoint into the local agent's configuration in development.sap official, capExposes CAP services as MCP servers for AI agentsfrom CAP
- @gavdi/cap-mcp@gavdi/cap-mcpGenerates an MCP server from the CDS model — annotated entities become resources and annotated actions become tools, so an agent reaches the service without a second server being written.independent, capGenerates an MCP server from annotated CDS entities and actionsfrom CAP
- btp-cf-mcpbtp-cf-mcpAn MCP server over an SAP BTP account and its Cloud Foundry runtime that acts as the person who logged in, so their own global-account and space roles decide what an agent can see.independent, btpMCP server for SAP BTP and Cloud Foundry acting as the logged-in userfrom BTP/BAIP
- MarkWuRY168/SAP_MCPMarkWuRY168/SAP_MCPPublishes SAP system functions as MCP tools from configuration tables held inside the SAP system, so adding a tool is a configuration change rather than a code change.independent, abapMCP server publishing SAP functions as tools from config tablesfrom ABAP
- @neoimpulse/cap-js-mcp@neoimpulse/cap-js-mcpAn MCP server inside a CAP application, with default tools that read the running model and query entities, plus configurable application tools, prompts and resources.independent, capMCP server inside a CAP application with model and query toolsfrom CAP
- @odatano/core-mcp@odatano/core-mcpMCP server exposing ODATANO — the Cardano-to-OData bridge built on CAP — to an agent, so the chain is reachable as tools rather than as a REST client.independent, capMCP server exposing the ODATANO Cardano-to-OData bridge as toolsfrom CAP
- @odatano/nightgate-mcp@odatano/nightgate-mcpMCP server exposing NIGHTGATE, the Midnight blockchain attestation layer, as agent tools — the companion to the CAP indexer plugin of the same name.independent, capMCP server exposing the NIGHTGATE Midnight attestation layerfrom CAP
- @shahid.la/cds-db-nlquery-mcp@shahid.la/cds-db-nlquery-mcpMCP server that answers plain-English questions against the entities in db/schema.cds — it discovers the schema, generates CQN-backed SQL with real joins, and returns rows.independent, capMCP server answering plain-English questions against a CDS schemafrom CAP
- Skybuffer AI MCP serverSkybuffer AI MCP serverAn ABAP add-on that serves SAP business data, transactions and development context as MCP tools from an ICF node inside SAP ECC and S/4HANA, each call running as the signed-in user under PFCG authorization checks.independent, abapABAP add-on serving business data and transactions as MCP toolsfrom ABAP
- cap-mcp-plugincap-mcp-pluginGenerates an MCP server from a CDS model: annotated entities become MCP resources, functions and actions become tools, and services can expose reusable prompt templates. A fork of @gavdi/cap-mcp that adds an OAuth proxy, IAS client registration and draft-lifecycle tools.independent, capMCP server generated from a CDS model, forked from @gavdi/cap-mcpfrom CAP
- llm_clientllm_clientAn ABAP client that gives chat-completion LLM APIs one interface for chat messages, structured output and tool calls across ten providers, from OpenAI and Anthropic to OLLAMA and AWS Bedrock.independent, abapABAP client with one interface to chat-completion LLM APIsfrom ABAP
- abap_btocs_ollamaabap_btocs_ollamaAn ABAP plugin, built on the B-Tocs ABAP SDK, that calls models served by Ollama through an SM59 RFC destination, implementing four of its API endpoints: generate, tags, show and embeddings.independent, abapB-Tocs ABAP SDK plugin connecting to Ollama modelsfrom ABAP
- SAP AI CoreSAP AI CoreSAP's AI service on BTP: the runtime for AI assets, and through the Generative AI Hub inside it the access to foundation models, the orchestration service with its templating, masking, filtering and grounding modules, the Prompt Registry and Document Grounding.sap official, btpAI runtime on BTP with the Generative AI Hubfrom BTP/BAIP
- cap-java/cds-aicap-java/cds-aiBridges CAP Java to SAP AI Core and adds AI-powered field recommendations to Fiori draft UIs, as two alpha Maven modules with mock fallbacks for local development.sap official, capBridge from CAP Java to SAP AI Core, with Fiori field recommendationsfrom CAP
- @cap-js/ai@cap-js/aiOut-of-the-box value-help recommendations powered by SAP RPT-1, SAP AI Core as a standard CAP service, and an experimental local embedding model behind SQLite's vector functions.sap official, capValue-help recommendations and SAP AI Core as a CAP servicefrom CAP
- cap-llm-plugincap-llm-pluginGenerative AI in a CAP application with the sensitive fields anonymised through SAP HANA before the prompt leaves, so the model never sees the confidential half.independent, capGenerative AI in CAP with fields anonymised through SAP HANAfrom CAP
- @geertjanklaps/cds-toon-ai-protocol-adapter@geertjanklaps/cds-toon-ai-protocol-adapterA protocol adapter that serves CAP data as TOON — Token-Oriented Object Notation — instead of JSON, so a payload bound for a language model costs fewer tokens to send.independent, capProtocol adapter serving CAP data as TOON instead of JSONfrom CAP
- abap-sdk-nwas-xabap-sdk-nwas-xAn ABAP client library for IBM's watsonx.ai and watsonx.ai Runtime APIs, installed into an SAP NetWeaver AS ABAP system through abapGit, generating and refreshing the IAM token from an API key.independent, abapABAP client library for IBM watsonx.ai APIsfrom ABAP
- @jerome-benoit/sap-ai-provider@jerome-benoit/sap-ai-providerA provider for the Vercel AI SDK that speaks to SAP AI Core through its orchestration or foundation models API, so an application written against that SDK runs on SAP's models without being rewritten.independent, capVercel AI SDK provider for SAP AI Corefrom CAP
- ui5-cap-ai-featuresui5-cap-ai-featuresBoth halves of an AI text feature in one package: a CDS plugin serving an AIService over SAP AI Core's Orchestration Service, and the be.wl.ai UI5 control library that calls exactly that service.independent, capCDS plugin and UI5 controls for AI text features via SAP AI Corefrom CAP
- Microsoft AI SDK for SAPMicrosoft AI SDK for SAPMicrosoft's ABAP library for calling Azure OpenAI and OpenAI from an SAP application server, wrapping completions, embeddings, fine-tuning and the other operations in ABAP data types, installed with abapGit.partner, abapABAP library for calling Azure OpenAI and OpenAIfrom ABAP
- zllmzllmAn ABAP framework for chaining and orchestrating calls to large language models in pure ABAP, with templated prompts, routing by complexity, response caching and token estimation.independent, abapABAP framework for chaining and orchestrating LLM callsfrom ABAP
- ABAP AI SDKABAP AI SDKSAP's reuse library for calling a large language model from ABAP code, powered by Intelligent Scenario Lifecycle Management and reaching the models in the Generative AI Hub; delivered with SAP BTP ABAP environment, SAP S/4HANA Cloud Public and Private Edition and SAP S/4HANA.sap official, abapSAP reuse library for calling large language models from ABAPfrom ABAP
- @sap-ai-sdk/ai-api@sap-ai-sdk/ai-apiThe AI Core API surface of SAP's AI SDK, covering deployments, configurations and the rest of the control plane, as opposed to calling a model.sap official, capAI Core control plane API surface of SAP's AI SDKfrom CAP
- @sap-ai-sdk/core@sap-ai-sdk/coreThe shared internals that the packages of SAP's AI SDK build on, which its own readme says are not meant to be depended on directly.sap official, capShared internals of SAP's AI SDKfrom CAP
- @sap-ai-sdk/foundation-models@sap-ai-sdk/foundation-modelsThe package of SAP's AI SDK that calls foundation models through SAP AI Core and the Generative AI Hub, and the one an application actually reaches for.sap official, capClient for foundation models via SAP AI Core and Generative AI Hubfrom CAP
- @sap-ai-sdk/orchestration@sap-ai-sdk/orchestrationThe Orchestration Service client of SAP's AI SDK, which applies templating, grounding, filtering and masking around a model call rather than in the application.sap official, capOrchestration Service client for templating, grounding and maskingfrom CAP
- @sap-ai-sdk/prompt-registry@sap-ai-sdk/prompt-registryA package for keeping prompts in SAP's prompt registry rather than in the codebase, so changing a prompt is not a deployment.sap official, capClient for prompts kept in SAP's prompt registryfrom CAP
- @saptarishi/cds-plugin-llm@saptarishi/cds-plugin-llmA CAP service kind that puts eleven model providers behind one chat, stream, embed and batch interface, so which backend a service calls is a profile in package.json rather than a change to the handler.independent, capCAP service kind putting eleven model providers behind one APIfrom CAP
- @shahid.la/cds-db-nlquery-mcp@shahid.la/cds-db-nlquery-mcpMCP server that answers plain-English questions against the entities in db/schema.cds — it discovers the schema, generates CQN-backed SQL with real joins, and returns rows.independent, capMCP server answering plain-English questions against a CDS schemafrom CAP
- @ui5/webcomponents@ui5/webcomponentsSAP's UI elements as standard custom elements, ui5-button among them, implementing SAP Fiori design and usable from plain HTML, React, Angular or Vue.sap official, ui5SAP's UI elements as standard custom elementsfrom UI5
- abap-sdk-nwasabap-sdk-nwasAn ABAP client library for IBM Watson's Discovery, Language Translator, Natural Language Understanding, Speech to Text, Text to Speech and Assistant services, installed through abapGit.independent, abapAn ABAP client library for IBM Watson's Discovery, Language Translator, Natural Language Understanding, Speech to Text, Text to Speech and Assistant services, installed through abapGit.from ABAP
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
Flavors
“| ABAP Standard (on-premise, S/4HANA, NetWeaver 7.50+) | `standard` | packages 01-03, the ICF node `/sap/bc/z2ui5_agent` |” — abap-agent-runtime — README, Installation
“| ABAP Cloud (BTP ABAP environment, S/4HANA Cloud Public Edition) | `cloud` | packages 01, 02, 04 |” — abap-agent-runtime — README, Installation
Contributors
History in the atlas
- First seen.
For your agent
- Ref
artifact:abap2ui5-addons-abap-agent-runtime- JSON
- /artifacts/abap2ui5-addons-abap-agent-runtime.json
- MCP
- Connecting an agent