SAP Business AI & Joule Development
Related Skills
sap-hana-cloud — Vector engine for embeddings, HANA Cloud as knowledge store
sap-rap-comprehensive — RAP-based data access for grounding AI with SAP data
sap-cap-advanced — CAP MCP plugin for AI-assisted development
sap-build-apps — AI-powered low-code app generation
sap-integration-suite-advanced — AI-assisted mapping in Integration Advisor
Quick Start
Choose your AI scenario:
| Scenario |
Service |
Entry Point |
| Custom ML model training/serving |
AI Core |
AI Launchpad → ML Operations |
| LLM orchestration (chat, completion) |
Generative AI Hub |
AI Core API / orchestration |
| Embed AI in SAP standard apps |
Joule |
Extension Center / Joule Studio |
| RAG with SAP data |
GenAI Hub + HANA Vector |
Orchestration service |
| Document extraction |
Document Information Extraction |
BTP service instance |
Minimal GenAI Hub call (Python):
from gen_ai_hub.proxy.core.proxy_clients import get_proxy_client
from gen_ai_hub.proxy.langchain import ChatOpenAI
proxy_client = get_proxy_client('gen-ai-hub')
llm = ChatOpenAI(
proxy_model_name='gpt-4o',
proxy_client=proxy_client,
temperature=0.0
)
response = llm.invoke("Summarize SAP S/4HANA extensibility options")
print(response.content)
Core Concepts
SAP AI Core Architecture
- Resource groups: Isolated execution environments (multi-tenant)
- Configurations: Define which model/pipeline + parameters to use
- Deployments: Running model inference endpoints
- Executions: One-time training or batch jobs
- Artifacts: Models, datasets registered in AI Core
Generative AI Hub
- Proxy access: Unified API for multiple LLM providers (OpenAI, Azure OpenAI, Anthropic, Google, AWS Bedrock)
- Orchestration service: Chain LLM calls with grounding, content filtering, templating
- Prompt registry: Version-controlled prompt templates
- Content filtering: Input/output moderation (hate, self-harm, sexual, violence)
Joule Architecture
- Joule Foundations: Core capabilities (NLU, context management, response generation)
- Joule Skills: Discrete capabilities mapped to SAP business actions
- Extension Center: Register custom skills for Joule
- Guided answers: Structured multi-turn flows for complex tasks
Vector Engine (HANA Cloud)
- Native
REAL_VECTOR data type (up to 5000 dimensions)
- Distance functions:
COSINE_SIMILARITY, L2DISTANCE, INNER_PRODUCT
- HNSW index for approximate nearest neighbor (ANN)
- Integrated with SAP GenAI Hub embedding models
Common Patterns
Pattern 1: Orchestration Service — Templating + Grounding + Filtering
from gen_ai_hub.orchestration.models.message import SystemMessage, UserMessage
from gen_ai_hub.orchestration.models.template import Template, TemplateValue
from gen_ai_hub.orchestration.models.llm import LLM
from gen_ai_hub.orchestration import OrchestrationClient
llm = LLM(name="gpt-4o", version="latest", parameters={"max_tokens": 1000, "temperature": 0.2})
template = Template(
messages=[
SystemMessage("You are an SAP expert assistant. Answer based on the provided context only."),
UserMessage("Context: {{?context}}\n\nQuestion: {{?question}}")
],
defaults=[TemplateValue(name="context", value="No context provided")]
)
client = OrchestrationClient(llm=llm, template=template)
response = client.run(
template_values=[
TemplateValue(name="context", value="S/4HANA supports tier-1 (key user) and tier-2 (developer) extensibility..."),
TemplateValue(name="question", value="What extensibility tiers does S/4HANA support?")
]
)
print(response.content)
Pattern 2: RAG with HANA Cloud Vector Engine
from gen_ai_hub.proxy.core.proxy_clients import get_proxy_client
from gen_ai_hub.proxy.langchain import OpenAIEmbeddings, ChatOpenAI
from hdbcli import dbapi
proxy_client = get_proxy_client('gen-ai-hub')
embeddings = OpenAIEmbeddings(proxy_model_name='text-embedding-ada-002', proxy_client=proxy_client)
# 1. Embed the query
query = "How do I create a custom CDS view extension?"
query_vector = embeddings.embed_query(query)
# 2. Search HANA Cloud vector store
conn = dbapi.connect(address='<host>', port=443, user='<user>', password='<pwd>', encrypt=True)
cursor = conn.cursor()
cursor.execute("""
SELECT TOP 5 "CONTENT",
COSINE_SIMILARITY("EMBEDDING", TO_REAL_VECTOR(?)) AS score
FROM "KNOWLEDGE_BASE"
ORDER BY score DESC
""", [str(query_vector)])
chunks = [row[0] for row in cursor.fetchall()]
# 3. Generate answer with context
llm = ChatOpenAI(proxy_model_name='gpt-4o', proxy_client=proxy_client, temperature=0.0)
context = "\n---\n".join(chunks)
response = llm.invoke(f"Context:\n{context}\n\nQuestion: {query}\n\nAnswer based on context only:")
print(response.content)
Pattern 3: Content Filtering Configuration
from gen_ai_hub.orchestration.models.content_filter import ContentFilter, AzureFilterThreshold
input_filter = ContentFilter(
provider="azure",
hate=AzureFilterThreshold.ALLOW_SAFE,
self_harm=AzureFilterThreshold.ALLOW_SAFE,
sexual=AzureFilterThreshold.ALLOW_SAFE,
violence=AzureFilterThreshold.ALLOW_SAFE
)
output_filter = ContentFilter(
provider="azure",
hate=AzureFilterThreshold.ALLOW_SAFE,
self_harm=AzureFilterThreshold.ALLOW_SAFE,
sexual=AzureFilterThreshold.ALLOW_SAFE,
violence=AzureFilterThreshold.ALLOW_SAFE_LOW
)
client = OrchestrationClient(
llm=llm,
template=template,
input_filter=input_filter,
output_filter=output_filter
)
Pattern 4: CAP Plugin for AI (Node.js)
// package.json — add cap-llm-plugin
// "dependencies": { "@cap-js/hana": "^1", "cap-llm-plugin": "^1" }
// srv/ai-service.js
const cds = require('@sap/cds');
module.exports = class AIService extends cds.ApplicationService {
async init() {
this.on('askQuestion', async (req) => {
const { question } = req.data;
const vectorPlugin = await cds.connect.to('cap-llm-plugin');
// RAG: retrieve + generate
const response = await vectorPlugin.getRagResponse(
question,
'KNOWLEDGE_BASE', // HANA table with embeddings
'EMBEDDING', // vector column
'CONTENT', // text column
'text-embedding-ada-002',
'gpt-4o',
5 // top-k
);
return { answer: response };
});
await super.init();
}
};
Pattern 5: Joule Custom Skill Definition
{
"name": "lookup-material",
"description": "Look up material master data by material number or description",
"parameters": {
"type": "object",
"properties": {
"materialNumber": {
"type": "string",
"description": "SAP material number (e.g., MAT-001)"
},
"searchTerm": {
"type": "string",
"description": "Free text search term for material description"
}
}
},
"endpoint": {
"url": "https://<app>.cfapps.<region>.hana.ondemand.com/api/materials/search",
"method": "POST",
"authentication": "OAuth2ClientCredentials"
}
}
Error Catalog
| Error |
Message |
Root Cause |
Fix |
401 Unauthorized |
JWT token validation failed |
AI Core service key expired or wrong |
Regenerate service key in BTP Cockpit |
429 Too Many Requests |
Rate limit exceeded |
Too many LLM calls per minute |
Implement retry with exponential backoff; check quota |
404 Deployment not found |
No running deployment |
Model not deployed or deployment scaled to 0 |
Check AI Launchpad → Deployments; redeploy |
VECTOR_DIM_MISMATCH |
Dimension mismatch |
Query vector dimensions ≠ stored vector dimensions |
Ensure same embedding model for indexing and querying |
Content filtered |
Output blocked by content filter |
Response triggered moderation |
Adjust filter thresholds or rephrase prompt |
RESOURCE_EXHAUSTED |
Resource group quota exceeded |
Too many concurrent deployments |
Delete unused deployments; request quota increase |
Performance Tips
- Batch embeddings — Embed documents in batches of 100-500; single calls are 10-50x slower
- Cache embeddings — Store in HANA
REAL_VECTOR column; never re-embed unchanged content
- HNSW index — Create for vector columns with >10K rows:
CREATE HNSW VECTOR INDEX ON "TABLE"("COL")
- Chunk size — 512-1024 tokens per chunk for RAG; too small loses context, too large dilutes relevance
- Streaming — Use streaming responses for chat UIs to reduce perceived latency
- Model selection — Use smaller models (GPT-4o-mini, Claude Haiku) for classification/extraction; larger for reasoning
- Prompt caching — Orchestration service caches prompt templates; reuse templates with variable substitution
- Connection pooling — Reuse AI Core proxy client instances; don't create per request
Gotchas
- Resource group isolation: Models deployed in one resource group are NOT accessible from another
- Token limits: Orchestration service has max token limits per model; check
max_tokens in deployment config
- Embedding model consistency: If you change embedding model, you MUST re-embed all existing documents
- GenAI Hub model availability: Not all models available in all regions; check SAP Discovery Center
- HANA vector index: HNSW index build is CPU-intensive; schedule during low-usage periods
- Joule skill registration: Custom skills require SAP Extension Center access and admin approval
1---2name: sap-business-ai-joule3description: SAP Business AI and Joule copilot development skill. Use when integrating SAP AI Core, building GenAI Hub scenarios (GPT-4/Claude/Llama), extending Joule, using HANA Cloud vector engine for RAG, or working with Document Information Extraction. If the user mentions Joule, SAP AI Core, GenAI Hub, AI Foundation, or RAG with SAP data, use this skill.4license: MIT5---67# SAP Business AI & Joule Development89## Related Skills10- `sap-hana-cloud` — Vector engine for embeddings, HANA Cloud as knowledge store11- `sap-rap-comprehensive` — RAP-based data access for grounding AI with SAP data12- `sap-cap-advanced` — CAP MCP plugin for AI-assisted development13- `sap-build-apps` — AI-powered low-code app generation14- `sap-integration-suite-advanced` — AI-assisted mapping in Integration Advisor1516## Quick Start1718**Choose your AI scenario:**1920| Scenario | Service | Entry Point |21|----------|---------|-------------|22| Custom ML model training/serving | AI Core | AI Launchpad → ML Operations |23| LLM orchestration (chat, completion) | Generative AI Hub | AI Core API / orchestration |24| Embed AI in SAP standard apps | Joule | Extension Center / Joule Studio |25| RAG with SAP data | GenAI Hub + HANA Vector | Orchestration service |26| Document extraction | Document Information Extraction | BTP service instance |2728**Minimal GenAI Hub call (Python):**2930```python31from gen_ai_hub.proxy.core.proxy_clients import get_proxy_client32from gen_ai_hub.proxy.langchain import ChatOpenAI3334proxy_client = get_proxy_client('gen-ai-hub')3536llm = ChatOpenAI(37 proxy_model_name='gpt-4o',38 proxy_client=proxy_client,39 temperature=0.040)4142response = llm.invoke("Summarize SAP S/4HANA extensibility options")43print(response.content)44```4546## Core Concepts4748### SAP AI Core Architecture49- **Resource groups**: Isolated execution environments (multi-tenant)50- **Configurations**: Define which model/pipeline + parameters to use51- **Deployments**: Running model inference endpoints52- **Executions**: One-time training or batch jobs53- **Artifacts**: Models, datasets registered in AI Core5455### Generative AI Hub56- **Proxy access**: Unified API for multiple LLM providers (OpenAI, Azure OpenAI, Anthropic, Google, AWS Bedrock)57- **Orchestration service**: Chain LLM calls with grounding, content filtering, templating58- **Prompt registry**: Version-controlled prompt templates59- **Content filtering**: Input/output moderation (hate, self-harm, sexual, violence)6061### Joule Architecture62- **Joule Foundations**: Core capabilities (NLU, context management, response generation)63- **Joule Skills**: Discrete capabilities mapped to SAP business actions64- **Extension Center**: Register custom skills for Joule65- **Guided answers**: Structured multi-turn flows for complex tasks6667### Vector Engine (HANA Cloud)68- Native `REAL_VECTOR` data type (up to 5000 dimensions)69- Distance functions: `COSINE_SIMILARITY`, `L2DISTANCE`, `INNER_PRODUCT`70- HNSW index for approximate nearest neighbor (ANN)71- Integrated with SAP GenAI Hub embedding models7273## Common Patterns7475### Pattern 1: Orchestration Service — Templating + Grounding + Filtering7677```python78from gen_ai_hub.orchestration.models.message import SystemMessage, UserMessage79from gen_ai_hub.orchestration.models.template import Template, TemplateValue80from gen_ai_hub.orchestration.models.llm import LLM81from gen_ai_hub.orchestration import OrchestrationClient8283llm = LLM(name="gpt-4o", version="latest", parameters={"max_tokens": 1000, "temperature": 0.2})8485template = Template(86 messages=[87 SystemMessage("You are an SAP expert assistant. Answer based on the provided context only."),88 UserMessage("Context: {{?context}}\n\nQuestion: {{?question}}")89 ],90 defaults=[TemplateValue(name="context", value="No context provided")]91)9293client = OrchestrationClient(llm=llm, template=template)9495response = client.run(96 template_values=[97 TemplateValue(name="context", value="S/4HANA supports tier-1 (key user) and tier-2 (developer) extensibility..."),98 TemplateValue(name="question", value="What extensibility tiers does S/4HANA support?")99 ]100)101print(response.content)102```103104### Pattern 2: RAG with HANA Cloud Vector Engine105106```python107from gen_ai_hub.proxy.core.proxy_clients import get_proxy_client108from gen_ai_hub.proxy.langchain import OpenAIEmbeddings, ChatOpenAI109from hdbcli import dbapi110111proxy_client = get_proxy_client('gen-ai-hub')112embeddings = OpenAIEmbeddings(proxy_model_name='text-embedding-ada-002', proxy_client=proxy_client)113114# 1. Embed the query115query = "How do I create a custom CDS view extension?"116query_vector = embeddings.embed_query(query)117118# 2. Search HANA Cloud vector store119conn = dbapi.connect(address='<host>', port=443, user='<user>', password='<pwd>', encrypt=True)120cursor = conn.cursor()121cursor.execute("""122 SELECT TOP 5 "CONTENT",123 COSINE_SIMILARITY("EMBEDDING", TO_REAL_VECTOR(?)) AS score124 FROM "KNOWLEDGE_BASE"125 ORDER BY score DESC126""", [str(query_vector)])127chunks = [row[0] for row in cursor.fetchall()]128129# 3. Generate answer with context130llm = ChatOpenAI(proxy_model_name='gpt-4o', proxy_client=proxy_client, temperature=0.0)131context = "\n---\n".join(chunks)132response = llm.invoke(f"Context:\n{context}\n\nQuestion: {query}\n\nAnswer based on context only:")133print(response.content)134```135136### Pattern 3: Content Filtering Configuration137138```python139from gen_ai_hub.orchestration.models.content_filter import ContentFilter, AzureFilterThreshold140141input_filter = ContentFilter(142 provider="azure",143 hate=AzureFilterThreshold.ALLOW_SAFE,144 self_harm=AzureFilterThreshold.ALLOW_SAFE,145 sexual=AzureFilterThreshold.ALLOW_SAFE,146 violence=AzureFilterThreshold.ALLOW_SAFE147)148149output_filter = ContentFilter(150 provider="azure",151 hate=AzureFilterThreshold.ALLOW_SAFE,152 self_harm=AzureFilterThreshold.ALLOW_SAFE,153 sexual=AzureFilterThreshold.ALLOW_SAFE,154 violence=AzureFilterThreshold.ALLOW_SAFE_LOW155)156157client = OrchestrationClient(158 llm=llm,159 template=template,160 input_filter=input_filter,161 output_filter=output_filter162)163```164165### Pattern 4: CAP Plugin for AI (Node.js)166167```javascript168// package.json — add cap-llm-plugin169// "dependencies": { "@cap-js/hana": "^1", "cap-llm-plugin": "^1" }170171// srv/ai-service.js172const cds = require('@sap/cds');173174module.exports = class AIService extends cds.ApplicationService {175 async init() {176 this.on('askQuestion', async (req) => {177 const { question } = req.data;178 const vectorPlugin = await cds.connect.to('cap-llm-plugin');179180 // RAG: retrieve + generate181 const response = await vectorPlugin.getRagResponse(182 question,183 'KNOWLEDGE_BASE', // HANA table with embeddings184 'EMBEDDING', // vector column185 'CONTENT', // text column186 'text-embedding-ada-002',187 'gpt-4o',188 5 // top-k189 );190191 return { answer: response };192 });193 await super.init();194 }195};196```197198### Pattern 5: Joule Custom Skill Definition199200```json201{202 "name": "lookup-material",203 "description": "Look up material master data by material number or description",204 "parameters": {205 "type": "object",206 "properties": {207 "materialNumber": {208 "type": "string",209 "description": "SAP material number (e.g., MAT-001)"210 },211 "searchTerm": {212 "type": "string",213 "description": "Free text search term for material description"214 }215 }216 },217 "endpoint": {218 "url": "https://<app>.cfapps.<region>.hana.ondemand.com/api/materials/search",219 "method": "POST",220 "authentication": "OAuth2ClientCredentials"221 }222}223```224225## Error Catalog226227| Error | Message | Root Cause | Fix |228|-------|---------|------------|-----|229| `401 Unauthorized` | `JWT token validation failed` | AI Core service key expired or wrong | Regenerate service key in BTP Cockpit |230| `429 Too Many Requests` | Rate limit exceeded | Too many LLM calls per minute | Implement retry with exponential backoff; check quota |231| `404 Deployment not found` | `No running deployment` | Model not deployed or deployment scaled to 0 | Check AI Launchpad → Deployments; redeploy |232| `VECTOR_DIM_MISMATCH` | `Dimension mismatch` | Query vector dimensions ≠ stored vector dimensions | Ensure same embedding model for indexing and querying |233| `Content filtered` | `Output blocked by content filter` | Response triggered moderation | Adjust filter thresholds or rephrase prompt |234| `RESOURCE_EXHAUSTED` | `Resource group quota exceeded` | Too many concurrent deployments | Delete unused deployments; request quota increase |235236## Performance Tips2372381. **Batch embeddings** — Embed documents in batches of 100-500; single calls are 10-50x slower2392. **Cache embeddings** — Store in HANA `REAL_VECTOR` column; never re-embed unchanged content2403. **HNSW index** — Create for vector columns with >10K rows: `CREATE HNSW VECTOR INDEX ON "TABLE"("COL")`2414. **Chunk size** — 512-1024 tokens per chunk for RAG; too small loses context, too large dilutes relevance2425. **Streaming** — Use streaming responses for chat UIs to reduce perceived latency2436. **Model selection** — Use smaller models (GPT-4o-mini, Claude Haiku) for classification/extraction; larger for reasoning2447. **Prompt caching** — Orchestration service caches prompt templates; reuse templates with variable substitution2458. **Connection pooling** — Reuse AI Core proxy client instances; don't create per request246247## Gotchas248249- **Resource group isolation**: Models deployed in one resource group are NOT accessible from another250- **Token limits**: Orchestration service has max token limits per model; check `max_tokens` in deployment config251- **Embedding model consistency**: If you change embedding model, you MUST re-embed all existing documents252- **GenAI Hub model availability**: Not all models available in all regions; check SAP Discovery Center253- **HANA vector index**: HNSW index build is CPU-intensive; schedule during low-usage periods254- **Joule skill registration**: Custom skills require SAP Extension Center access and admin approval