SAP COMMUNITY | SERIES: PART 2 OF 6 | SAP AI CORE | GENERATIVE AI HUB
SAP Generative AI Hub: Using the Python SDK for SAP Data Tasks
Updated March 2026: Corrected environment section — Jupyter notebooks run in SAP Business Application Studio (BAS)
Five practical SAP use cases with working Python code — across SAP AI Launchpad notebooks, local scripts, and BTP applications — using the generative-ai-hub-sdk for clean, production-ready authentication.
By Deepa Dorairaj | SAP AI Solution Architect | Part 2 of 6 | Published 2026
TL;DR: Once your Generative AI Hub is configured (see Part 1), the generative-ai-hub-sdk Python package handles OAuth token management automatically — removing the biggest friction point from direct API integration. This article covers SDK installation and configuration across three environments (AI Launchpad notebooks, local Python scripts, BTP applications), followed by five working code examples for real SAP data tasks: exception log summarization, HANA query analysis, ABAP/SQL code generation, master data classification, and structured data extraction from SAP documents.
This is Part 2 of a 6-part series on SAP Generative AI Hub. Part 1 covered the complete setup path from BTP entitlements to your first API call. If you haven't configured your AI Core instance and resource group yet, start there before continuing.
This part focuses on practical Python integration — the code patterns you'll use for real SAP workloads, across the three environments where SAP practitioners most commonly run Python against the Hub.
Environment | Best For | Key Consideration |
AI Launchpad Notebooks | Interactive development, rapid prototyping | Credentials pre-configured — fastest to start |
Local Python Script | Automation, scheduled jobs, local development | Requires .env file with service key credentials |
BTP Application | Production workloads, CAP integration, APIs | Credentials via BTP environment variables or secrets |
SDK INSTALLATION & CONFIGURATION
Why the SDK Over Direct API Calls
Part 1 showed the raw OAuth 2.0 flow using direct API calls — which is useful to understand what's happening under the hood. For any real workload, the generative-ai-hub-sdk is the better path. It handles token acquisition, token refresh, retry logic, and deployment ID resolution automatically. Your application code focuses on the task, not the authentication plumbing.
Installation
# Install the SAP Generative AI Hub SDK
pip install sap-ai-sdk-gen
# Optional but recommended — for HANA connection examples later
pip install hdbcli pandas python-dotenvConfiguration: AI Launchpad Notebooks
▶ Environment: SAP Business Application Studio (BAS) — Jupyter Notebooks
Setting Up a BAS Dev Space for Jupyter
SAP Business Application Studio is the browser-based IDE available on BTP that supports Jupyter notebooks via the built-in Jupyter and Python extensions. This is the SAP-native interactive notebook environment for Python development — not SAP AI Launchpad, which does not provide a notebook interface.
BAS is available to all BTP customers and trial users. No additional entitlement beyond BAS subscription is required to run Jupyter notebooks.
Dev Space Setup — Step by Step
Step 1 — Create a Dev Space:
Step 2 — Install pip and required packages:
Open a terminal in BAS (F1 → Open Terminal) and run:
# Install pip if not already available
curl https://bootstrap.pypa.io/get-pip.py > get-pip.py && python3 get-pip.py
echo "export PATH=/home/user/.local/bin:$PATH" >> ~/.bashrc && source ~/.bashrc
# Create a virtual environment for your project
python3 -m venv ~/.venv/genai
source ~/.venv/genai/bin/activate
# Install the SAP Generative AI Hub SDK and Jupyter kernel
pip install sap-ai-sdk-gen ipykernel hdbcli pandas python-dotenv
python -m ipykernel install --user --name genai --display-name 'GenAI Hub'Step 3 — Create the AI Core credentials file:
Create .aicore-config.json in your home directory with your AI Core service key values:
{
"AICORE_AUTH_URL": "https://<subdomain>.authentication.<region>.hana.ondemand.com",
"AICORE_CLIENT_ID": "<clientid from service key>",
"AICORE_CLIENT_SECRET": "<clientsecret from service key>",
"AICORE_BASE_URL": "<AI_API_URL from service key>",
"AICORE_RESOURCE_GROUP": "default"
}Step 4 — Create and run a notebook:
Step 5 — Verify the SDK connection in the first notebook cell:
# Verify SDK picks up credentials from .aicore-config.json
from gen_ai_hub.proxy.native.openai import OpenAI
client = OpenAI()
print('SDK connected successfully')Do not commit .aicore-config.json to any Git repository. If you clone a repository into BAS and push back to Git, add .aicore-config.json to your .gitignore before the first commit. BAS has Git integration enabled by default — credential exposure via accidental commit is a real risk.
Once your dev space is running and the venv is activated, the SDK reads .aicore-config.json automatically. All five use case examples in this article run without any additional configuration changes from the BAS notebook environment.
Persisting the Virtual Environment Across BAS Sessions
BAS dev spaces suspend after inactivity. The virtual environment persists between sessions, but you must re-activate it each time you open a new terminal:
# Re-activate venv at the start of each BAS session
source ~/.venv/genai/bin/activate
Tip: Add the activation command to your BAS dev space's shell profile (~/.bashrc) so it runs automatically when a new terminal opens: echo 'source ~/.venv/genai/bin/activate' >> ~/.bashrc
Configuration: Local Python Script
▶ Environment: Local Python Script
For local development, create a configuration file that points the SDK to your AI Core service key credentials. Store this as .aicore-config.json in your home directory or reference it via an environment variable.
environment variable.
# ~/.aicore-config.json — from your AI Core service key
{
"AICORE_AUTH_URL": "https://<your-subdomain>.authentication.<region>.hana.ondemand.com",
"AICORE_CLIENT_ID": "<clientid from service key>",
"AICORE_CLIENT_SECRET": "<clientsecret from service key>",
"AICORE_BASE_URL": "<AI_API_URL from service key>",
"AICORE_RESOURCE_GROUP": "default"
}Never commit .aicore-config.json to version control. Add it to your .gitignore immediately. For team environments, use environment variables (AICORE_AUTH_URL, AICORE_CLIENT_ID, etc.) instead of the config file — the SDK reads both patterns automatically.
Configuration: BTP Application
▶ Environment: BTP Application
In BTP applications, bind the AI Core service instance to your application. The SDK reads credentials from the VCAP_SERVICES environment variable that BTP injects automatically at runtime — no manual credential management required.
# BTP injects VCAP_SERVICES automatically when AI Core is bound
# The SDK reads it without any additional configuration
from gen_ai_hub.proxy.core.proxy_clients import get_proxy_client
# SDK auto-resolves from VCAP_SERVICES in BTP runtime
proxy_client = get_proxy_client('gen-ai-hub')Once credentials are configured for your target environment, all five use case examples below work identically across all three environments. The SDK abstracts the credential source — your application code does not change.
FIVE SAP USE CASES WITH WORKING CODE
The following examples cover five practical SAP use cases. Each uses the same SDK pattern — choose your preferred model by changing one parameter. All examples use Claude 3.5 Sonnet as the default; swap the model_name value for GPT-4o, Gemini, or Mistral as needed based on the model comparison in this week's LinkedIn post.
Use Case | What the Model Does |
Exception log summarization | Parse and summarize SAP SM21 / application error logs into structured root cause analysis |
HANA query result analysis | Interpret query output and surface anomalies, trends, or data quality issues |
ABAP / SQL / HANA code generation | Generate or explain code from natural language descriptions |
Master data classification | Tag and categorize SAP master data records against defined classification schemes |
Structured data extraction | Pull structured fields from SAP documents, change logs, or transport descriptions |
Use Case 1: Summarizing SAP Exception Logs
SAP exception logs — SM21 system logs, application error dumps, job logs — are high-volume and time-consuming to triage manually. This pattern feeds raw log text to the model and returns a structured root cause summary with recommended actions.
# Use Case 1: SAP Exception Log Summarization
from gen_ai_hub.proxy.langchain.openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
llm = ChatOpenAI(proxy_model_name='claude-3.5-sonnet')
log_text = '''
[SM21 Log Extract]
E RABAX INCLUDE: ZREPORT_DELTA_LOAD Line 847
E Runtime Error: COMPUTE_INT_PLUS_OVERFLOW
E Date: 2026-03-10 Time: 04:32:17
E Work process terminated abnormally
'''
messages = [
SystemMessage(content='''You are an SAP Basis and ABAP expert.
Analyze SAP exception logs and return:
1. Root cause (one sentence)
2. Affected component
3. Severity: Critical / High / Medium / Low
4. Recommended action
Be concise and technical.'''),
HumanMessage(content=f'Analyze this SAP log:\n{log_text}')
]
response = llm(messages)
print(response.content)Output example — Root cause: Integer overflow in delta load procedure at ZREPORT_DELTA_LOAD line 847 due to 32-bit counter exceeding maximum value. Component: ABAP Runtime. Severity: Critical. Action: Cast counter variable to BIGINT and redeploy procedure.
Use Case 2: Analyzing HANA Query Results
This pattern connects to HANA Cloud, executes a query, and passes the result set to the model for interpretation — surfacing anomalies, trends, or data quality issues that would otherwise require manual review.
# Use Case 2: HANA Query Result Analysis
import hdbcli.dbapi as hdb
import pandas as pd
from gen_ai_hub.proxy.langchain.openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
# Connect to HANA Cloud
conn = hdb.connect(
address='<your-hana-host>.hanacloud.ondemand.com',
port=443,
user='<user>',
password='<password>',
encrypt=True
)
# Run your query and load into DataFrame
query = '''
SELECT PLANT, MATERIAL, SUM(QUANTITY) AS TOTAL_QTY,
COUNT(*) AS RECORD_COUNT
FROM STOCK_OVERVIEW
GROUP BY PLANT, MATERIAL
ORDER BY TOTAL_QTY DESC
LIMIT 50
'''
df = pd.read_sql(query, conn)
# Pass result to model for analysis
llm = ChatOpenAI(proxy_model_name='claude-3.5-sonnet')
messages = [
SystemMessage(content='You are an SAP data analyst. Identify anomalies, trends, and data quality issues in SAP query results. Be specific and reference actual values from the data.'),
HumanMessage(content=f'Analyze this SAP stock query result:\n{df.to_string()}')
]
response = llm(messages)
print(response.content)Do not pass full production datasets to the model. Apply LIMIT clauses and aggregate before sending. For sensitive SAP data, review your BTP data residency settings and confirm model data handling aligns with your organization's data governance policy before deploying to production.
Use Case 3: Generating ABAP / SQL / HANA Code from Natural Language
This pattern accepts a plain-language description of a requirement and returns production-ready ABAP, SQL, or HANA SQL code. Useful for accelerating development, explaining existing code, or onboarding team members to unfamiliar syntax.
# Use Case 3: SAP Code Generation from Natural Language
from gen_ai_hub.proxy.langchain.openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
llm = ChatOpenAI(proxy_model_name='gpt-4o')
# GPT-4o recommended for ABAP — see model comparison article
requirement = '''
Write a HANA SQL procedure that:
- Reads from a virtual table SOURCE_SCHEMA.ORDERS
- Filters records where CHANGE_DATE > last_run_date parameter
- Inserts new records into TARGET_SCHEMA.ORDERS_DELTA
- Updates a control table DELTA_CONTROL with the new last_run_date
- Handles errors with a rollback
'''
messages = [
SystemMessage(content='''You are a senior SAP HANA SQL developer.
Generate clean, production-ready HANA SQL code.
Include comments explaining key sections.
Flag any HANA-specific considerations or limitations.'''),
HumanMessage(content=f'Generate HANA SQL for this requirement:\n{requirement}')
]
response = llm(messages)
print(response.content)
Use Case 4: Classifying SAP Master Data
Master data classification — tagging materials, vendors, cost centers, or GL accounts against defined schemes — is high-volume and rule-heavy. This pattern uses the model to apply a classification schema to a batch of records and return structured JSON output ready for loading back into SAP.
# Use Case 4: SAP Master Data Classification
import json
from gen_ai_hub.proxy.langchain.openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
llm = ChatOpenAI(proxy_model_name='claude-3.5-sonnet')
materials = [
{'MATNR': '000000000010001234', 'MAKTX': 'Hydraulic Pump Assembly 250bar'},
{'MATNR': '000000000010005678', 'MAKTX': 'Office Chair Ergonomic Mesh Black'},
{'MATNR': '000000000010009012', 'MAKTX': 'SAP S4HANA License Annual Renewal'},
]
classification_schema = ['Mechanical Components', 'Office Supplies',
'Software & Licenses', 'Raw Materials', 'Services']
messages = [
SystemMessage(content=f'''Classify SAP material master records.
Return ONLY valid JSON array. No explanation.
Schema: {classification_schema}
Format: [{{'MATNR': '...', 'CATEGORY': '...', 'CONFIDENCE': 'High/Medium/Low'}}]'''),
HumanMessage(content=f'Classify these materials:\n{json.dumps(materials)}')
]
response = llm(messages)
classified = json.loads(response.content)
print(json.dumps(classified, indent=2))Prompt the model to return only JSON with no preamble or explanation when you need structured output for downstream processing. Claude is particularly consistent at following this instruction on classification tasks.
Use Case 5: Extracting Structured Data from SAP Documents
SAP landscapes accumulate semi-structured text in transport request descriptions, change log comments, functional spec attachments, and ticket notes. This pattern extracts structured fields from unstructured SAP document text — turning narrative descriptions into queryable data.
# Use Case 5: Structured Data Extraction from SAP Documents
import json
from gen_ai_hub.proxy.langchain.openai import ChatOpenAI
from langchain.schema import HumanMessage, SystemMessage
llm = ChatOpenAI(proxy_model_name='claude-3.5-sonnet')
transport_description = '''
TR: DEVK912345 - FI Delta Load Fix
Developer: firstname.lastname@company.com
Changed ZFI_DELTA_LOAD procedure to fix integer overflow on
BKPF document counter. Root cause was 32-bit INT hitting max
value after 2.1B records. Cast to BIGINT. Tested on DEV and QA.
Affected tables: BKPF, BSEG. No customizing changes.
Approved by: firstname1.lastname1@company.com on 2026-03-08
'''
messages = [
SystemMessage(content='''Extract structured data from SAP transport descriptions.
Return ONLY valid JSON. No explanation.
Fields: transport_id, title, developer, approver, approval_date,
affected_tables (list), root_cause, change_type, tested_systems (list)'''),
HumanMessage(content=f'Extract fields from:\n{transport_description}')
]
response = llm(messages)
extracted = json.loads(response.content)
print(json.dumps(extracted, indent=2))Based on practical testing across these five patterns — and detailed in this week's LinkedIn model comparison post — here are the recommended model defaults:
Use Case | What the Model Does |
Exception log summarization | Claude 3.5 Sonnet — consistent on long, noisy log text |
HANA query result analysis | Claude 3.5 Sonnet — structured output quality, handles wide DataFrames |
ABAP / SQL / HANA code generation | GPT-4o — broader SAP code knowledge, stronger on ABAP specifics |
Master data classification | Claude 3.5 Sonnet — reliable JSON-only output, consistent confidence scoring |
Structured data extraction | Claude 3.5 Sonnet — long-form document coherence, clean JSON output |
Swap model_name='gpt-4o' or model_name='mistral-large' in any example to compare outputs. The SDK pattern is identical across all models.
If you work through any of these examples and run into environment-specific issues — particularly around BTP binding or AI Launchpad notebook credential resolution — drop a comment below. The configuration edge cases are where community knowledge adds the most value.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 25 | |
| 19 | |
| 17 | |
| 13 | |
| 11 | |
| 11 | |
| 10 | |
| 9 | |
| 6 | |
| 4 |