ARC-1 Tool Reference¶
Complete documentation for all MCP tools available in ARC-1.
ARC-1 exposes 12 intent-based tools designed for AI agents. Instead of 200+ individual tools (one per object type per operation), ARC-1 groups by intent with a type parameter for routing. This keeps the LLM's tool selection simple, with the schema payload guarded by CI budgets and a hyperfocused 1-tool mode for tight context windows.
Experimental aggregate multi-target mode can add one catalog utility, SAPTargets. It is not one
of the 12 core intent tools and is never exposed on /mcp or a pinned target route.
Error intelligence: ARC-1 enriches many SAP ADT failures with concise, actionable hints (for example lock conflicts, enqueue issues, missing authorizations, and transport/corrNr problems). Hints can include SAP transaction references like SM12 (locks), SU53 (authorization), and SE09 (transport checks) to speed up troubleshooting.
SAPTargets (aggregate multi-target only)¶
List the SAP targets that can be selected through /multi/mcp. The tool takes no target parameter
and does not contact SAP. Listing a target proves only that ARC-1 accepted its configuration; it
does not prove that the current user's SAP identity can access it.
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | No | Case-insensitive filter over target IDs and descriptions. Admin results also match destination name, status, code, and message. Maximum 160 characters. |
offset |
integer | No | Admin-only diagnostic-page offset. Follow diagnosticNextOffset when the bounded result is truncated. |
- A reader sees
SAPTargetsonly when more than one target is active. Its compact response contains target IDs, descriptions, andidentity(per-userorshared). - An Admin sees it with zero, one, or many targets, including paged, secret-safe registry and quarantine diagnostics. Destination URLs, credentials, tokens, certificates, and raw Cloud Connector location IDs are never returned. It remains available when registry discovery fails.
- It is never listed on
/<SYSTEM>/<CLIENT>/mcp, an alias-pinned route, or the explicitly configured single-target/mcproute.
See Multi-System Setup for the response shape, privacy boundary, and target-selection behavior.
SAPRead¶
Read any SAP ABAP object.
Use SAPRead when you need exact raw source, one method body, grep output, inactive drafts, revision history, or metadata. For object understanding questions such as "what does this class do?" or pre-change/spec/review orientation, start with SAPContext(action="deps"); it includes the object's KTD when available and avoids reading full source before the model knows what matters.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Object type (see below; includes AUTH, FEATURE_TOGGLE, ENHO, VERSIONS, VERSION_SOURCE on on-prem systems, and the server-driven objects DSFD/DESD/EVTB/EVTO/DTSC/CSNM/COTA/DTDC/UIAD where the system advertises them — ABAP Platform 2025 / 8.16+, plus EVTB on S/4HANA 2023) |
name |
string | No | Object name (e.g., ZTEST_PROGRAM, ZCL_ORDER, MARA) |
action |
string | No | "diff" — return a unified diff between two source versions on this system (only the hunks, not two full sources), using from/to. Source types only: PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DCLS, BDEF, SRVD, DDLX, TABL (CDS views are DDLS; classic DDIC VIEW is unsupported — it has no plain-text source). Note: SAP only snapshots a version on transport release, so from/to revision ids are sparse — active vs inactive (pending unactivated changes) is the most reliable use. |
from |
string | No | For action="diff": OLD side — "active" (default), "inactive", a revision id (from a VERSIONS response), or a full /sap/bc/adt/ revision URI. |
to |
string | No | For action="diff": NEW side — defaults to "inactive". Same accepted values as from. |
fromLabel |
string | No | For action="diff": optional display label for the OLD side in the summary and patch header, e.g. DNT-6-6: Validate discounts (DS7K900123). Does not affect source resolution. |
toLabel |
string | No | For action="diff": optional display label for the NEW side in the summary and patch header, e.g. active or inactive draft. Does not affect source resolution. |
format |
string | No | Output format: "text" (default) or "structured" (CLAS only, see below) |
include |
string | No | For CLAS: main, testclasses, definitions, implementations, macros. For DDLS: elements (extract CDS view elements). |
method |
string | No | For CLAS: method name to read (e.g., get_name), or * to list all methods |
grep |
string | No | Case-insensitive regex; returns only matching source lines (+3 lines of context, with line numbers) instead of the full object — token-efficient search over source-bearing types (PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DCLS, BDEF, SRVD, SRVB, SKTD/KTD, DDLX, TABL, VIEW). For CLAS, matches are annotated with the owning class/method; combine with include= to scope a section, but not with method=. Falls back to a literal search when the pattern is not valid regex. |
expand_includes |
boolean | No | For FUGR: expand include source inline |
group |
string | No | For FUNC: function group name |
versionUri |
string | No | For VERSION_SOURCE: revision URI from a VERSIONS response (revisions[].uri), must start with /sap/bc/adt/ |
maxRows |
number | No | For TABLE_CONTENTS: max rows (default 100) |
sqlFilter |
string | No | For TABLE_CONTENTS: condition expression only (no WHERE, no SELECT), e.g. MANDT = '100' |
objectType |
string | No | For API_STATE: SAP object type (CLAS, INTF, PROG, FUGR, etc.) — auto-detected from name if omitted |
version |
string | No | Source version: active (default), inactive, or auto. Applies to source-bearing types (PROG, CLAS, INTF, FUNC, INCL, DDLS, DCLS, DDLX, BDEF, SRVD, FUGR, SRVB, SKTD/KTD, TABL, VIEW). See Active vs Inactive Source below. |
force_refresh |
boolean | No | For source reads: bypass the cached source AND the inactive-list cache before reading. Use when you know the object changed outside ARC-1 in a way conditional GET can't catch. |
includeSignature |
boolean | No | For FUNC only. When true, response is JSON {source, signature: {importing[], exporting[], changing[], tables[], exceptions[], raising[]}, processingType?, updateTaskKind?} — each parameter parsed into {kind, name, type, byValue?, default?, optional?}; processingType reports normal/rfc/update (a metadata read, so it may add propertiesError instead if that GET fails). Default false (returns plain source body). See SAPWrite for FUNC for the round-trip. |
Supported types:
| Type | Description |
|---|---|
PROG |
Program source |
CLAS |
Class source |
INTF |
Interface source |
FUNC |
Function module source |
FUGR |
Function group structure (function modules + includes). Uses /functions/groups/{g}/objectstructure, falling back to the generic /repository/objectstructure on releases that don't ship it (NW 7.50/7.51). |
INCL |
Include source |
DDLS |
CDS view source |
DCLS |
CDS access control source (authorization rules for CDS views) |
DDLX |
CDS metadata extension (UI annotations for Fiori Elements) |
BDEF |
Behavior definition |
SRVD |
Service definition |
SRVB |
Service binding (structured JSON: OData version, binding type, publish status) |
SKTD / KTD |
Knowledge Transfer Document attached to an ABAP object. Returns Markdown decoded from the ADT XML envelope. KTD is a friendly alias; SKTD remains the canonical SAP object type. |
TABL |
DDIC TABL — covers both transparent tables (T000-style) and DDIC structures (BAPIRET2-style). Returns CDS-like source. ARC-1 auto-resolves the URL: tries /sap/bc/adt/ddic/tables/{name} first, falls back to /sap/bc/adt/ddic/structures/{name} on 404. There is no separate STRU type — TABL is the canonical short type for both, mirroring TADIR R3TR TABL and abapGit conventions. |
TTYP |
DDIC table type (on-prem only). Returns {name, description, rowType, rowTypeKind, accessType, keyKind}. Written via SAPWrite(type="TTYP") — the create POSTs a CHAR shell and a follow-up PUT sets the real row type. |
VIEW |
DDIC view |
DOMA |
Domain metadata (structured JSON: data type, length, fixed values, value table) |
DTEL |
Data element metadata (structured JSON: type, labels, search help) |
AUTH |
Authorization field metadata (structured JSON: role name, check table, domain, conversion exit, org-level info) |
FEATURE_TOGGLE |
Feature toggle states (structured JSON: toggle state per system from SAP switch framework). Renamed from FTG2 in audit Plan B (docs/research/abap-types/types/ftg2.md) — FTG2 still accepted as deprecated alias for one minor release with stderr warning. |
ENHO |
Enhancement implementation metadata (structured JSON: BAdI technology, referenced object, implementation classes) |
VERSIONS |
Revision history for an ABAP object. Returns JSON: { object: { name, type }, revisions: [{ id, author, timestamp, transport?, uri }] }. Optional include for CLAS and group for FUNC. On-prem only. |
VERSION_SOURCE |
Source code at a specific revision. Pass versionUri from a VERSIONS response. Returns raw source text. On-prem only. |
DESD |
CDS Logical External Schema — server-driven object (generic AFF read). Returns JSON: parsed blue:blueSource metadata (name, type, description, package, language, version, …) + the AFF JSON source. SAP_BASIS 8.16+ (ABAP Platform 2025), discovery-gated. |
EVTB |
RAP Event Binding — server-driven object. JSON metadata + AFF JSON source (boName, boOperation, events[]). Available on S/4HANA 2023 (758) and 8.16+. |
EVTO |
RAP Event Object — server-driven object. 8.16+. |
DTSC |
CDS Static Cache (table-entity buffer) — server-driven object. JSON metadata + DDL text source (define static cache …). 8.16+. |
CSNM |
Core Schema Notation Model (CSN) — server-driven object. 8.16+. |
COTA |
Communication Target — server-driven object. 8.16+. |
DSFD |
CDS Scalar Function Definition — server-driven object. JSON metadata + DDL text source (define scalar function …). Available on S/4HANA 2023 (758) and 8.16+. |
UIAD |
Launchpad App Descriptor Item (LADI) — server-driven object. SAP_BASIS 8.16+. The successor to the deprecated tile/target-mapping model and the unit SAP Build Work Zone content exposure v2 federates. AFF JSON source carries generalInformation (appType, catalogId, transaction), navigation (targetMappingId, semanticObject, action, form factors) and tiles[]. Find names via SAPRead type=DEVC on the owning package (listed as UIAD/TYP — pass the bare UIAD). |
DTDC |
CDS Dynamic Cache — server-driven object with its OWN metadata format (<dtdc:dtdcSource>, not blue:blueSource). JSON metadata + DDL text source (define dynamic cache …). Available on S/4HANA 2023 (758) and 8.16+. |
TRAN |
Transaction metadata (structured JSON: code, description, program) |
SOBJ |
BOR business object (list methods, or read specific method with method param) |
BSP |
BSP/UI5 filestore (list apps, browse structure, read files via name+include path) |
API_STATE |
API release state (clean core compliance — contract states C0-C4, successor info) |
TABLE_CONTENTS |
Table data (rows) |
DEVC |
Package contents |
SYSTEM |
System info (SID, release, kernel) |
COMPONENTS |
Installed software components |
MSAG |
Message class metadata (structured JSON with number, shortText, longText per message). MSAG is the canonical TADIR R3TR short type (added in audit Plan B — docs/research/abap-types/types/msag.md). |
MESSAGES |
Deprecated alias for MSAG. Still accepted for one minor release with stderr warning; use MSAG going forward. |
TEXT_ELEMENTS |
Program text elements |
VARIANTS |
Program variants |
INACTIVE_OBJECTS |
List all objects pending activation for the calling user (no name needed). Returns rich metadata: name, type, uri, description?, user, deleted, transport, parentTransport. |
Structured format (CLAS only):
When format="structured" is used with CLAS type, the response is a JSON object with:
- metadata — class metadata (description, language, category, package, fixPointArithmetic, abapLanguageVersion)
- main — main class source code
- testclasses — test class source (or null if none)
- definitions — local definitions (or null)
- implementations — local implementations (or null)
- macros — macros (or null)
This is useful when you need to understand class structure or separate test code from production code.
Examples:
SAPRead(type="PROG", name="ZTEST_REPORT")
SAPRead(type="CLAS", name="ZCL_ORDER", include="testclasses")
SAPRead(type="CLAS", name="ZCL_ORDER", format="structured") — JSON with metadata + decomposed source
SAPRead(type="CLAS", name="ZCL_ORDER", method="*") — list all methods
SAPRead(type="CLAS", name="ZCL_ORDER", method="get_name") — read a specific method
SAPRead(type="CLAS", name="ZCL_ORDER", grep="select.*from") — matching lines only, annotated by method
SAPRead(type="CLAS", name="ZCL_ORDER", include="text_symbols") — maintained text pool (on-prem; see Class text symbols)
SAPRead(type="PROG", name="ZTEST_REPORT", grep="WRITE") — search source, returns matches + context
SAPRead(type="DDLS", name="ZI_TRAVEL", include="elements") — extract CDS view elements
SAPRead(type="DCLS", name="ZI_TRAVEL_DCL") — CDS access control source
SAPRead(type="DDLX", name="ZC_TRAVEL") — metadata extension with UI annotations
SAPRead(type="SRVB", name="ZUI_TRAVEL_O4") — service binding metadata as JSON
SAPRead(type="KTD", name="ZCL_ORDER") — read the object's Knowledge Transfer Document as Markdown
SAPRead(type="FUGR", name="ZUTILS", expand_includes=true) — function group with all includes expanded
SAPRead(type="TABL", name="BAPIRET2") — DDIC structure (auto-resolved to /structures/)
SAPRead(type="TABL", name="T000") — transparent table (auto-resolved to /tables/)
SAPRead(type="DOMA", name="BUKRS") — domain metadata with fixed values
SAPRead(type="DTEL", name="MANDT") — data element metadata with labels
SAPRead(type="AUTH", name="BUKRS") — authorization field metadata
SAPRead(type="FEATURE_TOGGLE", name="ABC_TOGGLE") — feature toggle states (FTG2 still works as deprecated alias)
SAPRead(type="MSAG", name="SY") — message class (MESSAGES still works as deprecated alias)
SAPRead(type="ENHO", name="ZMY_BADI_IMPL") — enhancement implementation metadata
SAPRead(type="VERSIONS", name="ZARC1_TEST_REPORT") — list object revisions with revision URIs
SAPRead(type="VERSIONS", name="ZCL_X", include="definitions") — list revisions for CLAS definitions include
SAPRead(type="VERSION_SOURCE", versionUri="/sap/bc/adt/programs/programs/ZARC1_TEST_REPORT/source/main/versions/20260410185851/00000/content") — fetch source at one revision
SAPRead(type="CLAS", name="ZCL_ORDER", action="diff") — diff active vs your inactive draft (pending changes)
SAPRead(type="CLAS", name="ZCL_ORDER", action="diff", from="00001", to="active") — diff a revision against the active version
SAPRead(type="CLAS", name="ZCL_ORDER", action="diff", from="00001", to="active", fromLabel="DNT-6-6 (DS7K900123)", toLabel="active") — readable diff headers
SAPRead(type="TRAN", name="SE38") — transaction metadata
SAPRead(type="SOBJ", name="BUS2032") — list BOR object methods
SAPRead(type="BSP") — list all BSP/UI5 apps
SAPRead(type="API_STATE", name="CL_SALV_TABLE") — check if class is released for ABAP Cloud
SAPRead(type="API_STATE", name="IF_HTTP_CLIENT") — check interface release state
SAPRead(type="API_STATE", name="MARA", objectType="TABL") — check table with explicit type
SAPRead(type="TABLE_CONTENTS", name="MARA", maxRows=10, sqlFilter="MATNR LIKE 'Z%'")
# TABLE_CONTENTS sqlFilter must be a condition expression only:
# ✅ "MANDT = '100'"
# ❌ "WHERE MANDT = '100'"
# ❌ "SELECT * FROM MARA WHERE MANDT = '100'"
SAPRead(type="SYSTEM")
SAPRead(type="INACTIVE_OBJECTS") — list objects pending activation
Active vs Inactive Source¶
Source-bearing types accept a version parameter to choose between the activated source and the calling user's unactivated draft:
version |
Behaviour |
|---|---|
active (default) |
Reads the last activated source. If the user has an unactivated draft (created in Eclipse/SE80, not yet activated), the response is prefixed with a one-line note flagging the draft so the LLM knows there's a gap and can re-read with version='inactive' if appropriate. |
inactive |
Reads the user's draft directly. If no draft exists, SAP falls back to the active source and the response is prefixed with: "No inactive draft exists for this object on the server. Returning the active version." |
auto |
Resolves client-side via the cached inactive-objects list: returns the draft if one exists, otherwise active. No warning is prefixed (the caller explicitly opted into "show me my view"). |
The default preserves all existing caller behaviour; version is an opt-in extension.
SAPRead(type="CLAS", name="ZCL_ORDER") — active source (default)
SAPRead(type="CLAS", name="ZCL_ORDER", version="inactive") — your draft
SAPRead(type="CLAS", name="ZCL_ORDER", version="auto") — draft if it exists, else active
Cache Behaviour¶
ARC-1 caches every source read with the SAP-emitted ETag. On the next read, ARC-1 sends If-None-Match so the server itself confirms freshness:
304 Not Modified→ cached body is still authoritative; response is prefixed with[cached:revalidated].200 OKwith new body and ETag → cache is replaced; no prefix on the response.404/410→ cache entry is invalidated and the error is propagated.
This means external writes (Eclipse activations, gCTS pulls, abapGit imports) are caught automatically — there's no staleness window. To force a fresh fetch and bypass the cache for one read, pass force_refresh: true.
The full caching architecture (per-version cache keys, conditional GET, dependency-graph caching, inactive-list session cache, write invalidation) is documented in Caching System.
SAPSearch¶
Search for ABAP objects by name pattern, exact object-directory names, or ABAP source text.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
query |
string | No | Search pattern (e.g., ZCL_ORDER*, Z*TEST*), source text, or comma/whitespace-separated names for tadir_lookup |
maxResults |
number | No | Maximum results (default 100) |
searchType |
string | No | object (default, name search), tadir_lookup (exact cross-package object lookup), or source_code (text search within ABAP source) |
names |
array | No | For tadir_lookup: exact object names to resolve across packages |
objectTypes |
array | No | For tadir_lookup: optional ADT/TADIR type filters such as TABL, DDLS, BDEF, SRVB, CLAS/OC |
objectType |
string | No | For source_code: filter by object type. For tadir_lookup: single type filter |
source |
string | No | For tadir_lookup only: adt (default), db, or both. db/both require the sql scope and SAP_ALLOW_FREE_SQL=true. See TADIR lookup source modes below. |
packageName |
string | No | For source_code search: filter by package |
Returns: Object type, name, package, and description for each match. tadir_lookup groups exact matches by requested name and includes a missing list. Source code search also returns line numbers and code snippets. When source='both' reveals divergence between the ADT and DB views, the response adds a splitBrain: [name, ...] array and a warnings: [...] array explaining each diverging name.
Examples:
SAPSearch(query="ZCL_ORDER*")
SAPSearch(query="Z*INVOICE*", maxResults=20)
SAPSearch(searchType="tadir_lookup", names=["ZDM_PROJECT_D","ZR_DM_PROJECT"], objectTypes=["TABL","BDEF"])
SAPSearch(searchType="tadir_lookup", query="ZDM_PROJECT_D ZUI_DM_PROJECTS_O4")
SAPSearch(searchType="tadir_lookup", names=["ZR_OLD_VIEW"], source="both") // detect TADIR ghosts after a failed delete
SAPSearch(query="SY-SUBRC", searchType="source_code")
SAPSearch(query="SELECT * FROM mara", searchType="source_code", objectType="CLAS", packageName="ZDEV")
Umlaut handling: Object name queries containing non-ASCII characters (ä, ö, ü, ß) are automatically transliterated to ASCII equivalents (AE, OE, UE, SS). SAP object names are ASCII-only. Source code search preserves non-ASCII characters.
Field names: If searching for a field/column name (e.g., MATNR, BUKRS), use SAPQuery against DD03L instead — SAPSearch only searches object names.
TADIR lookup: Use searchType="tadir_lookup" for reset/create preflights that need to know whether objects exist anywhere, regardless of package. The default source='adt' uses ADT repository quick search, which avoids long IN (...) parser limits and works in read/search-only configurations. The endpoint deliberately filters out TADIR rows that don't resolve to a live workbench resource, so orphan/ghost entries (left behind by aborted create/delete cycles) are invisible to the default path — see the source modes section below.
TADIR lookup source modes¶
source |
Underlying call | Scope required | When to use |
|---|---|---|---|
adt (default) |
GET /sap/bc/adt/repository/informationsystem/search?operation=quickSearch&query=... (one per name) |
read |
Default; workbench-resolvable objects only. Skips TADIR ghost rows by design. |
db |
POST /sap/bc/adt/datapreview/freestyle with SELECT pgmid, object, obj_name, devclass FROM tadir WHERE obj_name IN (…) |
sql (server-side: SAP_ALLOW_FREE_SQL=true) |
One round-trip for any number of names — much faster for large lists, and surfaces orphan TADIR rows the ADT route hides. |
both |
Parallel adt + db calls; merge by (base type, name) with dedupe |
sql |
Explicit split-brain detection. Returns splitBrain: [name, ...] and a warnings array when the two sources disagree (e.g. a TADIR ghost from an aborted create/delete). |
Every match in the result set is stamped with an _origin: 'adt' | 'db' field so callers can colour-code or filter rows by provenance. The 'db' path also covers legacy SEGW types (IWSV/IWMO/IWPR) that the ADT info-system does not return; the URL is left empty for types that aren't addressable via a single ADT base URL (e.g. function modules, which need the parent group).
Source code search availability: Not available on all SAP systems. Requires SICF service activation. If unavailable, falls back with an error suggesting SAPQuery as an alternative.
SAPWrite¶
Create or update ABAP source code. Handles lock/modify/unlock automatically.
NetWeaver < 7.51: ADT writes over HTTP require a stateful session that older releases don't honor, so writes fail with
423 invalid lock handleuntil theabapfs_extensionsenhancement is installed on the SAP system. This is not SAP Note 2727890 (a separate narrow bug). See SAP trial setup → Writes fail with 423 (423 troubleshooting section). S/4HANA (≥ 7.51) is unaffected.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | create, update, delete, edit_method, edit_unit (on-prem), edit_class_definition, add_method, edit_method_signature, delete_method, change_method_visibility, batch_create, scaffold_rap_handlers, generate_behavior_implementation, or edit_text_symbols. edit_unit surgically replaces one FORM or MODULE in a PROG/INCL; see Procedural unit surgery. The class-section surgery actions (edit_class_definition, add_method, edit_method_signature, delete_method, change_method_visibility) are token-efficient edits to a global class without re-sending /source/main. See Class-section surgery below. edit_text_symbols writes a global class's text pool — see Class text symbols. |
type |
string | No | PROG, CLAS, INTF, FUNC, FUGR, INCL, DDLS, DCLS, DDLX, BDEF, SRVD, SRVB, SKTD/KTD, TABL, TTYP (on-prem), TABL/DT, TABL/DS, DOMA, DTEL, MSAG (for single object actions; availability is adapted for BTP vs. on-prem), plus the server-driven objects DESD/EVTB/DTSC/CSNM/EVTO/COTA/DSFD/DTDC/UIAD (see Server-driven object writes). Slash/case aliases are auto-normalized (e.g., CLAS/OC or clas → CLAS; KTD → SKTD). |
group |
string | No | For FUNC: parent function-group name. Required for FUNC create (the FUGR must already exist — create it first via SAPWrite type=FUGR). Auto-resolved via search for FUNC update/delete if omitted. For INCL: addresses a structural include inside this function group; supported by update and edit_unit. Ignored for other types. |
rowType |
string | No | TTYP create/update (on-prem only): the row type — a built-in ABAP type (STRING, I, …) or a DDIC type name such as BAPIRET2. |
rowTypeKind |
string | No | TTYP only: builtin or structure. Omit it and ARC-1 infers from rowType; pass it explicitly when SAP knows a built-in type ARC-1 has not enumerated. |
processingType |
string | No | On-prem FUNC create only: normal, rfc (Remote-Enabled), or update. Omit it to preserve the legacy SAP-default behavior. |
updateTaskKind |
string | No | Required when processingType="update": startImmediate (V1 restartable), immediateStartNoRestart (V1 non-restartable), or startDelayed (V2). Rejected for normal/RFC modules. |
name |
string | No | Object name (for single object actions) |
source |
string | No | ABAP source code. For create/update: full source body. For edit_method: new method body. For edit_unit: the complete replacement FORM … ENDFORM. or MODULE … ENDMODULE. block. For edit_class_definition without include=: ONLY the new global CLASS … DEFINITION … ENDCLASS. block (~10–80 lines instead of full class). For edit_class_definition with include=: the FULL replacement body of that class-local include; for include="testclasses" this normally includes both local CLASS ltc_* DEFINITION and CLASS ltc_* IMPLEMENTATION. For edit_method_signature: ONLY the new METHODS clause for one method (~1–5 lines). Not used by add_method/delete_method/change_method_visibility — pass the method clause/name and target visibility via method/visibility instead. |
include |
string | No | For CLAS write actions update, edit_method, and edit_class_definition: write a class-local include (definitions, implementations, macros, or testclasses) instead of /source/main. Omit this parameter for main class source updates. add_method/edit_method_signature/delete_method/change_method_visibility operate on the global class /source/main only and reject include=. Include writes create an inactive draft; verify with SAPRead(version="inactive") until activation. NOTE: edit_class_definition with include= skips the symmetry refuse-policy (cross-include validation is not performed; rely on SAPActivate to catch breaks). Auto-init: whole-include writes (update and edit_class_definition with include=) create the target include automatically if it does not exist yet — notably testclasses (CCAU) on a freshly-created class. No separate init step or user-supplied lock handle is needed; the success message notes when ARC-1 initialized it. |
method |
string | No | For edit_method/edit_method_signature/delete_method/change_method_visibility: method NAME (e.g., "get_name", "zif_order~process", "lhc_project~approve_project"). For add_method: the full METHODS CLAUSE as ABAP source (e.g., "METHODS greet IMPORTING who TYPE string RETURNING VALUE(r) TYPE string."). |
unit |
string | No | For on-prem edit_unit: case-insensitive FORM or MODULE name (for example "PROCESS_ORDERS" or "STATUS_0100"). |
visibility |
string | No | For add_method: target visibility section — public (default), protected, or private. For change_method_visibility: target visibility section (required). The section header must already exist in the DEFINITION block; if not, ARC-1 refuses with a hint to use edit_class_definition first. |
abstract |
boolean | No | For add_method: when true, only the METHODS clause is inserted into DEFINITION — no METHOD/ENDMETHOD stub is added to IMPLEMENTATION. Default false. |
bdefName |
string | No | For scaffold_rap_handlers: interface BDEF name used to derive required handler signatures. For generate_behavior_implementation: optional override; default discovery reads the class metadata's <class:rootEntityRef> to locate the BDEF automatically. |
autoApply |
boolean | No | For scaffold_rap_handlers: when true, create missing lhc_* skeletons, inject missing signatures plus empty method stubs into the behavior pool, and write back. Not used by generate_behavior_implementation (which always applies; use dryRun=true there to preview). |
targetAlias |
string | No | For scaffold_rap_handlers and generate_behavior_implementation: optional RAP entity alias filter (scaffold only one alias/handler class) |
activate |
boolean | No | For generate_behavior_implementation: when true (default), runs SAPActivate on the class after writing. When false, only the source is written. Activation failures matching the well-known Local classes of CL_ABAP_BEHAVIOR_HANDLER… stale-active coupling do not throw — they return activation.success=false with a guided recovery hint so the just-written CCDEF/CCIMP source remains useful. |
dryRun |
boolean | No | For generate_behavior_implementation: when true, runs discovery + cross-validation + scaffold planning and returns the report without writing or activating. Use this to preview what would change. |
description |
string | No | Object description for create (defaults to name if omitted, max 60 chars) |
package |
string | No | Package for new objects (default $TMP) |
transport |
string | No | Transport request number. For update and delete, if omitted ARC-1 auto-uses the correction number returned by the SAP lock (if any). Explicit value takes precedence. |
lintBeforeWrite |
boolean | No | Override server lint setting for this call (false to bypass pre-write lint) |
preflightBeforeWrite |
boolean | No | Override deterministic RAP preflight checks for this call (false to bypass TABL/BDEF/DDLX/DDLS static checks) |
dataType |
string | No | DOMA/DTEL: ABAP data type (CHAR, NUMC, DEC, ...) |
length |
number | No | DOMA/DTEL: data type length |
decimals |
number | No | DOMA/DTEL: decimal places |
outputLength |
number | No | DOMA: output length |
conversionExit |
string | No | DOMA: conversion exit (e.g., ALPHA) |
signExists |
boolean | No | DOMA: whether signed values are allowed |
lowercase |
boolean | No | DOMA: whether lowercase characters are allowed |
fixedValues |
array | No | DOMA: fixed value entries ([{low, high?, description?}]) |
valueTable |
string | No | DOMA: value table reference (e.g., T001) |
typeKind |
string | No | DTEL: domain or predefinedAbapType |
typeName |
string | No | DTEL: referenced domain/type name (for typeKind="domain") |
shortLabel |
string | No | DTEL: short field label |
mediumLabel |
string | No | DTEL: medium field label |
longLabel |
string | No | DTEL: long field label |
headingLabel |
string | No | DTEL: heading field label |
searchHelp |
string | No | DTEL: search help name |
searchHelpParameter |
string | No | DTEL: search help parameter |
setGetParameter |
string | No | DTEL: SET/GET parameter ID |
defaultComponentName |
string | No | DTEL: default component name |
changeDocument |
boolean | No | DTEL: change document flag |
messages |
array | No | MSAG: message entries ([{number, shortText, longText?}]) — number is a 3-digit string (e.g., "001"), shortText is the message text (max 73 chars) |
serviceDefinition |
string | No | SRVB: referenced service definition name (SRVD). Required for SRVB create. |
bindingType |
string | No | SRVB: binding type (default ODATA) |
category |
string | No | SRVB: binding category (0 = UI, 1 = Web API; default 0) |
version |
string | No | SRVB: service version for binding metadata (default 0001) |
objects |
array | No | For batch_create: ordered list of objects (see below) |
activateAtEnd |
boolean | No | For batch_create only. Default false (per-object inline activation). When true, ARC-1 writes inactive drafts for every object then issues one terminal batch-activate — SAP's activator resolves cross-references between siblings in a single pass. Use this for interdependent objects (composition-linked DDLS, RAP behavior stacks where parent references not-yet-active child). Partial-failure semantics are unchanged: a write-phase failure still breaks the loop and only the already-written subset is batch-activated. |
DDIC metadata writes: DOMA, DTEL, MSAG, and SRVB use structured XML payloads and do not use /source/main. MSAG writes use the /sap/bc/adt/messageclass/ endpoint and accept a messages array of {number, shortText, longText?} entries. SRVB create uses wildcard content type (application/*) and SRVB update uses vendor type (application/vnd.sap.adt.businessservices.servicebinding.v2+xml).
Source-based DDIC writes: TABL, DDLS, DCLS, BDEF, SRVD, and SKTD/KTD are source-based and write source via /source/main. TABL covers both transparent tables (TABL/DT) and DDIC structures (TABL/DS); ARC-1 auto-resolves between /ddic/tables/ and /ddic/structures/ for read/update. SKTD writes Markdown knowledge-transfer documentation attached to one KTD-capable ABAP object; KTD is accepted as a friendly alias. Create requires refObjectType and uses name as the documented object name. ARC-1 supports KTD creates for parent types with verified ADT parent URI routing, including DDLS/DF, BDEF/BDO, SRVD/SRV, SRVB/SVB, and DEVC/K. CLAS/OC, INTF/OI, and PROG/P were not registered for KTD DOCUMENTATION scope on the tested SAP_BASIS 758 and 816 systems; use ABAP Doc for those code objects. Other SAP-registered KTD parent types require ARC-1 parent URI routing before create is enabled.
Server-driven object writes¶
DESD, EVTB, DTSC, CSNM, EVTO, COTA, DSFD, and UIAD are server-driven objects (mostly ABAP Platform 2025 / SAP_BASIS 8.16+) — ~46 repository types that share one AFF generic-object contract. SAPWrite supports create, update, and delete for them; SAPActivate activates them:
createposts a minimal<blue:blueSource>metadata body to the type's collection (e.g./sap/bc/adt/ddic/desd), then — ifsourceis supplied — writes it. The object is left inactive; follow withSAPActivate(type=..., name=...).sourceformat is per-type. Most types take AFF JSON — e.g.{"formatVersion":"1","header":{"description":"…","originalLanguage":"en","abapLanguageVersion":"cloudDevelopment"}}— parse-validated (clean error on malformed JSON) and written to…/source/mainasapplication/json.DTSCandDSFDinstead take DDL text (define static cache …,define scalar function …), written astext/plain; sending the wrong content type is a hard415from SAP, so the flavor is pinned per type inSDO_REGISTRY. ABAP-specific pre-write steps (lint, RAP preflight, CDS guard) do not apply.updaterequiressource(AFF JSON or DDL text, per the type);deleteuses the standard lock → delete flow. Both honor theallowedPackagesceiling against the object's real package.- Availability is discovery-gated and per-type. On systems that don't expose a type, write returns a clean
requires SAP_BASIS 8.16+error. Most types need 8.16+, butEVTB(RAP Event Binding),DSFD(CDS Scalar Function Definition) andDTDC(CDS Dynamic Cache) also ship on S/4HANA 2023 (758) — their write paths are live-verified there (create/update/activate/read/delete). NetWeaver 7.50 exposes none of them.
| Type | Object | Notes |
|---|---|---|
DESD |
CDS Logical External Schema | Creates standalone — the reference round-trip type. |
EVTB |
RAP Event Binding | Also on 758. |
EVTO |
RAP Event Object | Create uses the blues v2 content-type (the others use v1). |
DTSC |
CDS Static Cache (table-entity buffer) | Source is DDL text, not JSON. |
CSNM |
Core Schema Notation Model (CSN) | |
COTA |
Communication Target | |
DSFD |
CDS Scalar Function Definition | Source is DDL text, not JSON. Also on 758. |
UIAD |
Launchpad App Descriptor Item (LADI) | Registered, but writes are refused by SAP outside ABAP Cloud: 400 Editing of LADIs with ALV "Standard" not allowed in workbench tools — LADI edits require the ABAP Cloud language version. Read-only in practice on-prem. |
DTDC |
CDS Dynamic Cache | Non-blue metadata format (<dtdc:dtdcSource>). Source is DDL text (define dynamic cache …). Also on 758. |
Other actions (edit_method, surgery, batch_create, RAP scaffolding) are not supported for server-driven types and return a clear error.
Function group (FUGR) create: POSTs <group:abapFunctionGroup … adtcore:type="FUGR/F"> to /sap/bc/adt/functions/groups with content type application/vnd.sap.adt.functions.groups.v3+xml. Provide package and (for non-$TMP) transport. Delete the FUGR only after all its function modules have been deleted.
Function module (FUNC) create / update / delete (issue #250): The parent FUGR must already exist — pass group explicitly on create (or auto-resolve via search on update/delete). Create POSTs <fmodule:abapFunctionModule … adtcore:type="FUGR/FF"> with <adtcore:containerRef> to /sap/bc/adt/functions/groups/{group}/fmodules. The FM inherits its package from the parent FUGR: omit package, or supply the exact inherited package as an assertion. ARC-1 resolves and safety-checks the real FUGR package before creating the contained module, and rejects an explicit mismatch. SAPGUI-style *"…IMPORTING…"* parameter comment blocks in source are auto-stripped before PUT as defense-in-depth (SAP rejects them with FUNC_ADT028) and a warning is appended in that case.
Execution semantics are function-module metadata, not ABAP source. Set processingType="rfc" for a Remote-Enabled module. For update modules, set processingType="update" plus an explicit updateTaskKind; V1 "Start immediately" is startImmediate. ARC-1 rejects processing fields on updates and non-FUNC objects instead of silently ignoring them.
SAP's collection POST creates a normal function-module shell even when it accepts processing attributes. For an explicit processing type, ARC-1 therefore reads the new inactive root, preserves the server-provided representation, applies a locked metadata PUT with the release-negotiated media type, and reads the root back before reporting success. If that post-create step fails, the error warns that a normal shell may remain and must be reviewed or deleted before retrying. When processingType is omitted, ARC-1 keeps the pre-existing create behavior without the extra metadata round trips.
SAPWrite for FUNC: create / update with structured parameters¶
Issue #252 added structured FM parameter management. Pass a parameters array to declare the function module's signature; ARC-1 builds the ABAP-source-based IMPORTING / EXPORTING / CHANGING / TABLES / EXCEPTIONS / RAISING clause and splices it into the source body before PUT. SAP ADT exposes parameters ONLY through /source/main (verified live on a4h S/4HANA 2023 + NPL 7.50 SP02) — there is no separate metadata endpoint.
Each parameter:
| Field | Type | Description |
|---|---|---|
kind |
string | One of importing, exporting, changing, tables, exceptions, raising. |
name |
string | Parameter / exception name. Always uppercased on emit. |
type |
string | ABAP type expression (STRING, I, BAPIRET2, TYPE STANDARD TABLE OF X, LIKE DOKHL-OBJECT, …). Required for IMPORTING/EXPORTING/CHANGING/TABLES; ignored for EXCEPTIONS/RAISING. For TABLES, include the leading TYPE or LIKE keyword. |
byValue |
boolean | Emit VALUE(name) wrapper. Default false (pass-by-reference). |
default |
string | Raw ABAP literal — IMPORTING/CHANGING only. Emitted verbatim (no escaping). Examples: 'X', 0, space. |
optional |
boolean | Emit OPTIONAL keyword. |
Example — create an FM with a typed signature:
SAPWrite({
action: "create",
type: "FUNC",
name: "Z_GREET",
group: "ZARC1_FG",
description: "Greet a user",
parameters: [
{ kind: "importing", name: "IV_NAME", type: "STRING", byValue: true, default: "'World'" },
{ kind: "exporting", name: "EV_GREET", type: "STRING", byValue: true },
{ kind: "raising", name: "CX_ROOT" }
],
source: " ev_greet = |Hello { iv_name }|.\n"
})
The source value is the FM body only — ARC-1 wraps it in FUNCTION Z_GREET …. ENDFUNCTION. and emits the signature clause from parameters. Or pass full FUNCTION/ENDFUNCTION source and the splicer will replace just the signature region. Or omit source entirely to create an empty-body FM with only the signature.
Round-trip: SAPRead({type: "FUNC", name: "Z_GREET", group: "ZARC1_FG", includeSignature: true}) returns:
{
"source": "FUNCTION z_greet\n IMPORTING\n VALUE(iv_name) TYPE string DEFAULT 'World'\n EXPORTING\n VALUE(ev_greet) TYPE string\n RAISING\n cx_root.\n ev_greet = |Hello { iv_name }|.\nENDFUNCTION.",
"signature": {
"importing": [ { "kind": "importing", "name": "IV_NAME", "type": "string", "byValue": true, "default": "'World'" } ],
"exporting": [ { "kind": "exporting", "name": "EV_GREET", "type": "string", "byValue": true } ],
"changing": [],
"tables": [],
"exceptions": [],
"raising": [ { "kind": "raising", "name": "CX_ROOT" } ]
}
}
Backward-compat: when parameters is omitted, the existing source-only PUT path runs unchanged. When includeSignature is omitted on read, the response is plain text source.
Reading the processing type back¶
SAPRead(type="FUNC", …, includeSignature=true) reports processingType and, for update modules,
updateTaskKind alongside the parsed signature — so a caller that set one can verify it took effect.
It is a metadata read, so a failure there adds propertiesError to the payload rather than breaking
the signature read. See the create-side docs above for how the attributes are written.
Function-group structural includes (type="INCL" with group=)¶
SAPWrite(type="INCL", group=<FUGR>) creates, updates and deletes a function group's structural includes (LZ<GROUP>TOP global data, F01 subroutines, O01/I01 PBO/PAI modules, T99 unit tests):
SAPWrite({ action: "create", type: "INCL", name: "LZARC1_FGF01", group: "ZARC1_FG",
description: "Subroutines", package: "$TMP" })
SAPWrite({ action: "update", type: "INCL", name: "LZARC1_FGF01", group: "ZARC1_FG",
source: "FORM do_work.\nENDFORM.\n" })
- The include name must start with
L<GROUP>— SAP derives the include from its group and rejects anything else with an opaque500 "Attributes for program … have not been saved", so ARC-1 refuses it up front. - SAP maintains the main program itself: creating an include appends its
INCLUDEline, deleting one comments that line out. No main-program edit is needed. - The include inherits the group's package — SAP ignores
packagehere — soallowedPackagesis checked against the group's real package, and apackageargument that disagrees with it is refused. On update/delete the include itself is the lock and package-resolution target (itscontainerRefcarries the group's package). - Omitting
group=targets the standalone program-include collection instead, which still works for ordinary include names. AnL-prefixed name there is refused with a pointer togroup=— SAP reservesL*for function-group includes and answers with a 500, which would otherwise read as a transient error.
Verified on NW 7.50 SP02 and S/4HANA 2023 (758) — the ADT contract is identical on both.
Robust to GPT/OpenAI optional-field "overpopulation" (issue #360). GPT/OpenAI tool callers (especially under Structured Outputs / strict mode, the default for the Responses API) tend to over-populate optional fields — emitting null for every unused optional, blank strings, or stringified booleans like "false". ARC-1 normalizes these before validation: null and empty/whitespace strings are treated as omitted (across every tool), and optional booleans accept real JSON booleans and "true"/"false"/"1"/"0"/"yes"/"no" (so signExists="false" is correctly stored as false, never inverted). Practical guidance for tool authors: omit optional fields you don't need rather than sending ""/null; include is CLAS-only (for update/edit_method/edit_class_definition) and is ignored for other types/actions; delete needs only type and name (plus optional transport).
Mixed-case object names rejected on create. SAP TADIR is uppercase on every release; mixed-case names cause silent corruption (e.g., a DDLS named Zc_MyView registers as ZC_MYVIEW in TADIR but the source body keeps mixed case, confusing every downstream tool). SAPWrite(action="create"\|"batch_create") rejects mixed-case names pre-flight with an actionable error. The source code inside the object can still use mixed case (e.g., define view entity Zc_MyView); only the TADIR object name needs to be uppercase.
BDEF creation: Uses SAP's blue:blueSource XML format with content-type application/vnd.sap.adt.blues.v1+xml. BDEF objects are created with type="BDEF" and require a source parameter containing the behavior definition.
Release gates for pre-7.52 systems. Several ADT resources simply do not exist before SAP_BASIS 7.52. Rather than surfacing a raw 404 (whose generic hint wrongly suggests the object "was not found"), ARC-1 refuses these up front with a release hint once discovery has been probed:
| Operation | Missing resource | Fallback |
|---|---|---|
SAPWrite create type="TABL"/"TABL/DT" |
/sap/bc/adt/ddic/tables |
SE11. Writing the source through /ddic/structures/ instead would flip DD02L-TABCLASS to INTTAB and corrupt the table |
SAPWrite create type="DOMA" |
/sap/bc/adt/ddic/domains |
SE11. Data elements that reference a domain are blocked with it |
SAPWrite create type="TTYP" |
/sap/bc/adt/ddic/tabletypes |
SE11 |
SAPManage action="create_package" |
/sap/bc/adt/packages |
SE80 / SE21 |
Endpoint absence verified on two independent NW 7.50 systems (a dev edition and an ECC EhP8 7.50 SP31 production system); all four are present on S/4HANA 2023 (758) and ABAP Platform 2025 (816). Structures (TABL/DS), data elements, function groups, function modules and includes do work on 7.50 — note that DDIC structure source there uses define type <name> { … }, not define structure.
The gates key off ADT discovery, so a session that never probed (for example a one-shot CLI call) is never blocked — it falls through to SAP's own error.
DDIC save diagnostics: On SAPWrite save failures for DDIC/RAP artifacts (TABL, DDLS, DCLS, BDEF, SRVD, SRVB, DDLX, DOMA, DTEL), ARC-1 enriches errors with structured diagnostics:
- T100 message identifiers/variables (e.g., SBD_MESSAGES/007, V1..V4)
- Line-aware details when available
- Best-effort inactive syntax-check output for source-based DDIC creates (TABL, DDLS, DCLS, BDEF, SRVD, SRVB, DDLX)
This helps pinpoint the exact failing field/annotation instead of retrying blindly.
CDS dependency-aware CRUD hints (DDLS):
- SAPWrite(action="update", type="DDLS", ...) appends downstream where-used impact buckets and a concrete re-activation order + SAPActivate(objects=[...]) template.
- SAPWrite(action="delete", type="DDLS", ...) enriches dependency-style delete failures (for example DDIC [?/039]) with blocking dependents and suggested delete order.
- Delete hints include cycle-break guidance for mutually-dependent projection graphs (strip redirected/composition clauses, activate stripped versions, then delete).
- If delete guidance lists dependents that were just deleted, treat it as possible stale SAP active dependency/index state and retry after a short wait before deeper cleanup.
- If SAP reports a delete dependency error but current where-used results are empty, ARC-1 now adds stale active-dependency guidance: wait/retry after recent cleanup, activate restored/stripped sources first, then re-check references/locks.
- ARC-1 combines unfiltered ADT where-used results with scoped object-type filters where available. This avoids under-reporting dependents on SAP systems that return only a shallow default usageReferences result.
- If the where-used endpoint is unavailable on the backend, ARC-1 keeps the CRUD action behavior unchanged and adds a short "impact unavailable" note instead of failing the call.
Blue framework package handling: TABL and BDEF create calls now pass package in both the XML (packageRef) and URL query (_package=<pkg>), alongside transport (corrNr) when provided.
CDS pre-write validation:
- Table entity version guard:
define table entitysyntax requires ABAP Cloud (BTP) or S/4HANA on-premise with SAP_BASIS >= 757. On older systems, ARC-1 rejects the write early with an actionable message instead of letting SAP fail with a generic error. - Reserved keyword warnings: CDS field names like
position,value,type,dataetc. may be CDS reserved keywords that cause silent DDL save failures. ARC-1 detects these and includes an advisory warning (non-blocking) suggesting renamed alternatives. - Empty DDLS source: When reading a DDLS that exists but has no stored source, ARC-1 returns an explicit warning instead of silent empty content.
ARC-1-native pre-write semantic hints (TABL):
ARC-1 layers a small set of release-aware, RAP-convention hints on top of the abaplint pass. They emit severity:'warning' only — the write is not blocked. The first hint surfaces a known draft-table anti-pattern; future hints follow the same pattern in src/lint/pre-write-hints.ts.
arc1-tabl-draft-admin-include: A TABL source containsinclude sych_bdl_draft_admin_incwithout the SAP-canonical named-include prefix"%admin" : include sych_bdl_draft_admin_inc;. The bare include activates at TABL level on most releases but is non-canonical per ABAP keyword doc ABENBDL_DRAFT_TABLE and breaks BDEF binding for some draft scenarios. SAP standard draft tables (e.g.BOTD_TAB_ROOT_D) all use the named form. Hint surfaces in the responsewarningsarray withrule: 'arc1-tabl-draft-admin-include'.
RAP deterministic preflight validation:
- Runs before
create/update/batch_createfor RAP-prone source types (TABL,BDEF,DDLX,DDLS). - Blocks writes on deterministic rule errors (for example: missing
@Semantics.amount.currencyCodeforabap.curr, invalidauthorization master ( none ), unsupported DDLX scope annotations on on-prem 7.5x). - Emits warning-only findings for non-fatal patterns (for example: explicit client in DDLS select list).
- Per-call override:
preflightBeforeWrite=false.
Batch creation:
batch_create creates and activates multiple objects in sequence via a single tool call. Objects are processed in array order — put dependencies first (e.g., domain before data element, TABL before DDLS, DCLS after DDLS, BDEF after CDS views). Each object in the array has: type (string, required), name (string, required), source (string, optional), description (string, optional), optional package and transport overrides, plus optional DOMA/DTEL metadata fields. A FUNC entry also accepts group, processingType, updateTaskKind, and structured parameters; group may instead be supplied once at the top level when all FUNC entries share it. Item-level package and transport override the top-level values for ordinary objects. A contained FUNC always inherits its FUGR package, so omit its package or use the exact inherited value as an assertion.
If any object fails, processing stops and the response reports which objects succeeded and which failed. AFF metadata validation runs automatically for supported types (CLAS, INTF, PROG, DDLS, BDEF, SRVD, SRVB) — invalid metadata is rejected before hitting SAP.
Deferred activation for interdependent objects (activateAtEnd: true): By default, each object is created → source written → activated, in order. This works for linear dependency chains but fails when siblings cross-reference each other (e.g. composition-linked DDLS where the parent's composition [0..*] of ZR_CHILD references a not-yet-active child, or a RAP behavior stack where the BDEF refers to a draft SRVD). Set activateAtEnd: true to defer activation: ARC-1 writes inactive drafts for every object then issues one terminal activateBatch call. SAP's activator sees the whole graph at once and resolves cross-references internally. Partial-failure semantics are unchanged — a write-phase failure still breaks the loop, and the terminal batch-activate runs only over the already-written subset.
RAP handler scaffolding:
scaffold_rap_handlers derives required behavior-pool METHODS ... FOR ... signatures from an interface BDEF, computes missing signatures, and can optionally create missing local handler skeletons plus inject declarations and empty METHOD ... ENDMETHOD stubs into the behavior pool class:
- Scans class sections from
source/main,includes/definitions, andincludes/implementations - In
autoApply=true, creates missingCLASS lhc_<alias> DEFINITION INHERITING FROM cl_abap_behavior_handlershells inincludes/definitionsand matching implementation shells inincludes/implementations - Supports dry-run listing (
autoApply=false, default) and write-back mode (autoApply=true) - Helps recover from generic behavior-pool save errors by generating exact signatures for actions/determinations/validations/authorization handlers
SAPWrite(action="batch_create", package="ZDEV", transport="K900123", objects=[
{type:"TABL", name:"ZTRAVEL", source:"define table ztravel {...}"},
{type:"DDLS", name:"ZI_TRAVEL", source:"define root view..."},
{type:"DCLS", name:"ZI_TRAVEL_DCL", source:"define role..."},
{type:"BDEF", name:"ZI_TRAVEL", source:"managed implementation..."},
{type:"SRVD", name:"ZSD_TRAVEL", source:"define service..."},
{type:"CLAS", name:"ZBP_I_TRAVEL", source:"CLASS zbp_i_travel..."},
{type:"SRVB", name:"ZSB_TRAVEL_O4", serviceDefinition:"ZSD_TRAVEL", category:"0"}
])
SAPWrite(action="batch_create", objects=[
{type:"TABL", name:"ZTRAVEL", package:"ZDEV", transport:"K900123", source:"define table ztravel {...}"},
{type:"DDLS", name:"ZI_TRAVEL", package:"ZDEV", transport:"K900123", source:"define root view..."}
])
SAPWrite(action="create", type="TABL", name="ZTRAVEL", package="$TMP",
source="@EndUserText.label : 'Travel'\ndefine table ztravel {\n key client : abap.clnt;\n key travel_id : abap.numc(8);\n description : abap.char(256);\n}")
SAPWrite(action="create", type="DOMA", name="ZSTATUS", package="$TMP",
dataType="CHAR", length=1,
fixedValues=[{low:"A",description:"Active"},{low:"I",description:"Inactive"}])
SAPWrite(action="create", type="DTEL", name="ZSTATUS", package="$TMP",
typeKind="domain", typeName="ZSTATUS",
shortLabel="Status", mediumLabel="Order Status")
SAPWrite(action="create", type="SRVB", name="ZSB_TRAVEL_O4", package="$TMP",
serviceDefinition="ZSD_TRAVEL", category="0")
SAPWrite(action="update", type="CLAS", name="ZBP_I_TRAVELREQ",
include="implementations",
source="CLASS lhc_travel IMPLEMENTATION.\nENDCLASS.")
SAPWrite(action="scaffold_rap_handlers", type="CLAS", name="ZBP_I_TRAVELREQ",
bdefName="ZI_TRAVELREQ", autoApply=true)
# One-shot RAP behavior pool: discover BDEF + scaffold + activate in one call
SAPWrite(action="generate_behavior_implementation", type="CLAS", name="ZBP_DM_PROJECT")
# Same, with preview-only mode (returns the plan, does not write)
SAPWrite(action="generate_behavior_implementation", type="CLAS", name="ZBP_DM_PROJECT",
dryRun=true, activate=false)
generate_behavior_implementation is the reliable equivalent of Eclipse ADT's "Generate Behavior Implementation" Cmd+1 quickfix. Auto-discovers the BDEF via the class metadata's <class:rootEntityRef> element, cross-validates that MAIN's FOR BEHAVIOR OF <bdef> and the BDEF's managed implementation in class <class> agree, scaffolds every required handler (creating missing lhc_<alias> skeletons), writes CCDEF + CCIMP under one stateful lock, and (by default) activates the class. Avoids the broken /sap/bc/adt/quickfixes/proposals/.../create_class_implementation server endpoint (HTTP 500 on a4h regardless of payload, verified live during PR-C research 2026-05-10).
Transport behavior:
updateanddelete: ARC-1 automatically reuses the correction number from the SAP object lock when no explicittransportis provided. This means writes to transportable objects often succeed without manually specifying a transport.createandbatch_create: ARC-1 performs a transport pre-flight check for non-$TMPpackages when no transport is provided. This calls the SAP transport checks endpoint to determine whether a transport number is required:- If the object is already locked in a transport, ARC-1 auto-uses that transport.
- If the package is local (e.g.,
$TMP), no transport is needed — creation proceeds. - If a transport IS required but none was provided, ARC-1 returns an actionable error message listing existing transports and guiding the caller to use
SAPTransport(action="list")orSAPTransport(action="create")first. - If the pre-flight check fails (older system, permissions), ARC-1 proceeds and lets SAP handle the error.
Note: Not available by default (read-only mode). Enable with SAP_ALLOW_WRITES=true / --allow-writes=true. Write access is restricted to package $TMP by default; to write to other packages, set SAP_ALLOWED_PACKAGES='$TMP,Z*' (quote in shell so $TMP isn't expanded).
Procedural unit surgery¶
Issue #558. On-prem action="edit_unit" replaces one named FORM…ENDFORM or MODULE…ENDMODULE block in a PROG or INCL without making the caller re-send the full program. ARC-1 reads the latest active or inactive-draft source directly from SAP, finds the block with abaplint's structure tree, validates that the replacement has the same kind and name, splices it, then uses the normal package gate and lock/modify/unlock write path.
Pass the complete replacement block so multi-line FORM signatures and MODULE direction (INPUT/OUTPUT) remain explicit. The action is case-insensitive by unit name, preserves CRLF source files, leaves sibling units untouched, and does not auto-activate. Run SAPActivate afterwards. Function-group structural includes are supported with type="INCL", group="<FUGR>"; activate those with the same type, name, and group so ARC-1 addresses the structural include directly on every supported release.
{
"action": "edit_unit",
"type": "PROG",
"name": "ZPROG_ORDERS",
"unit": "PROCESS_ORDERS",
"source": "FORM process_orders USING iv_force TYPE abap_bool.\n \" new implementation\nENDFORM.",
"transport": "DEVK900001"
}
Event blocks such as START-OF-SELECTION and AT SELECTION-SCREEN are intentionally unsupported: abaplint does not expose them as bounded structure nodes, so name-based replacement cannot provide the same safety guarantee. FUNC is also out of scope because each function module already has a dedicated /source/main resource containing only that function module.
Class-section surgery¶
Issue #303. Four token-efficient SAPWrite actions for editing a global ABAP class without re-sending the full /source/main body. All require type=CLAS and use SAP's existing /sap/bc/adt/oo/classes/{name}/objectstructure endpoint to locate the precise line ranges to splice — no client-side ABAP parsing of the existing source is needed.
Backing pattern for main-source surgery: GET /objectstructure → fetch active or inactive-draft /source/main → splice → PUT under lock → no auto-activate. Caller runs SAPActivate next. For edit_class_definition include=..., ARC-1 whole-replaces the class-local include directly and auto-initializes a missing include under the same parent class lock before the PUT.
action="edit_class_definition" — replace the DEFINITION block whole¶
Without include=, send only the new global CLASS … DEFINITION … ENDCLASS. block (typical ~10–80 lines for a 20-method class). ARC-1 fetches the existing /source/main, splices the new DEFINITION over the existing one, and PUTs back. The IMPLEMENTATION block is preserved verbatim.
With include=definitions|implementations|macros|testclasses, send the full replacement body for that local include. For ABAP Unit tests, target include="testclasses" and write local ltc_* classes; ARC-1 creates the missing CCAU include automatically on first write.
Refuse-policy. Before PUT, ARC-1 diffs the new DEFINITION against the current class structure. If the diff would produce a non-activatable draft, the call is refused with a structured error pointing at the right tool:
- Added concrete method without a matching
METHOD …. ENDMETHOD.block in IMPLEMENTATION → "useadd_method". - Removed method that still has an orphan METHOD/ENDMETHOD block in IMPLEMENTATION → "use
delete_method".
Exempted from the symmetry check (no IMPL needed): ABSTRACT METHODS, EVENTS, INTERFACES, ALIASES. For include= writes (CCDEF), the refuse-policy is skipped — cross-include validation is not performed; rely on SAPActivate to catch breaks.
// Drop FINAL from a class without touching any method
{
"action": "edit_class_definition",
"type": "CLAS",
"name": "ZCL_ORDER",
"source": "CLASS zcl_order DEFINITION PUBLIC CREATE PUBLIC.\n PUBLIC SECTION.\n METHODS process RETURNING VALUE(r) TYPE abap_bool.\n PRIVATE SECTION.\n DATA mv_id TYPE string.\nENDCLASS."
}
action="add_method" — atomic DEFINITION + IMPLEMENTATION insert¶
Insert a METHODS clause AND an empty METHOD <name>. ENDMETHOD. stub in one PUT. Default target is visibility=public. The target section header must already exist; if missing, ARC-1 refuses with a hint to use edit_class_definition to add the section first.
{
"action": "add_method",
"type": "CLAS",
"name": "ZCL_ORDER",
"method": "METHODS greet IMPORTING who TYPE string RETURNING VALUE(r) TYPE string.",
"visibility": "public"
}
// → inserts METHODS greet ... in PUBLIC SECTION + empty METHOD greet. ENDMETHOD. in IMPLEMENTATION
Pass abstract: true to skip the IMPLEMENTATION stub (for METHODS x ABSTRACT. in an abstract class).
action="edit_method_signature" — replace one METHODS clause¶
One range replacement on a method's declaration. The IMPLEMENTATION block is untouched — any body incompatibility surfaces at SAPActivate, same as today's edit_method contract.
{
"action": "edit_method_signature",
"type": "CLAS",
"name": "ZCL_ORDER",
"method": "process",
"source": " METHODS process IMPORTING force TYPE abap_bool DEFAULT abap_false RETURNING VALUE(r) TYPE abap_bool."
}
action="delete_method" — atomic DEFINITION + IMPLEMENTATION remove¶
Drops both the METHODS clause and the METHOD…ENDMETHOD body in one PUT. ABSTRACT methods (no IMPL) have only the DEFINITION line removed.
⚠️ Destructive — discards the method body. Do not use
delete_method+add_methodto change a method's visibility: that recreates an empty stub and loses the implementation. Usechange_method_visibilityinstead, which moves the declaration while leaving the body untouched.
action="change_method_visibility" — move a method between sections (body preserved)¶
Moves a method's METHODS clause from its current visibility section to a target section (public / protected / private). Touches the DEFINITION only — the IMPLEMENTATION block (the method body) is preserved verbatim. This is the safe, token-efficient way to change visibility: send the method name + target section instead of re-sending the whole DEFINITION (edit_class_definition), and without the data loss of delete_method + add_method.
- Idempotent: if the method is already in the target section, it's a no-op (no write).
- The target section header must already exist; if not, ARC-1 refuses with a hint to add it via
edit_class_definitionfirst.
{
"action": "change_method_visibility",
"type": "CLAS",
"name": "ZCL_ORDER",
"method": "process",
"visibility": "private"
}
// → METHODS process … clause moves from its current section to PRIVATE SECTION;
// METHOD process. … ENDMETHOD. body in IMPLEMENTATION is untouched.
Cross-release notes¶
Verified live on a4h (S/4HANA 2023, kernel 7.58) end-to-end. The underlying /objectstructure endpoint also works on NW 7.50 SP02 (reads verified); on that release methods are split across CLAS/OO (def) + CLAS/OM (impl) elements and merged by name in the parser. Writes on the un-patched NW 7.50 dev edition can trip SAP Note 2727890 "ADT: fix unstable adt lock handle" — a system-level bug affecting every ADT write, not specific to this feature; ARC-1 detects the 423 status and emits a hint.
Class text symbols¶
Read and write a global class's text symbols (Textsymbole / class text elements — 'Text'(001) literals) via the ADT textelements service.
SAPRead(type="CLAS", name="ZCL_ORDER", include="text_symbols") — read the maintained text pool
SAPWrite(action="edit_text_symbols", type="CLAS", name="ZCL_ORDER",
source="@MaxLength:20\n001=Order\n\n@MaxLength:30\n002=Order created\n")
- Body format: one
@MaxLength:NNline per symbol, thenNNN=text; symbols are blank-line separated. A shared/missing@MaxLengthis rejected (406 "Text elements contain errors"). - Immediately active — no
SAPActivateneeded. Defining the referenced symbols is what clears the ATC finding "Text symbol NNN not defined" that a bare'Text'(001)literal otherwise leaves behind. - On-prem only, discovery-gated. The service is present on SAP_BASIS ≥ 7.51 (verified on 758 + 816) and absent on NW 7.50 — ARC-1 returns a clean "textelements service not available" error there.
- Scope: text symbols only. Selection texts are a program selection-screen concept — a class has none, so
source/selectionsis always empty and un-writable (SAP406); program/function-group text elements are a planned follow-up.
Verified live end-to-end on a4h (758): create a $TMP class referencing 'Hi'(001) → edit_text_symbols → read back → SAPActivate clean.
SAPActivate¶
Activate (publish) ABAP objects. Supports single object or batch activation.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | No | Object name (for single activation) |
type |
string | No | Object type (PROG, CLAS, DDLS, DDLX, BDEF, SRVD, SRVB, etc.) |
group |
string | No | Parent function group for FUNC or a function-group structural INCL. May also be set per batch item. |
preaudit |
boolean | No | Request pre-activation audit from SAP (default: true). Set false to skip pre-audit for faster activation. |
objects |
array | No | For batch: array of {type, name, group?} objects to activate together |
Use batch activation for RAP stacks where objects depend on each other (DDLS, BDEF, SRVD, DDLX, SRVB must be activated together). Batch responses include per-object status (active, warning, error) with attached messages, so failed members can be retried selectively.
For failed DDLS activation, ARC-1 appends CDS dependency impact buckets and a concrete batch re-activation template derived from where-used results.
Examples:
SAPActivate(type="CLAS", name="ZCL_ORDER")
SAPActivate(type="INCL", name="LZFGTOP", group="ZFG")
SAPActivate(objects=[{type:"DDLS",name:"ZI_TRAVEL"},{type:"BDEF",name:"ZI_TRAVEL"},{type:"SRVD",name:"ZSD_TRAVEL"}])
Note: Not available by default (read-only mode). Enable with SAP_ALLOW_WRITES=true / --allow-writes=true.
SAPNavigate¶
Navigate code: find definitions, references (where-used), code completion, and class hierarchy.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | definition, references, completion, or hierarchy |
uri |
string | No | Source URI of the object. Optional for references if type+name are provided. |
type |
string | No | Object type (PROG, CLAS, INTF, FUNC, etc.) — alternative to uri for references. |
name |
string | No | Object name — alternative to uri for references. |
objectType |
string | No | For references: keep only results of this ADT type, slash format (CLAS/OC, PROG/P, FUGR/FF). A bare prefix (CLAS) matches every subtype. Applied client-side. |
maxResults |
number | No | For references: max entries (default 100, max 1000). total counts every match of the filter. |
line |
number | No | Line number (1-based) |
column |
number | No | Column number (1-based) |
source |
string | No | Current source code |
References action (Where-Used): Uses the full scope-based Where-Used API, returning detailed results with package info. Falls back to the simpler reference lookup on older SAP systems that don't support the scope endpoint.
Returns a paged envelope — {total, shown, truncated, hint?, references} — because where-used is
unbounded: CL_ABAP_TYPEDESCR has 6,644 references (~968K tokens, several times a context window).
total is the number of matches, not the page length, so a capped page still reports the real
blast radius.
Paging and objectType filtering are both client-side, and deliberately so: SAP's
usageReferences endpoint declares only {?uri} and ignores every limit or filter we can send
(verified live across nine request variants, all byte-identical). The full set therefore still
crosses the wire — this bounds what reaches the model, not what SAP computes.
Hierarchy action: Returns the class inheritance chain via SEOMETAREL: superclass (or null), implemented interfaces, and direct subclasses. Requires name parameter (class name). It needs either table preview (SAP_ALLOW_DATA_PREVIEW=true + data scope) or freestyle SQL (SAP_ALLOW_FREE_SQL=true + sql scope). ARC-1 uses SQL when available and falls back to named table preview.
Examples:
SAPNavigate(action="definition", uri="/sap/bc/adt/programs/programs/ztest", line=10, column=5)
SAPNavigate(action="references", uri="/sap/bc/adt/oo/classes/zcl_order")
SAPNavigate(action="references", type="CLAS", name="ZCL_ORDER")
SAPNavigate(action="references", type="CLAS", name="ZCL_ORDER", objectType="PROG/P")
SAPNavigate(action="completion", uri="/sap/bc/adt/programs/programs/ztest", line=10, column=15, source="...")
SAPNavigate(action="hierarchy", name="ZCL_ORDER")
SAPQuery¶
Execute ABAP SQL queries against SAP tables.
Self-correcting errors. An unknown table yields a "Did you mean …?" suggestion; an unknown column (here or in
SAPRead type=TABLE_QUERY) yields the table's actual column list (Unknown column "X" on T000. Available columns: MANDT, MTEXT, …), so the agent retries in one shot. Best-effort: if column discovery is unavailable (e.g. thedatapreviewendpoint is unbound on older NW 7.50 SPs), the original error is returned unchanged.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
sql |
string | Yes | ABAP SQL SELECT statement |
maxRows |
number | No | Maximum rows (default 100) |
Important: Uses the ADT freestyle SQL endpoint (/sap/bc/adt/datapreview/freestyle) with ABAP SQL syntax, NOT standard SQL:
- Use alias~field for qualified fields (not alias.field; a dot ends the ABAP statement)
- Use ASCENDING/DESCENDING (not ASC/DESC)
- Use maxRows parameter (not LIMIT)
- GROUP BY, COUNT(*), WHERE all work
- ABAP SQL aggregate rule applies: non-aggregated selected fields must be listed in GROUP BY
JOINs, aggregates, and subqueries are supported. For a plain projection SELECT, ARC-1 automatically chunks the longest literal IN (...) list—even when the query has several IN clauses—and merges the rows. Queries with ORDER BY, GROUP BY, HAVING, DISTINCT, UNION, or aggregates are sent whole because concatenating per-chunk results would change their semantics. If a backend rejects a long list in one of those queries, split the list manually, union the results, and re-sort client-side when needed.
See: SAPQuery Freestyle Capability Matrix
Examples:
SAPQuery(sql="SELECT carrid, COUNT(*) as cnt FROM sflight GROUP BY carrid ORDER BY cnt DESCENDING")
SAPQuery(sql="SELECT * FROM mara WHERE matnr LIKE 'Z%'", maxRows=50)
Note: Not available by default (free SQL blocked). Enable with SAP_ALLOW_FREE_SQL=true / --allow-free-sql=true. User also needs the sql scope (or API-key profile viewer-sql/developer-sql/admin).
SAPTransport¶
Manage CTS transport requests (SE09/SE10 equivalent): list, get details, create, release, delete, reassign owner, recursive release, check transport requirements, and object transport history (reverse lookup). create uses the ADT CreateCorrectionRequest endpoint, which works on both NetWeaver 7.50+ and S/4HANA.
In multi-target v1, only the read-only list, get, check, and history actions are listed and
accepted. Transport mutations and topology actions remain structurally unavailable.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | list, get, create, release, delete, remove_object, reassign, release_recursive, check, or history |
id |
string | No | Transport request ID, e.g. A4HK900123 (for get/release/delete/remove_object/reassign/release_recursive) |
description |
string | No | Transport description text (required for create) |
name |
string | No | Object name (for check/history/remove_object actions, e.g. ZCL_ORDER) |
package |
string | No | Package name. For create: optional — defaults to $TMP, pass an explicit package to influence the transport route. For check: required. |
user |
string | No | SAP username to filter by (for list). Defaults to the current SAP user. Use * to list all users. |
status |
string | No | Transport status filter (for list). D=modifiable (default), R=released, *=all statuses. |
type |
string | No | Object type for check/history/remove_object actions (PROG, CLAS, DDLS, etc.). For remove_object it is the CTS/E071 object type exactly as shown by get (e.g. PROG, DEVC). Not used by create — the SAP backend infers transport type (K/W/T) from the package's TADIR route on the CreateCorrectionRequest endpoint. |
pgmid |
string | No | Program ID for remove_object: R3TR (whole object) or LIMU (sub-object). Required for remove_object — the object type alone does not determine pgmid. |
owner |
string | No | New owner SAP username (required for reassign) |
recursive |
boolean | No | Apply recursively to child tasks (for delete/reassign). release_recursive always recurses. |
summary |
boolean | No | For list only. Default true — headers-only: omits each transport's (and task's) objects[], keeping id/description/owner/status/target plus an objectCount. Pass false for full object lists (~5x larger). |
Actions:
list— List transport requests. Defaults to current user, modifiable (status D), all types (Workbench, Customizing, Transport of Copies). Returns a paged envelope{total, shown, truncated, transports}—totalis the full backlog, so a capped page still reports it. Summarised by default (object lists dropped,objectCountkept): scan cheaply, thengetthe one you want in full; passsummary=falsefor the object lists. Paged atmaxResults(default 50, max 1000). Live: 55 requests went 104 KB / ~26K tokens → 23 KB / ~5.7K tokens.get— Get transport details including tasks and objects.create— Create a new transport request. Requiresdescription. Optionalpackage(defaults to$TMP— pass an explicit package to influence the transport route, which determines K/W/T type). Uses the ADTCreateCorrectionRequestendpoint (POST /sap/bc/adt/cts/transports); legacy NW 7.50 systems are supported.release— Release a single transport or task.delete— Delete a transport. Userecursive=trueto delete tasks first.remove_object— Remove a single object from a request while keeping the request (the SE09/SE10 "remove from request" operation). Requires the full CTS object keypgmid+type+name(the object type alone does not determinepgmid— e.g.COMMis valid under bothR3OBandLIMU). ARC-1 resolves the entry from the request's object list and removes it via the ADTremoveobjectoperation; the object itself is not deleted. Functional on SAP_BASIS 7.58/8.16; on NW 7.5x the backend ignoresremoveobject(HTTP 400) — clean such requests in SE09/SE10.reassign— Change transport owner. Requiresowner. Userecursive=truefor tasks too.release_recursive— Release all unreleased tasks first, then the transport itself.check— Check if a transport number is required for creating an object in a specific package. Requirestype,name, andpackage. Returns whether transport recording is required, whether the package is local, existing transports, and any locked transport. Does NOT require--allow-transport-writes— this is a read-only pre-flight check.history— Reverse lookup: given an object (type+name), list the transport requests that reference it. Returns the locked transport (if any), all related transports, and candidate transports for assignment. Read-only; does NOT require--allow-transport-writes.
Check action output:
{
"package": "ZDEV",
"transportRequired": true,
"isLocal": false,
"deliveryUnit": "HOME",
"existingTransports": [
{ "id": "A4HK900123", "description": "My transport", "owner": "DEVELOPER" }
],
"summary": "Package \"ZDEV\" requires a transport for object creation."
}
History action output:
{
"object": { "type": "CLAS", "name": "ZCL_ORDER", "uri": "/sap/bc/adt/oo/classes/zcl_order" },
"lockedTransport": "A4HK900123",
"relatedTransports": [
{ "id": "A4HK900123", "description": "", "owner": "", "status": "D" }
],
"candidateTransports": [
{ "id": "A4HK900124", "description": "Refactor", "owner": "DEVELOPER" }
],
"summary": "Object ZCL_ORDER is locked in transport A4HK900123."
}
List defaults: Without parameters, list returns modifiable transports (status D) for the current SAP user, across all transport types (Workbench, Customizing, Transport of Copies). Query params follow sapcli's workbench_params() pattern (requestType=KWT, requestStatus).
Protocol compatibility: ARC-1 uses startup ADT service discovery (/sap/bc/adt/discovery) to proactively select endpoint MIME types, with endpoint-specific CTS media types and a one-retry 406/415 fallback as defense-in-depth.
Note: Transport mutations (create, release, release_recursive, reassign, delete, remove_object) require write + transports scopes and both SAP_ALLOW_WRITES=true and SAP_ALLOW_TRANSPORT_WRITES=true. list, get, check, and history are read actions and work without --allow-transport-writes.
SAPGit¶
Git-based ABAP repository workflows with backend auto-selection: gCTS is preferred when available, otherwise ARC-1 uses the abapGit ADT bridge.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | list_repos, whoami, config, branches, external_info, history, objects, check, stage, clone, pull, push, commit, switch_branch, create_branch, unlink |
backend |
string | No | Optional backend override: gcts or abapgit |
repoId |
string | No | Repository ID/key (required by most repo-scoped actions) |
url |
string | No | Remote Git URL (required for clone, and for abapGit external_info) |
branch |
string | No | Branch name (for switch/create branch) |
package |
string | No | ABAP package (required for clone/create on package-bound backends) |
transport |
string | No | Transport request (backend-dependent) |
commit |
string | No | Commit SHA (for gCTS pull by commit) |
message |
string | Yes for commit/push |
Commit message (gCTS commit and abapGit push) |
objects |
array | No | Commit/staging object list ([{type,name}]). For abapGit push it selects which changed objects to commit; omit to push every local change |
user |
string | No | Remote Git username |
password |
string | No | Remote Git password |
token |
string | No | Remote Git token. gCTS takes it as-is; abapGit sends it as basic auth with user x-access-token (GitHub convention) unless user is also given |
limit |
number | No | Limit for history queries (gCTS) |
Backend support matrix:
- Both backends:
list_repos,clone,pull,switch_branch,create_branch,unlink - gCTS only:
whoami,config,branches,history,objects,commit - abapGit only:
external_info,check,stage,push
Safety and scope rules:
- Read actions require
readscope (HTTP auth mode). - Write actions (
clone,pull,push,commit,stage,switch_branch,create_branch,unlink) requirewritescope. - All write actions are blocked unless
--allow-git-writes/SAP_ALLOW_GIT_WRITES=trueis set. - Package-bound create/clone operations must pass the configured package allowlist.
abapGit private repositories: pass user + password, or just token. ARC-1 forwards them to the
bridge on every remote-touching call — external_info, clone, pull, check, stage, push,
switch_branch, create_branch — as the Username / base64 Password headers the abapGit ADT backend
reads. They are request-scoped: never stored, never logged (the Password header is redacted).
abapGit push stages first, then commits the objects you select: ARC-1 calls the stage endpoint, keeps
the objects (with their file lists) that match objects, and sends them back with your message. Author
and committer come from the git user abapGit has stored for the repo, so no identity parameters are needed.
A push with no matching local change is reported as a no-op instead of an empty commit.
Examples:
SAPGit(action="list_repos")
SAPGit(action="whoami", backend="gcts")
SAPGit(action="config", backend="gcts")
SAPGit(action="history", backend="gcts", repoId="ZARC1", limit=20)
SAPGit(action="external_info", backend="abapgit", url="https://github.com/abapGit-tests/CLAS.git")
SAPGit(action="switch_branch", repoId="000000000006", branch="main", backend="abapgit")
SAPGit(action="clone", backend="abapgit", package="$TMP", url="https://github.com/org/repo.git")
SAPGit(action="clone", backend="abapgit", package="$TMP", url="https://github.com/org/private.git", token="ghp_…")
SAPGit(action="stage", backend="abapgit", repoId="000000000001")
SAPGit(action="push", backend="abapgit", repoId="000000000001", message="Add order validation")
SAPContext¶
Get context-first understanding for an ABAP object, or look up reverse dependencies (who uses a given object).
Use this before SAPRead when the user asks what an existing class, interface, program, function module, or CDS view does, or before drafting a spec/change/review. action="deps" prepends the object's Knowledge Transfer Document (SKTD/KTD) when one exists, then returns compressed dependency contracts. Use SAPRead after that only when you need exact source, method-level detail, grep output, drafts, revisions, or metadata.
SAPContext has three modes controlled by the action parameter:
Quick decision rule:
- "What breaks if I change <CDS view>?" / "Who consumes I_*?" / "Impact of <DDLS>" → action="impact"
- "What does <object> do?" / "Explain <object>" / spec, review, or dependency context before editing → action="deps" (default)
- "Who calls <object>?" → action="usages" (live SAP where-used)
Do not hand-roll CDS impact analysis by querying
DDDDLSRC,ACMDCLSRC,DDLXSRC_SRC, orSRVDSRC_SRCviaSAPQuery. Those text-scans produce substring-match noise and package group nodes.action="impact"uses SAP's where-used index and returns deduplicated, RAP-classified results.
action="deps" (default) — Dependency context¶
Returns the target object's KTD first when available, followed by only the public API contracts (method signatures, interface definitions, type declarations) of all objects that the target depends on — NOT the full source code. Typical compression: 7-30x fewer tokens.
What gets extracted per dependency:
- Classes: CLASS DEFINITION with PUBLIC SECTION only. PROTECTED, PRIVATE sections and CLASS IMPLEMENTATION are stripped.
- Interfaces: Full interface definition (interfaces are already public contracts).
- Function modules: FUNCTION signature block only (IMPORTING/EXPORTING parameters). Function body is stripped.
Filtering: SAP standard objects (CL_ABAP_*, IF_ABAP_*, CX_SY_*) are excluded by default. Custom objects (Z*, Y*) are prioritized in the output.
Dependency detection: Uses @abaplint/core AST parsing to find TYPE REF TO, NEW, CAST, INHERITING FROM, INTERFACES, CALL FUNCTION, RAISING, CATCH, and static method calls (=>).
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | No | "deps" (default), "usages", "impact", or "structure" |
type |
string | Yes (for deps/structure), optional for impact/usages | Object type: CLAS, INTF, PROG, FUNC, DDLS, TABL |
name |
string | Yes | Object name (e.g., ZCL_ORDER) |
source |
string | No | Provide source directly instead of fetching from SAP |
includeKtd |
boolean | No | Only for action="deps". Defaults to true; prepends the object's KTD (SKTD/KTD) when one exists. Set false to skip the KTD lookup. Ignored when source is supplied. |
group |
string | No | Required for FUNC type. The function group name. |
maxDeps |
number | No | Maximum dependencies to resolve (default 20) |
depth |
number | No | Dependency depth: 1 = direct only (default), 2 = deps of deps, 3 = max |
includeIndirect |
boolean | No | Only for action="impact" (DDLS): include indirect downstream where-used entries (default false) |
siblingCheck |
boolean | No | Only for action="impact": run sibling metadata-extension consistency analysis (default true) |
siblingMaxCandidates |
number | No | Only for action="impact": max sibling DDLS candidates to compare (default 4, hard cap 10) |
Examples:
SAPContext(type="CLAS", name="ZCL_ORDER")
SAPContext(type="CLAS", name="ZCL_ORDER", depth=2, maxDeps=10)
SAPContext(type="INTF", name="ZIF_ORDER", source="<already fetched source>")
SAPContext(action="deps", type="CLAS", name="ZCL_ORDER")
SAPContext(action="structure", type="TABL", name="BAPIRET2")
Output format:
* === Knowledge Transfer Document for ZCL_ORDER ===
# ZCL_ORDER
Business intent and object notes from the KTD.
* === Dependency context for ZCL_ORDER (3 deps resolved) ===
* --- ZIF_ORDER (intf, 4 methods) ---
INTERFACE zif_order PUBLIC.
METHODS create IMPORTING order TYPE t_order.
...
ENDINTERFACE.
* --- ZCL_ITEM (clas, 3 methods) ---
CLASS zcl_item DEFINITION PUBLIC.
PUBLIC SECTION.
METHODS get_price RETURNING VALUE(result) TYPE p.
...
ENDCLASS.
* Stats: 5 deps found, 3 resolved, 0 failed, 25 lines
If the object has no KTD or the backend returns 404/410 for the KTD document, ARC-1 silently omits the KTD section and still returns the dependency context. Other KTD read errors are surfaced normally.
Cache indicator: When the dependency graph is served from the hash-keyed dep-graph cache (no further ADT calls beyond the source revalidation), the header changes to:
The [cached] label here is for dependency graph hits (hash-keyed, naturally correct without server validation). It is distinct from [cached:revalidated] which appears on SAPRead source responses after SAP confirms freshness via 304 Not Modified. See Caching System → Source freshness for details.
action="structure" — DDIC includes + append structures (TABL only)¶
Returns a JSON tree for a DDIC structure or transparent table. ARC-1 parses embedded includes from the TABL source (include <name>;, named includes, and classic .INCLUDE) and resolves append/extension structures through ADT where-used. Append candidates are only returned after ARC-1 reads the candidate source and confirms it contains extend type <base> with; .APPEND is not parsed from the base source because ADT does not emit append structures there.
Example:
{
"name": "ZMCP_SHR_STRU",
"type": "TABL",
"includeExtensions": true,
"tree": {
"structure": "ZMCP_SHR_STRU",
"attribute": null,
"kind": "root",
"children": [
{ "structure": "ZMCP_SHR_STRU_INC", "attribute": null, "kind": "include", "children": [] },
{ "structure": "ZOK_S_APPEND", "attribute": null, "kind": "append", "children": [] }
]
},
"summary": {
"totalNodes": 3,
"includes": 1,
"appends": 1,
"cyclic": 0,
"unresolved": 0,
"truncated": 0
}
}
action="impact" — CDS upstream + downstream impact (DDLS only)¶
Returns a single JSON payload with:
- upstream dependencies from CDS AST extraction (tables, views, associations, compositions)
- downstream where-used consumers classified into RAP-relevant buckets (projectionViews, bdefs, serviceDefinitions, serviceBindings, accessControls, metadataExtensions, abapConsumers, documentation, etc.)
- consistencyHints (additive): human-readable hints when sibling DDLS variants in the same package have asymmetric DDLX coverage
- siblingExtensionAnalysis (additive): structured details about sibling candidate filtering and metadata-extension counts
Use this to answer: "If I change this CDS view, what breaks?"
Example:
SAPContext(action="impact", type="DDLS", name="ZI_ARC1_I33_ROOT")
SAPContext(action="impact", type="DDLS", name="ZI_ARC1_I33_ROOT", includeIndirect=true)
SAPContext(action="impact", type="DDLS", name="ZI_ARC1_I33_ROOT", siblingCheck=false)
SAPContext(action="impact", type="DDLS", name="ZI_ARC1_I33_ROOT", siblingMaxCandidates=6)
Output (shape):
{
"name": "ZI_ARC1_I33_ROOT",
"type": "DDLS",
"upstream": {
"tables": [{ "name": "ZTABL_ARC1_I33" }],
"views": [],
"associations": [],
"compositions": []
},
"downstream": {
"projectionViews": [{ "name": "ZI_ARC1_I33_PROJ", "type": "DDLS/DF" }],
"bdefs": [],
"serviceDefinitions": [],
"serviceBindings": [],
"accessControls": [],
"metadataExtensions": [],
"abapConsumers": [],
"tables": [],
"documentation": [],
"other": [],
"summary": { "total": 1, "direct": 1, "indirect": 0, "byBucket": { "projectionViews": 1 } }
},
"summary": { "upstreamCount": 1, "downstreamTotal": 1, "downstreamDirect": 1 },
"consistencyHints": [
"Possible sibling metadata-extension inconsistency: ..."
],
"siblingExtensionAnalysis": {
"stem": "ZI_ARC1_I33_ROOT",
"maxCandidates": 4,
"consideredCandidates": 2,
"checkedCandidates": [
{ "name": "ZI_ARC1_I33_ROOT2", "packageName": "ZARC1", "metadataExtensions": 1, "downstreamTotal": 3 }
]
}
}
Sibling analysis is best-effort and bounded. Any sibling-search or sibling where-used failures are returned as warnings while the primary impact result still succeeds.
action="usages" — Reverse dependency lookup¶
Queries SAP's live where-used index for objects that depend on the target (i.e., "who calls/uses this?"). The lookup uses the current caller's SAP identity and works with memory, SQLite, or no cache. SAPNavigate(action="references") uses the same live lookup but returns the navigation-oriented result directly.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | "usages" |
name |
string | Yes | Object name to look up (e.g., ZCL_ORDER, ZIF_ORDER) |
type |
string | No | Object type. Recommended when known; otherwise ARC-1 performs exact-name resolution and continues only for one unambiguous match. |
Example:
Output:
{
"name": "ZIF_ORDER",
"resolvedObject": {
"type": "INTF",
"name": "ZIF_ORDER",
"uri": "/sap/bc/adt/oo/interfaces/zif_order"
},
"usageCount": 3,
"shown": 2,
"truncated": false,
"usages": [
{ "name": "ZCL_ORDER", "type": "CLAS/OC", "uri": "/sap/bc/adt/oo/classes/zcl_order" },
{ "name": "ZCL_ORDER_EXTENDED", "type": "CLAS/OC", "uri": "/sap/bc/adt/oo/classes/zcl_order_extended" }
],
"source": "live",
"fallbackUsed": false
}
usages is paged (maxResults, default 100, max 1000) because a where-used lookup on a common
object is unbounded — CL_ABAP_TYPEDESCR returns 6,644 references. usageCount is the total
match count, not the page length (shown is the page): a capped page must never under-report the
blast radius of a change. SAPNavigate(action="references") returns the same paged envelope under
references, and SAPContext(action="impact") caps each downstream bucket while summary keeps
the complete counts.
If exact name resolution finds multiple object types, ARC-1 returns a bounded candidate list and asks for type instead of guessing.
SAPLint¶
Run local abaplint rules on ABAP source code. System-aware: auto-selects cloud or on-prem rules based on detected system type. For server-side checks (ATC, syntax check, unit tests), use SAPDiagnose instead.
In multi-target v1, only the offline lint, lint_and_fix, and list_rules actions are listed and
accepted. format and formatter-settings actions contact or modify SAP and remain unavailable.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | lint, lint_and_fix, list_rules, format, get_formatter_settings, or set_formatter_settings |
source |
string | No | ABAP source code (for lint, lint_and_fix, and format) |
name |
string | No | Object name (used for filename detection) |
indentation |
boolean | No | PrettyPrinter indentation toggle (for set_formatter_settings) |
style |
string | No | PrettyPrinter keyword style: keywordUpper, keywordLower, keywordAuto, or none (for set_formatter_settings) |
rules |
object | No | Rule overrides: { "rule_name": false } to disable, { "rule_name": { "severity": "Warning" } } to configure |
Actions:
lint— Check ABAP source for issues. Returns errors and warnings with line/column positions.lint_and_fix— Lint + auto-fix all fixable issues (keyword case, obsolete statements, etc.). Returns the fixed source code alongside remaining unfixable issues.list_rules— List all available rules with current config (preset, enabled/disabled status, severity). No source needed.format— Pretty-print ABAP source via SAP ADT PrettyPrinter using the SAP system's global formatter settings. Returns formatted source text.get_formatter_settings— Read SAP global PrettyPrinter settings (indentation + keyword style).set_formatter_settings— Update SAP global PrettyPrinter settings. Provide at least one ofindentationorstyle. Requireswritescope andSAP_ALLOW_WRITES=true.
System-Aware Presets:
The lint rules auto-configure based on the detected SAP system:
- BTP/Cloud: cloud_types (Error), strict_sql (Error), obsolete_statement (Error) — enforces ABAP Cloud constraints
- On-premise: cloud_types (disabled), obsolete_statement (Warning) — more relaxed, allows classic ABAP
Pre-Write Validation:
When --lint-before-write is enabled (default: true), SAPWrite automatically runs a strict subset of lint rules before writing to SAP. Parser errors and cloud violations block the write. Style issues (keyword case, indentation) never block writes.
Execution mode note:
lint, lint_and_fix, and list_rules run locally in ARC-1. format and *_formatter_settings actions call the SAP system (ADT PrettyPrinter endpoints).
Custom Configuration:
Use --abaplint-config /path/to/abaplint.jsonc to load custom rules. The file uses the abaplint config format:
{
// Override specific rules
"rules": {
"line_length": { "severity": "Error", "length": 80 },
"abapdoc": true, // re-enable a disabled rule
"obsolete_statement": false // disable a rule
},
// Optional: override syntax version
"syntax": { "version": "v757" }
}
Rules from the config file are merged on top of the auto-detected preset (cloud/on-prem). Per-call overrides via the rules parameter take precedence over the config file.
Response shapes:
lintreturns:[{ rule, message, line, column, endLine, endColumn, severity }]lint_and_fixreturns:{ fixedSource, appliedFixes, fixedRules, remainingIssues }— usefixedSourceas the corrected codelist_rulesreturns:{ preset, abapVersion, enabledRules, disabledRules, rules }— shows active configformatreturns: plain text (formatted ABAP source)get_formatter_settingsreturns:{ indentation, style }set_formatter_settingsreturns:{ indentation, style }(effective merged settings)
Examples:
SAPLint(action="lint", source="DATA lv_test TYPE string.\nlv_test = 'hello'.")
SAPLint(action="lint_and_fix", source="data lv_x type i.\nadd 1 to lv_x.", name="ZCL_TEST")
SAPLint(action="list_rules")
SAPLint(action="format", source="report ztest. data lv type string.")
SAPLint(action="get_formatter_settings")
SAPLint(action="set_formatter_settings", style="keywordLower")
SAPLint(action="lint", source="...", rules={"line_length": {"severity": "Error", "length": 80}})
SAPDiagnose¶
Server-side code analysis: syntax check, ABAP unit tests, ATC checks, CDS test-case scaffolding, active/inactive object state, short dumps (ST22), ABAP profiler traces, the on-prem STUSERTRACE authorization trace, an OData performance probe (sap-statistics), and CDS Show-SQL.
Multi-target v1 includes atc and unittest under the existing read scope. They do not mutate
repository objects, but they execute SAP workloads and may create transient worklists/results;
administrators can disable them with SAP_DENY_ACTIONS.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | syntax, unittest, atc, atc_variants, cds_testcases, object_state, quickfix, apply_quickfix, dumps, traces, odata_perf, authorization_trace, cds_sql, sql_trace_state, set_sql_trace_state, or sql_trace_directory |
name |
string | No | Object name (required for syntax/unittest/atc/object_state/quickfix/apply_quickfix; the CDS entity / DDLS source name for cds_testcases and cds_sql) |
url |
string | No | For odata_perf: the host-relative OData path to probe (from the Fiori app's Network tab), e.g. /sap/opu/odata4/sap/.../Entity?$filter=.... Must be a path on the SAP system ARC-1 connects to — absolute URLs are rejected. |
type |
string | No | Object type: PROG, CLAS, INTF, FUNC (required for syntax/unittest/atc/object_state/quickfix/apply_quickfix) |
coverage |
boolean | No | For unittest: also return statement/branch/procedure coverage for the object, plus methodsBelowFull (methods under 100% statement coverage, worst first), in one extra round-trip. Default false. |
source |
string | No | Current source code (required for quickfix and apply_quickfix) |
line |
number | No | Source line number (required for quickfix and apply_quickfix) |
column |
number | No | Source column number (optional for quickfix and apply_quickfix, default 0) |
proposalUri |
string | No | Quickfix proposal URI from quickfix response (required for apply_quickfix) |
proposalUserContent |
string | No | Opaque proposal state from quickfix response (required for apply_quickfix) |
id |
string | No | Dump ID (for dump detail) or Trace ID (for trace analysis) |
user |
string | No | SAP-user filter for dumps, runtime feeds, or authorization_trace |
authObject |
string | No | For authorization_trace: filter to one authorization object, for example S_TCODE |
onlyFailures |
boolean | No | For authorization_trace: return only denied checks (RC <> 0) |
maxResults |
number | No | Maximum results (default 50 for dumps/feeds, 100 for authorization_trace; safely capped) |
variant |
string | No | ATC check variant name |
sqlOn |
boolean | No | For set_sql_trace_state: true arms the ST05 SQL trace, false disarms it (combine with user to filter to one SAP user) |
analysis |
string | No | For trace detail: hitlist, statements, or dbAccesses |
Actions:
syntax— Run SAP syntax check on an object. Returns errors/warnings with line, column, and message. Important: Syntax check runs against the active (on-system) source, not proposed new source. After writing/updating an object, activate it first, then run syntax check.unittest— Run ABAP unit tests. Returns results per test class/method with status, alert messages, and execution time. Passcoverage=trueto also return the object's statement / branch / procedure coverage ({executed, total, percent}each) plusmethodsBelowFull— the methods under 100% statement coverage, worst first (the actionable "what to test next" subset the object aggregate hides) — via a second ADT round-trip to the coverage-measurement endpoint; the output becomes{tests, coverage}. Best-effort — if the coverage endpoint is unavailable the tests still return with acoverageNote.atc— Run ATC (ABAP Test Cockpit) checks. Returns findings with priority, check title, message, URI, line number, plus quickfix metadata (quickfixInfo,hasQuickfix). Optionalvariantparameter for custom check variants.atc_variants— List the ATC check variants this system offers, plus the system default variant (the oneatcuses when novariantis passed). Read-only. Thevariantparameter doubles as an optional name filter (*= all; e.g.variant="ABAP_CLOUD*"). Returns{ systemDefault, filter, count, variants: [{ name, description }] }. Use it to discover the exactvariantstring to pass toaction="atc".cds_testcases— Get SAP-suggested ABAP Unit test cases for a CDS entity (CDS Test Double Framework). Requiresname(the CDS entity / DDLS source name; notype). Returns one suggestion per testable semantic — the whole view (semanticType: "NONE"), each calculated field ("CALCULATION"+calculatedField), and"CAST"/"JOIN"/"CASE"expressions — each with a suggestedtestMethodname +description, plus ahintfor scaffolding acl_cds_test_environmenttest class. Read-only. Available on SAP_BASIS 8.16+ (ABAP Platform 2025 / S/4HANA 2025) only — discovery-gated, so older releases return a clear "needs 8.16+" message. The AI-backed test-data / test-method generation (Joule for Developers) is intentionally not exposed.object_state— Compare active and inactive source versions for one object. ForCLAS, ARC-1 checks main, definitions, implementations, macros, and testclasses includes (up to 10 parallel reads per class; sequence calls when sweeping many classes). Returns ETags, byte lengths, SHA-256 hashes, and divergence flags without returning full source. Useful for diagnosing activation failures where active and inactive class includes disagree.quickfix— Get SAP quickfix proposals for a specific source position (name,type,source,line, optionalcolumn). Returns proposal entries withuri,type,name,description,userContent.apply_quickfix— Apply one proposal (proposalUri+proposalUserContent) and return text deltas (range + replacement content). This does not write source; useSAPWriteto persist.dumps— List short dumps (ST22). Withoutid: returns recent dumps (filterable byuser,maxResults). Withid: returns full dump detail including error type, exception, program, stack trace, and formatted output.traces— List ABAP profiler traces. Withoutid: returns trace list. Withid+analysis: returns trace analysis (hitlist= call hierarchy with hit counts and timings,statements= executed statements,dbAccesses= database access details).odata_perf— Diagnose why a Fiori/OData request is slow. Passurl(the host-relative OData path from the app's Network tab); ARC-1 GETs it with?sap-statistics=trueand a wall-clock timer, then returns the server-side timing split (gwtotal,gwapp,gwappdb= DB time,gwfw/gwhub= framework,icfauth= auth) plus averdictrouting you to the dominant cost (db→ check the CDS query /cds_sql/ ST05;app→ ABAP profilertraces;framework→ metadata/first-call;auth→ ICF/DCL). Read-only GET; gated like data preview (SAP_ALLOW_DATA_PREVIEW). The OData service must be on the same SAP host ARC-1 connects to. Older releases (e.g. NW 7.50) may report only agwhubtotal without a per-component split → the verdict says so rather than guessing.authorization_trace— Read the long-term, on-prem STUSERTRACE trace fromSUAUTHVALTRC, decode positional field values throughTOBJ, and return the user, application, authorization object, result code, checked values, ABAP code location, and first-seen timestamp. Optionaluser,authObject,onlyFailures, andmaxResultsnarrow the read; entries are sorted newest-first within the capped result set. Requires thedatascope,SAP_ALLOW_DATA_PREVIEW=true, and SAP table-read authorization forSUAUTHVALTRCandTOBJ; it never needs free SQL. This is not SU53's live last-failure buffer: it contains only checks recorded whileauth/auth_user_tracewas enabled, and ARC-1 cannot toggle that profile parameter. Every response therefore reportstraceState.status="unknown"and warns that persisted rows do not prove the trace is currently active; empty responses additionally include RZ11/profile activation guidance. Verify the current value in RZ11:Nis inactive,Frecords only filters maintained in STUSERTRACE (recommended; at least one filter is required), andYrecords all users/application types. A dynamic RZ11 change lasts until restart; select Change on All Servers when all application-server instances must participate, and maintainDEFAULT.PFLthrough the approved Basis profile workflow for a persistent setting. ABAP Cloud users should use the Display Authorization Trace Fiori app.cds_sql— Show the native SQL a CDS view compiles to (ADT "Show SQL Create Statement"). Passname(the CDS DDL source / DDLS, e.g.I_CURRENCY). Returns theCREATE VIEWstatement(s) — the joins/scans behind a slow entity. Read-only. Verified on NW 7.50, S/4HANA 2023 (758), and ABAP Platform 2025 (816); on 7.50 the statement is a classic DBVIEW.sql_trace_state— Read the current ST05 trace state (SQL/buffer/enqueue/RFC/HTTP/APC/AMC/auth on-off per application server, plus the active filter). Read-only.set_sql_trace_state— Arm or disarm the ST05 SQL trace. RequiressqlOn(true= arm,false= disarm); optionaluserfilters the trace to one SAP user. Mutates server trace state → needsSAP_ALLOW_WRITES. Workflow: arm → reproduce the slow request →sql_trace_directoryfor the record-viewer link.sql_trace_directory— Return where the recorded SQL is read. ADT has no SQL-record endpoint; SAP answers/st05/trace/directorywith the Technical Monitoring Cockpit "SQL Trace Analysis" deep-link — ARC-1 returns that URL (open it in a browser; needs the/sap/bc/stmcSICF service active). Read-only. (The richer ADT-native record reader is the ABAP Cross Trace API — a planned follow-up.)
Examples:
SAPDiagnose(action="syntax", type="CLAS", name="ZCL_ORDER")
SAPDiagnose(action="unittest", type="CLAS", name="ZCL_ORDER")
SAPDiagnose(action="atc", type="PROG", name="ZTEST_REPORT", variant="DEFAULT")
SAPDiagnose(action="cds_testcases", name="I_CURRENCY") — SAP-suggested unit-test cases for a CDS view (8.16+)
SAPDiagnose(action="object_state", type="CLAS", name="ZBP_DM_PROJECT")
SAPDiagnose(action="quickfix", type="CLAS", name="ZCL_ORDER", source="<current_source>", line=42, column=1)
SAPDiagnose(action="apply_quickfix", type="CLAS", name="ZCL_ORDER", source="<current_source>", line=42, column=1, proposalUri="/sap/bc/adt/quickfixes/...", proposalUserContent="<opaque_state>")
SAPDiagnose(action="dumps")
SAPDiagnose(action="dumps", user="DEVELOPER", maxResults=10)
SAPDiagnose(action="dumps", id="20260409_123456_DUMP_ID")
SAPDiagnose(action="traces")
SAPDiagnose(action="traces", id="TRACE123", analysis="hitlist")
SAPDiagnose(action="traces", id="TRACE123", analysis="dbAccesses")
SAPDiagnose(action="odata_perf", url="/sap/opu/odata4/sap/zui_mup/.../SerialNumbers?$filter=...") — where did the time go (DB vs ABAP vs framework)
SAPDiagnose(action="authorization_trace", user="AUTH_TEST", onlyFailures=true, maxResults=20) — denied STUSERTRACE checks (on-prem; data-preview gated)
SAPDiagnose(action="cds_sql", name="I_CURRENCY") — the native SQL CREATE VIEW behind a CDS entity
SAPDiagnose(action="sql_trace_state") — is the ST05 SQL trace on? for whom?
SAPDiagnose(action="set_sql_trace_state", sqlOn=true, user="MARIAN") — arm the SQL trace for one user (needs SAP_ALLOW_WRITES)
SAPDiagnose(action="sql_trace_directory") — get SAP's SQL Trace Analysis deep-link to read the records
Quickfix Workflow¶
- Run
SAPDiagnose(action="atc" ...)orSAPDiagnose(action="syntax" ...). - Check ATC findings for
hasQuickfix: true. - Call
SAPDiagnose(action="quickfix", ...)for the relevant line/column. - Select a proposal and call
SAPDiagnose(action="apply_quickfix", ...)to receive deltas. - Apply those deltas to source and persist via
SAPWrite(action="update" | "edit_method", ...).
SAPManage¶
Probe and report SAP system capabilities, inspect the object cache state, and manage package (DEVC) lifecycle operations.
Actions:
- probe — Re-probe the SAP system now (feature probes + auth checks + ADT discovery refresh). Detects optional features.
- features — Get cached feature status from last probe (fast, no SAP round-trip).
- cache_stats — Return request-driven cache statistics: cached sources, dependency graphs, released APIs, and the per-username inactive-list session cache (inactiveListCache.userCount, inactiveListCache.totalEntries).
- create_package — Create a package (DEVC) via /sap/bc/adt/packages.
- delete_package — Delete a package via lock/delete/unlock.
- change_package — Move an existing object into a different package (DEVC reassignment).
- flp_list_catalogs — List FLP designer catalogs. The flp_* actions target the classic tile/target-mapping model, deprecated as of S/4HANA 2023 and not federated by Work Zone content exposure v2 — the successor is the Launchpad App Descriptor Item (SAPRead type=UIAD). Business catalogs are a separate model (/UI2/FLPCM_CUST) and are not managed here.
- flp_list_groups — List FLP groups (Pages) from /UI2/FLPD_CATALOG.
- flp_list_tiles — List tiles/target mappings in a catalog.
- flp_create_catalog — Create an FLP designer catalog.
- flp_create_group — Create an FLP group.
- flp_create_tile — Create a tile in an FLP catalog.
- flp_add_tile_to_group — Assign a catalog tile instance into a group.
- flp_delete_catalog — Delete an FLP designer catalog.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action |
string | Yes | probe, features, cache_stats, create_package, delete_package, change_package, flp_list_catalogs, flp_list_groups, flp_list_tiles, flp_create_catalog, flp_create_group, flp_create_tile, flp_add_tile_to_group, flp_delete_catalog |
name |
string | No | Required for create_package and delete_package (package name) |
description |
string | No | Required for create_package (package description) |
superPackage |
string | No | Optional parent package for create_package (use $TMP for local packages) |
softwareComponent |
string | No | Optional software component for create_package (default: LOCAL) |
transportLayer |
string | No | Optional transport layer for create_package |
packageType |
string | No | Optional package type for create_package: development, structure, main (default: development) |
transport |
string | No | Optional transport request ID (corrNr) for create_package/delete_package/change_package |
objectName |
string | No | Required for change_package — name of the object to move (e.g., ZCL_MY_CLASS) |
objectType |
string | No | Required for change_package — ADT object type (e.g., CLAS/OC, DDLS/DF, PROG/P) |
objectUri |
string | No | Optional for change_package — ADT URI of the object. Auto-resolved from objectName + objectType if not provided |
oldPackage |
string | No | Required for change_package — current package of the object |
newPackage |
string | No | Required for change_package — target package to move the object to |
catalogId |
string | No | Required for flp_list_tiles, flp_create_tile, flp_add_tile_to_group |
groupId |
string | No | Required for flp_create_group, flp_add_tile_to_group |
domainId |
string | No | Required for flp_create_catalog |
title |
string | No | Required for flp_create_catalog, flp_create_group |
tileInstanceId |
string | No | Required for flp_add_tile_to_group |
tile |
object | No | Required for flp_create_tile. Fields: id, title, semanticObject, semanticAction, optional icon, url, subtitle, info |
Probed features: hana, abapGit, rap, amdp, ui5, transport, ui5repo, flp. Each returns available (bool), mode (auto/on/off), message, and probedAt timestamp.
cache_stats output:
{
"enabled": true,
"sourceCount": 42,
"contractCount": 38,
"apiCount": 0,
"inactiveListCache": {
"userCount": 1,
"totalEntries": 3
}
}
| Field | Description |
|---|---|
enabled |
Whether caching is active (false if ARC1_CACHE=none) |
sourceCount |
Cached source code entries (grows as objects are read) |
contractCount |
Cached dependency graphs (grows as SAPContext(deps) is called) |
apiCount |
Released API metadata entries populated by requests |
inactiveListCache |
Aggregate user/session draft-list cache counts |
Examples:
SAPManage(action="probe") → discover system capabilities
SAPManage(action="features") → get cached results (no SAP call)
SAPManage(action="cache_stats") → check request-driven cache state
SAPManage(action="create_package", name="ZRAP_TRAVEL", description="RAP Travel Demo")
SAPManage(action="create_package", name="ZRAP_TRAVEL", description="RAP Travel Demo", superPackage="ZRAP", softwareComponent="HOME", transportLayer="HOME", packageType="development", transport="K900123")
SAPManage(action="delete_package", name="ZRAP_TRAVEL")
SAPManage(action="change_package", objectName="ZCL_MY_CLASS", objectType="CLAS/OC", oldPackage="$TMP", newPackage="Z_PRODUCTION", transport="K900123")
SAPManage(action="flp_list_catalogs")
SAPManage(action="flp_list_groups")
SAPManage(action="flp_list_tiles", catalogId="ZARC1_SALES")
SAPManage(action="flp_create_catalog", domainId="ZARC1_SALES", title="Sales Catalog")
SAPManage(action="flp_create_group", groupId="ZARC1_SALES_GRP", title="Sales Group")
SAPManage(action="flp_create_tile", catalogId="ZARC1_SALES", tile={"id":"tile_sales","title":"Sales","semanticObject":"SalesOrder","semanticAction":"display"})
SAPManage(action="flp_add_tile_to_group", groupId="ZARC1_SALES_GRP", catalogId="ZARC1_SALES", tileInstanceId="00O2TO3741QLWH4GV74AHMWQE")
Note: The probe, features, and cache_stats actions are read operations that work without --allow-writes and require only read scope in HTTP auth mode. Mutating SAPManage actions require write scope and writable safety config.