Orchestrate

Set up for Unit 5: SAP generative AI hub access

Get access to SAP's generative AI hub, store an SAP AI Core service key safely, install the SAP Cloud SDK for AI and make your first model call.

Updated Oct 1, 2026Foundational 7 minDeep 40 min
Foundational layer · 7 min read

The 60-second version

Unit 5 is where learners stop building toy models and start calling real ones. Large language models (LLMs) from OpenAI, Anthropic, Google and others are big, expensive to run and trained by someone else. Enterprise teams call them over the internet and pay per use.

In the SAP world, the front door to those models is the generative AI hub. It is part of SAP AI Core, a service on SAP Business Technology Platform (BTP), and of SAP AI Launchpad, the screen where people try prompts. One account gives access to models from several providers, under one contract and one set of controls.

This setup does three things. It gets the learner access to the generative AI hub. It stores the access details, called a service key, safely on the laptop. And it installs SAP's Python library, the SAP Cloud SDK for AI, then makes one test call.

Setup takes 45 to 90 minutes. Most of that is account sign-up.

Why it matters to the business

Until now, everything in this course ran on a laptop for free. From here on, each call to a model costs a little money and goes through an account that someone controls. That is how it works on real projects too, so it is worth setting up properly.

Three points matter to a leader:

  • Access is a contract, not a download. Model calls in SAP's generative AI hub run under an SAP agreement. That is what lets a company use several model providers without signing a contract with each one.
  • Usage is billed in tokens. SAP meters generative AI use in tokens, the word pieces a model reads and writes. Those are converted into BTP capacity units. Output tokens usually cost more than input tokens, so long answers cost more than long questions.
  • Credentials are company assets. A service key works like a password for the whole AI account. On a real order-to-cash project, a leaked key could run up costs or expose prompts that contain customer data. This setup teaches the safe habit from day one.

How SAP does it

As of October 2026, SAP offers the generative AI hub in two ways that matter here:

  • A 30-day basic trial at no charge. SAP's trial page says it includes SAP AI Core, SAP AI Launchpad and access to models such as Anthropic Claude Sonnet 4, Google Gemini 2.5 Pro and OpenAI GPT-5. After the trial, SAP points to buying through Pay-As-You-Go for SAP BTP or an enterprise agreement.
  • The extended service plan of SAP AI Core, in a company's BTP enterprise account. SAP's documentation says the generative AI hub is available only in this plan. The standard plan covers other AI workloads without generative AI.

One change trips up older guides. SAP AI Core used to have a free plan, and many blogs still describe it. SAP discontinued it on 22 May 2026 and names the 30-day trial as the alternative.

Your access options

Option Who it suits Cost Limits
30-day generative AI hub trial Individual learners No charge Ends after 30 days; start it when you have time to work through Unit 5
Company BTP account, extended plan Learners whose employer already uses SAP AI Core Billed to the company per use Needs an administrator to create the service key
Pay-As-You-Go for SAP BTP Learners who want to keep going after the trial Small per-use charges, plus any BTP fees Needs a payment method and a BTP setup of your own
No SAP account yet Anyone, while access is being arranged Free Every hands-on step offers a --sample path with made-up output

The course works with any of the first three. The fourth lets a learner read and run the code, but not see a real model answer.

Time and money

  • Time: 45 to 90 minutes. Sign-up and waiting for the trial account take most of it. The install and check take about 15 minutes.
  • Money: nothing during the trial. After that, model calls are paid per use. A learner's test prompts are small, but costs vary by model, so check before choosing a big one.
  • Disk space: a few hundred megabytes for the SDK and the libraries it brings with it.
  • Clock: the trial runs for 30 days from the start. Plan Unit 5 so it fits.

Questions to ask IT

  • Does the company already have SAP AI Core with the extended plan? In which BTP subaccount?
  • May a learner get a service key for a sandbox or training resource group, rather than production?
  • Is a personal 30-day trial allowed, and with which email address?
  • Does the company network allow the SAP AI Core and BTP sign-in addresses from a laptop?
  • Who rotates service keys, and how should a learner report a key that leaked?

Common misconceptions

  • "SAP AI Core has a free tier." It did. SAP discontinued the free plan in May 2026. The current no-cost route is the 30-day trial.
  • "Any SAP AI Core instance gives you LLMs." Only the extended plan includes the generative AI hub. A standard-plan instance does not.
  • "The service key is only a technical detail." It grants access to the account's models and is billed to its owner. Treat it like a password.
  • "Once set up, the model list stays the same." Models are added and retired over time, and trial and company accounts may offer different ones. The check script shows what your account offers today.

Key terms

  • Generative AI hub: SAP's access point to large language models from several providers, inside SAP AI Core and SAP AI Launchpad.
  • SAP AI Core: an SAP BTP service that runs AI workloads and serves the generative AI hub.
  • SAP AI Launchpad: the web screen for working with SAP AI Core, including trying prompts.
  • Service plan: the edition of a BTP service you subscribe to; for generative AI it is the extended plan.
  • Service key: a small file of access details (an ID, a secret and two web addresses) for one service instance.
  • Token: a word piece a model reads or writes; the unit SAP meters generative AI use in.
  • SAP Cloud SDK for AI: SAP's library that lets code call the generative AI hub; this course uses the Python version.

Check yourself

Pick one answer for each question. The explanation appears after you choose.
  1. 1What does the Unit 5 setup give a learner?

    Answer: B. Unit 5 calls real models through SAP's generative AI hub. The setup gets access, stores the service key safely and installs the SAP Cloud SDK for AI, then proves it all with one call.
  2. 2A colleague's 2025 blog says to use SAP AI Core's free plan. What should you tell them?

    Answer: C. SAP's own release notes say the free plan was discontinued on 22 May 2026 and point to a 30-day trial including the generative AI hub. Older guides that describe the free plan are out of date.
  3. 3Your company has SAP AI Core on the standard plan. Can the team use the generative AI hub?

    Answer: D. SAP's documentation says the generative AI hub is available only in the extended plan. A company on the standard plan can update to extended, but SAP doesn't allow a downgrade back.
  4. 4How is generative AI use in SAP AI Core charged?

    Answer: A. SAP meters generative AI use in tokens and converts them into capacity units. Output tokens usually cost more than input tokens, so long answers cost more than long questions.
  5. 5Why should a leader treat a service key like a password?

    Answer: B. A service key gives access to the account's models, and usage is billed to the account owner. If it leaks, someone else can run up costs or send data through your account.
  6. 6A learner starts the 30-day trial a month before they have time for Unit 5. What goes wrong?

    Answer: D. The trial runs for 30 days from the start. Starting it only when there is time to work through Unit 5 makes the most of it.
  7. 7What is a good first question for IT before Unit 5?

    Answer: C. If the company already has the extended plan, a learner may get a service key for a sandbox instead of a personal trial. It also tells IT what access is being requested.
Deep layer · 40 min read

Mental model: a key on your laptop, a deployment in SAP AI Core

Every call in Unit 5 follows the same path. Your script reads the service key details from .env. It trades them for a short-lived token, then sends the prompt to an orchestration deployment in SAP AI Core. Orchestration forwards it to the model you named.

flowchart LR
  K[Service key<br/>downloaded once] -->|key_to_env.py| E[.env<br/>AICORE_ lines]
  E --> S[Your script<br/>SAP Cloud SDK for AI]
  S -->|client ID + secret| A[Sign-in URL<br/>returns token]
  S -->|token + prompt| O[Orchestration<br/>deployment]
  O --> M[Model, e.g.<br/>Claude, GPT, Gemini]

Once this path works, every later Unit 5 topic only changes the prompt and the settings. The plumbing stays the same.

How it works

The pieces SAP gives you

Piece What it is Where you see it
Subaccount Your area inside an SAP BTP account BTP cockpit
SAP AI Core instance Your copy of the service, on a service plan BTP cockpit, Instances and Subscriptions
Extended plan The plan that includes the generative AI hub The instance's plan column
Service key Access details for one instance: clientid, clientsecret, url, serviceurls.AI_API_URL A JSON file you download
Resource group A partition inside the instance; one called default exists from the start Sent as the header AI-Resource-Group
Orchestration deployment A running endpoint that forwards prompts to models Listed under the scenario orchestration

From service key to the SDK's settings

This is the service-key pattern from SAP BTP foundations for AI builders, where you swapped a key for a token by hand. Here the SDK does the swap. The service key and the SDK use different names for the same things. The SDK documentation lists five environment variables. SAP's service key documentation describes the fields they come from:

.env name Comes from the service key Note
AICORE_CLIENT_ID clientid Not secret on its own
AICORE_CLIENT_SECRET clientsecret Secret: never share it
AICORE_AUTH_URL url plus /oauth/token The sign-in address
AICORE_BASE_URL serviceurls.AI_API_URL plus /v2 The SDK expects the /v2 ending
AICORE_RESOURCE_GROUP Not in the key Use default for this course

Getting the two endings wrong is the most common setup error. The key_to_env.py script in Step 4 adds them for you.

How the SDK finds the orchestration deployment

SAP's documentation says your default resource group contains a running orchestration deployment. You don't have to create one. When the SDK starts an OrchestrationService without a URL, it lists the deployments in your resource group and picks a running one for the orchestration scenario.

You can see the same list yourself with GET {AI_API_URL}/v2/lm/deployments. The check script in Step 7 does exactly that, with only built-in Python.

Which version of orchestration

SAP's orchestration service has two API versions. The SDK's examples mark version 1 as deprecated, with decommissioning planned for October 2026. This course uses version 2 only: the gen_ai_hub.orchestration_v2 module.

Which models you can call

Models differ by account, region and date. SAP's documentation gives one call that lists them: GET {AI_API_URL}/v2/lm/scenarios/foundation-models/models. Each model lists its allowedScenarios; those that include orchestration can be called the way this course does. The check script prints a few names, which you can pass to the test script with --model.

Build it yourself: connect your laptop to the generative AI hub

You will get access to SAP AI Core, save its service key into .env with a small script, install the SAP Cloud SDK for AI, send one prompt about a blocked sales order, and run a check. If you have no SAP access yet, do every step marked no account and come back for the rest later.

Before you start: complete Set up your computer for this course and Set up for Unit 2. They install Python, VS Code and Git, and create your orchestrate-course folder with its .venv, .env and .gitignore. This walkthrough doesn't repeat those steps.

What you need

  • Your course folder from earlier units.
  • About 45 to 90 minutes.
  • An SAP account (free to register) for the trial, or a service key from your company's SAP AI Core administrator. Neither is needed for the --sample paths.
  • Cost: no charge during the 30-day trial. On a company or Pay-As-You-Go account, a small per-request charge for each model call.

Step 1: Open your course folder and turn on the virtual environment

  1. Open VS Code, choose File > Open Folder, and open orchestrate-course.

  2. Open a terminal: Terminal > New Terminal.

  3. If the prompt doesn't start with (.venv), turn it on:

    • Windows (PowerShell):

      .venv\Scripts\Activate.ps1
    • macOS / Linux:

      source .venv/bin/activate

Run every command in this topic from the course folder, not from unit05.

Step 2: Install the SAP Cloud SDK for AI (no account)

  1. In VS Code, open requirements.txt and add this line at the end:

    sap-ai-sdk-gen

    python-dotenv is already in the file from Unit 1.

  2. Save the file and install:

    pip install -r requirements.txt
  3. Confirm it worked (the same on every system):

    python -c "import gen_ai_hub.orchestration_v2; print('SAP Cloud SDK for AI is ready')"

What success looks like:

SAP Cloud SDK for AI is ready

sap-ai-sdk-gen is the SDK's package name. Its Python code is called gen_ai_hub, from the SDK's earlier name. The default install covers OpenAI models directly and every model through orchestration, which is all this course needs. As of October 2026 the current version is 7.4.1.

Step 3: Make the Unit 5 folder (no account)

  • Windows (PowerShell):

    New-Item -ItemType Directory -Force unit05
  • macOS / Linux:

    mkdir -p unit05

Step 4: Get access and download a service key

Pick one of the two paths.

Path A: the 30-day generative AI hub trial

  1. Open SAP's trial page: https://www.sap.com/products/artificial-intelligence/generative-ai-hub-trial.html.
  2. Choose the button to start the free trial. Sign in with your SAP account, or register for one when asked.
  3. Follow the trial's own on-screen steps until it says your trial is ready. This can take a few minutes.
  4. Open the SAP BTP cockpit for your trial and go to your subaccount.
  5. In the left menu, choose Instances and Subscriptions.
  6. Find the SAP AI Core instance. From its dropdown (or the … menu at the end of its row), choose Create Service Key.
  7. Enter a name, for example orchestrate-course, and click Create.
  8. Open the new key and download it. Save the .json file in your Downloads folder, not in the course folder.

Path B: your company's SAP AI Core

  1. Ask your SAP BTP administrator for a service key of an SAP AI Core instance on the extended plan. A sandbox or training instance is best.
  2. Ask them to send it securely, not by plain email or chat.
  3. Save the .json file in your Downloads folder.

Step 5: Copy the key into .env with a script

This script reads the downloaded key, converts it to the five AICORE_ lines from the table above and writes them into .env. It keeps your other lines, such as SAP_API_KEY, and never prints the secret.

  1. In VS Code's file list, right-click unit05, choose New File and name it key_to_env.py.
  2. Paste the code below and save.
"""Copy the SAP AI Core credentials from a downloaded service key into your course .env file.

How to run (from your course folder, with .venv turned on):
    python unit05/key_to_env.py path/to/your-service-key.json
    python unit05/key_to_env.py --sample      # practice with a made-up key; writes .env.sample instead

It writes five AICORE_ lines that the SAP Cloud SDK for AI reads. It never prints your secret.
It replaces older AICORE_ lines in .env and keeps every other line (such as SAP_API_KEY).
"""
import argparse
import json
import sys
from pathlib import Path

COURSE = Path(__file__).resolve().parent.parent   # the folder above unit05
SAMPLE_KEY = {   # made-up values, shaped like a real service key
    "clientid": "sb-sample-client-id",
    "clientsecret": "sample-secret-do-not-use",
    "url": "https://sample-subaccount.authentication.sap.hana.ondemand.com",
    "serviceurls": {"AI_API_URL": "https://api.ai.sample.cfapps.sap.hana.ondemand.com"},
}


def read_key(path: str) -> dict:
    """Load the service key file and check it has the parts we need."""
    file = Path(path).expanduser()
    if not file.exists():
        raise SystemExit(f"File not found: {file}. Check the path and file name.")
    try:
        key = json.loads(file.read_text(encoding="utf-8-sig"))
    except json.JSONDecodeError:
        raise SystemExit("That file is not valid JSON. Download the service key again, or copy all of it.")
    key = key.get("credentials", key)   # some tools wrap the key in "credentials"
    missing = [n for n in ("clientid", "clientsecret", "url") if not key.get(n)]
    if not key.get("serviceurls", {}).get("AI_API_URL"):
        missing.append("serviceurls.AI_API_URL")
    if missing:
        raise SystemExit("The key is missing: " + ", ".join(missing) +
                         ". Is it an SAP AI Core key with a client secret (not an x.509 certificate)?")
    return key


def env_lines(key: dict) -> list:
    """Turn the service key into the variable names the SDK expects."""
    return [
        f'AICORE_CLIENT_ID="{key["clientid"]}"',
        f'AICORE_CLIENT_SECRET="{key["clientsecret"]}"',
        f'AICORE_AUTH_URL="{key["url"].rstrip("/")}/oauth/token"',
        f'AICORE_BASE_URL="{key["serviceurls"]["AI_API_URL"].rstrip("/")}/v2"',
        'AICORE_RESOURCE_GROUP="default"',
    ]


def main() -> None:
    parser = argparse.ArgumentParser(description="Write SAP AI Core credentials into .env")
    parser.add_argument("key_file", nargs="?", help="the service key .json file you downloaded")
    parser.add_argument("--sample", action="store_true", help="use a made-up key and write .env.sample")
    args = parser.parse_args()
    if not args.sample and not args.key_file:
        parser.error("give the path to your service key file, or use --sample")

    key = SAMPLE_KEY if args.sample else read_key(args.key_file)
    target = COURSE / (".env.sample" if args.sample else ".env")
    old = target.read_text(encoding="utf-8").splitlines() if target.exists() else []
    kept = [line for line in old if not line.strip().startswith("AICORE_")]
    target.write_text("\n".join(kept + env_lines(key)) + "\n", encoding="utf-8")

    print(f"Wrote 5 AICORE_ lines to {target}")
    print(f"  client ID starts with: {key['clientid'][:6]}...")
    print(f"  auth URL host:         {key['url'].split('/')[2]}")
    print(f"  API URL host:          {key['serviceurls']['AI_API_URL'].split('/')[2]}")
    print("  resource group:        default")
    if not args.sample:
        print("Now delete the downloaded key file, or move it somewhere safe outside the course folder.")


if __name__ == "__main__":
    main()
  1. No account: practise with a made-up key. It writes a separate .env.sample file, so your real .env is untouched:

    python unit05/key_to_env.py --sample
  2. With your key: run it with the path to your downloaded file. Replace the file name with yours.

    • Windows (PowerShell):

      python unit05/key_to_env.py "$HOME\Downloads\orchestrate-course.json"
    • macOS / Linux:

      python unit05/key_to_env.py ~/Downloads/orchestrate-course.json

What success looks like (with --sample; your hosts will differ):

Wrote 5 AICORE_ lines to /Users/you/orchestrate-course/.env.sample
  client ID starts with: sb-sam...
  auth URL host:         sample-subaccount.authentication.sap.hana.ondemand.com
  API URL host:          api.ai.sample.cfapps.sap.hana.ondemand.com
  resource group:        default
  1. With a real key, the last line tells you to delete the downloaded file. Do it now: your .env has everything you need.
  2. Delete .env.sample too, if you made one; it is only practice.

What each part of the script does:

Part What it does
COURSE Finds the course folder from the script's own location, so .env lands in the right place
read_key Opens the JSON file and checks it has clientid, clientsecret, url and AI_API_URL
env_lines Builds the five lines, adding /oauth/token and /v2
Main part Removes older AICORE_ lines, keeps every other line, writes the file and prints only safe hints
--sample Uses a made-up key and writes .env.sample, so you can see the result without an account

Step 6: Send your first prompt

The test script asks a model to explain a blocked sales order to a sales manager, the running example from earlier units. It prints the answer and the number of tokens used.

  1. In unit05, create hello_genai_hub.py, paste the code below and save.
"""Unit 5 first call: send one prompt to a model through SAP's generative AI hub.

It uses the orchestration service (API version 2) through the SAP Cloud SDK for AI, with the
AICORE_ settings in your .env file. The orchestration deployment in your "default" resource group
is found automatically.

How to run (from your course folder, with .venv turned on):
    python unit05/hello_genai_hub.py --sample                    # no account: show a made-up answer
    python unit05/hello_genai_hub.py                             # real call, default model
    python unit05/hello_genai_hub.py --model gemini-2.5-pro      # pick another model your account offers
"""
import argparse
import os
import sys
import time

from dotenv import load_dotenv

PROMPT = ("Sales order {{?order}} is blocked for delivery because the customer is over the credit limit. "
          "In two short sentences, explain to a sales manager what that means and one sensible next step.")
ORDER = "4711 (made-up)"
SAMPLE_ANSWER = ("The customer owes more than the credit limit allows, so the system has stopped this "
                 "order from shipping. Ask credit management to review the account and decide whether "
                 "to release the order.")


def real_call(model: str):
    """Build an orchestration config (template + model) and run it once."""
    from gen_ai_hub.orchestration_v2 import (LLMModelDetails, ModuleConfig, OrchestrationConfig,
                                             OrchestrationService, PromptTemplatingModuleConfig,
                                             SystemMessage, Template, UserMessage)
    template = Template(template=[
        SystemMessage(content="You are a concise assistant for SAP order-to-cash users."),
        UserMessage(content=PROMPT),
    ])
    config = OrchestrationConfig(modules=ModuleConfig(prompt_templating=PromptTemplatingModuleConfig(
        prompt=template, model=LLMModelDetails(name=model))))
    service = OrchestrationService(config=config)
    try:
        result = service.run(placeholder_values={"order": ORDER})
    finally:
        service.close_http_connection()
    final = result.final_result
    return final.model, final.choices[0].message.content, final.usage


def main() -> None:
    parser = argparse.ArgumentParser(description="One prompt through SAP's generative AI hub.")
    parser.add_argument("--sample", action="store_true", help="no account needed: print a made-up answer")
    parser.add_argument("--model", default="anthropic--claude-4-sonnet",
                        help="model name as SAP AI Core lists it (check_unit05.py prints some)")
    args = parser.parse_args()

    print("Prompt:", PROMPT.replace("{{?order}}", ORDER))
    if args.sample:
        print("\n[sample] Made-up answer, no model was called:")
        print(SAMPLE_ANSWER)
        print("\n[sample] Tokens: about 60 in, 40 out (made-up numbers)")
        return

    load_dotenv()   # reads the AICORE_ lines from .env in your course folder
    needed = ["AICORE_CLIENT_ID", "AICORE_CLIENT_SECRET", "AICORE_AUTH_URL",
              "AICORE_BASE_URL", "AICORE_RESOURCE_GROUP"]
    missing = [name for name in needed if not os.environ.get(name)]
    if missing:
        sys.exit("Missing in .env: " + ", ".join(missing) + ". Run unit05/key_to_env.py first (Step 5).")

    start = time.perf_counter()
    try:
        model, answer, usage = real_call(args.model)
    except Exception as error:   # show a short, readable reason instead of a long traceback
        sys.exit(f"The call failed: {type(error).__name__}: {str(error)[:400]}")
    print(f"\nModel: {model}  ({time.perf_counter() - start:.1f} seconds)")
    print(answer)
    print(f"\nTokens: {usage.prompt_tokens} in, {usage.completion_tokens} out, {usage.total_tokens} total")


if __name__ == "__main__":
    main()
  1. No account:

    python unit05/hello_genai_hub.py --sample
  2. With your key:

    python unit05/hello_genai_hub.py

What success looks like (with --sample):

Prompt: Sales order 4711 (made-up) is blocked for delivery because the customer is over the credit limit. In two short sentences, explain to a sales manager what that means and one sensible next step.

[sample] Made-up answer, no model was called:
The customer owes more than the credit limit allows, so the system has stopped this order from shipping. Ask credit management to review the account and decide whether to release the order.

[sample] Tokens: about 60 in, 40 out (made-up numbers)

A real call prints Model: with the model's name and the time taken, the model's own answer, and real token counts. The wording changes on every run; that is normal for LLMs, as How LLMs generate text explained.

If the default model isn't offered in your account, run Step 7 first. It lists models you can use. Then pass one, for example --model gpt-5.

What each part of the script does:

Part What it does
PROMPT The user message, with a placeholder {{?order}} that orchestration fills in
Template A system message (the assistant's role) and the user message
LLMModelDetails Which model to use, by the name SAP AI Core gives it
OrchestrationConfig Joins the template and the model into one configuration
OrchestrationService Signs in with your .env settings, finds the running orchestration deployment and sends the request
placeholder_values Fills {{?order}} with the made-up order number
final_result The model's answer and the token counts, in the same shape as OpenAI's chat format
--sample, --model Optional: show a made-up answer without an account, or choose another model

Step 7: Run the Unit 5 check

The check uses only built-in Python, like the earlier checks. If your AICORE_ lines are there, it gets a sign-in token, confirms a running orchestration deployment and lists models you can use.

  1. In the course folder (not in unit05), create check_unit05.py, paste the code below and save.
"""Check that your computer is ready for Unit 5 (LLM engineering with SAP's generative AI hub).

Run it from your course folder:  python check_unit05.py
It reads your .env file but never prints your secret. If your SAP AI Core settings are there,
it asks SAP AI Core for a token and lists what your account offers. It changes nothing and
sends your credentials only to the SAP sign-in address from your own service key.
"""
import base64
import importlib.metadata
import importlib.util
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request

problems = 0
NAMES = ["AICORE_CLIENT_ID", "AICORE_CLIENT_SECRET", "AICORE_AUTH_URL", "AICORE_BASE_URL", "AICORE_RESOURCE_GROUP"]


def report(ok: bool, label: str, fix: str = "", optional: bool = False) -> None:
    """Print one line: OK, MISSING (must fix) or LATER (optional for now)."""
    global problems
    if ok:
        print(f"  OK       {label}")
    elif optional:
        print(f"  LATER    {label}  ->  {fix}")
    else:
        problems += 1
        print(f"  MISSING  {label}  ->  {fix}")


def read_env(path: str = ".env") -> dict:
    """Read NAME="value" lines from .env with built-in Python only."""
    values = {}
    if os.path.exists(path):
        with open(path, encoding="utf-8-sig") as f:
            for line in f:
                if "=" in line and not line.lstrip().startswith("#"):
                    name, value = line.split("=", 1)
                    values[name.strip()] = value.strip().strip('"').strip("'")
    return values


def get_json(url: str, headers: dict, data: bytes = None) -> dict:
    request = urllib.request.Request(url, data=data, headers=headers)
    with urllib.request.urlopen(request, timeout=30) as response:
        return json.loads(response.read().decode("utf-8"))


def why(error: Exception) -> str:
    """A short, readable reason for a failed web call."""
    if isinstance(error, urllib.error.HTTPError):
        return f"HTTP {error.code} {error.reason}"
    return type(error).__name__ + (f": {error.reason}" if hasattr(error, "reason") else "")


print("\n1. Python")
v = sys.version_info
report(v >= (3, 11), f"Python {v.major}.{v.minor}.{v.micro}",
       "the course needs Python 3.11 or newer (see Set up for Unit 2, Step 1)")
report(sys.prefix != sys.base_prefix, "virtual environment is active", "activate .venv (Step 1)")

print("\n2. Libraries")
for module, package in [("gen_ai_hub", "sap-ai-sdk-gen"), ("dotenv", "python-dotenv")]:
    found = importlib.util.find_spec(module) is not None
    version = importlib.metadata.version(package) if found else ""
    report(found, f"{package} {version}".strip(), "pip install -r requirements.txt (Step 2)")

print("\n3. Settings in .env")
env = read_env()
report(os.path.exists(".env"), ".env file in this folder", "create it (Set up your computer, Step 6)")
ignored = False
if os.path.exists(".gitignore"):
    with open(".gitignore", encoding="utf-8") as f:
        ignored = ".env" in f.read().split()
report(ignored, ".env is listed in .gitignore", "add a line .env to .gitignore (Set up your computer, Step 7)")
have = all(env.get(n) for n in NAMES)
for name in NAMES:
    report(bool(env.get(name)), name, "run unit05/key_to_env.py with your service key (Step 5)", optional=True)

print("\n4. SAP AI Core")
if not have:
    report(False, "SAP AI Core sign-in", "add your service key first; --sample paths work without it",
           optional=True)
else:
    token = ""
    try:
        basic = base64.b64encode(f"{env['AICORE_CLIENT_ID']}:{env['AICORE_CLIENT_SECRET']}".encode()).decode()
        reply = get_json(env["AICORE_AUTH_URL"],
                         {"Authorization": f"Basic {basic}", "Content-Type": "application/x-www-form-urlencoded"},
                         urllib.parse.urlencode({"grant_type": "client_credentials"}).encode())
        token = reply.get("access_token", "")
        report(bool(token), "got a sign-in token", "the reply had no token; create a new service key")
    except Exception as error:
        report(False, "got a sign-in token", f"{why(error)}; check the AICORE_ lines (Step 5) and your network")

    if token:
        headers = {"Authorization": f"Bearer {token}", "AI-Resource-Group": env["AICORE_RESOURCE_GROUP"]}
        base = env["AICORE_BASE_URL"].rstrip("/")
        try:
            deployments = get_json(f"{base}/lm/deployments", headers).get("resources", [])
            running = [d for d in deployments if d.get("status") == "RUNNING" and
                       (d.get("scenarioId") == "orchestration" or
                        d.get("configurationName") == "defaultOrchestrationConfig")]
            report(bool(running), f"orchestration deployment RUNNING in resource group "
                                  f"'{env['AICORE_RESOURCE_GROUP']}'",
                   "none found; see 'If something goes wrong' (Step 7)")
        except Exception as error:
            report(False, "list deployments", f"{why(error)}; is AICORE_BASE_URL right, ending in /v2?")
        try:
            models = get_json(f"{base}/lm/scenarios/foundation-models/models", headers).get("resources", [])
            usable = sorted(m["model"] for m in models if any(
                s.get("scenarioId") == "orchestration" for s in m.get("allowedScenarios", [])))
            report(bool(usable), f"{len(usable)} models usable through orchestration", "none listed")
            if usable:
                print("           for example: " + ", ".join(usable[:6]))
        except Exception as error:
            report(False, "list models", why(error))

print("\n5. Course folder")
for path, step in [("unit05", "3"), (os.path.join("unit05", "key_to_env.py"), "4"),
                   (os.path.join("unit05", "hello_genai_hub.py"), "6")]:
    report(os.path.exists(path), path, f"create it (Step {step})", optional=True)

print()
if problems:
    print(f"{problems} item(s) to fix. Fix them in order, then run this again.")
    sys.exit(1)
if have:
    print("All set. Your computer and your SAP AI Core access are ready for Unit 5.")
else:
    print("Your computer is ready. Add SAP AI Core access (Steps 4 and 5) for the real calls in Unit 5.")
  1. Run it:

    python check_unit05.py

What success looks like (with a working service key; your model names will differ):

1. Python
  OK       Python 3.11.15
  OK       virtual environment is active

2. Libraries
  OK       sap-ai-sdk-gen 7.4.1
  OK       python-dotenv 1.2.4

3. Settings in .env
  OK       .env file in this folder
  OK       .env is listed in .gitignore
  OK       AICORE_CLIENT_ID
  OK       AICORE_CLIENT_SECRET
  OK       AICORE_AUTH_URL
  OK       AICORE_BASE_URL
  OK       AICORE_RESOURCE_GROUP

4. SAP AI Core
  OK       got a sign-in token
  OK       orchestration deployment RUNNING in resource group 'default'
  OK       2 models usable through orchestration
           for example: anthropic--claude-4-sonnet, gpt-5

5. Course folder
  OK       unit05
  OK       unit05/key_to_env.py
  OK       unit05/hello_genai_hub.py

All set. Your computer and your SAP AI Core access are ready for Unit 5.

Without SAP access yet, the five AICORE_ lines and the sign-in show LATER, and the last line reads Your computer is ready. Add SAP AI Core access (Steps 4 and 5) for the real calls in Unit 5. That is a valid result: you can follow Unit 5 with the --sample paths and add access later.

What each part of the check does:

Part What it checks
Python Version 3.11 or newer, and that .venv is active
Libraries That sap-ai-sdk-gen and python-dotenv are installed
Settings That .env exists, Git ignores it, and the five AICORE_ names have values. It never prints them
SAP AI Core Gets a token from your sign-in URL, lists deployments in your resource group and lists models allowed for orchestration
Course folder That unit05 and both scripts exist

Step 8: Save your work in Git

  1. Confirm Git will not pick up your secrets:

    git status

    You should see requirements.txt, check_unit05.py and unit05/. You must not see .env or any .json key file. If you do, stop and fix .gitignore first.

  2. Save:

    git add requirements.txt check_unit05.py unit05/key_to_env.py unit05/hello_genai_hub.py
    git commit -m "Set up Unit 5: SAP AI Core access and first call"

If something goes wrong

What you see What it means What to do
python is not recognized, or command not found Python isn't installed, or the terminal can't find it Windows: repeat Unit 1, Step 1, then open a new terminal. macOS/Linux: use python3 until .venv is active
ModuleNotFoundError: No module named 'gen_ai_hub' or 'dotenv' The library isn't installed in the Python you're using Check for (.venv) in the prompt, then pip install -r requirements.txt
File not found from key_to_env.py The path to the key file is wrong Check the file name in Downloads; put the path in quotes if it has spaces
The key is missing: ... The file isn't an SAP AI Core key with a client secret Download the key again; if it has certificate and key instead, ask for a client-secret key
Missing in .env: AICORE_... key_to_env.py hasn't run, or wrote to another folder Run Step 5 from the course folder
AIAPIAuthenticatorException: Could not retrieve Authorization token Sign-in failed: wrong ID or secret, a deleted key, or the network blocked the sign-in URL Create a new service key and repeat Step 5; try another network
Check shows HTTP 401 Unauthorized on the token The client ID or secret is wrong Repeat Step 5 with a fresh key
Check shows HTTP 404 when listing deployments AICORE_BASE_URL doesn't end in /v2, or points to the wrong host Repeat Step 5; don't edit the URL by hand
orchestration deployment RUNNING shows MISSING No running orchestration deployment in your resource group Wait a few minutes on a new trial, then run the check again; on a company account, ask the administrator, or check AICORE_RESOURCE_GROUP is default
0 models usable through orchestration Your instance may not be on the extended plan Ask the administrator which plan the instance uses
The call fails with a model name error That model isn't offered in your account or region Run the check, then pass a listed name with --model
Tunnel connection failed, SSL or timed out A company proxy or firewall blocks SAP's servers Try another network, or ask IT to allow the SAP AI Core and sign-in hosts
Windows: .venv\Scripts\Activate.ps1 cannot be loaded PowerShell blocks scripts Run Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser, answer Y, and try again

The SAP way: from trial to a company account

Your laptop setup is the same on every account type. What changes is where the service key comes from and who pays.

Trial Company account (extended plan)
Account type 30-day basic trial BTP enterprise account
Generative AI hub Included Included in the extended plan only
Cost No charge Billed per use in capacity units
Who creates the key You Usually an administrator
Lifetime Ends after 30 days As long as the contract runs
Good for Learning Unit 5 Real projects and long-term practice

After the trial, SAP's trial page points to Pay-As-You-Go for SAP BTP or an enterprise agreement. A company on the standard plan can update its instance to extended, keeping its data; SAP's documentation says it can't go back to standard afterwards.

Two production habits are worth knowing now:

  • Separate resource groups. Real teams keep different projects or tenants apart in resource groups. The SDK reads the group from AICORE_RESOURCE_GROUP, so code doesn't change between them.
  • Certificates instead of secrets. SAP AI Core can issue a service key with an x.509 certificate instead of a client secret. The SDK supports it through AICORE_CERT_FILE_PATH and AICORE_KEY_FILE_PATH. This course uses client secrets for simplicity.

Apps deployed on BTP don't read a .env file; Unit 10 covers running AI on SAP BTP in production.

Production concerns

  • Secrets: .env is fine for a laptop. Shared or deployed code gets credentials from a secret store, never from a file in the repository.
  • Rotation: SAP's documentation makes you responsible for rotating SAP AI Core credentials. Delete keys you no longer use; create a new one if one might have leaked.
  • Cost control: every call is metered in tokens. Print token counts while learning, as the test script does, so you get a feel for cost before Unit 5's larger prompts.
  • Data: prompts leave your laptop and go to a model provider through SAP. Use made-up data in this course. On projects, check what your company's agreement allows.
  • Model changes: models are added and retired. Keep the model name in one place (here, --model) so a change is one edit.

Pitfalls

  • Following a guide for the old free plan. It was discontinued in May 2026. Use the trial or a company account.
  • Starting the trial too early. It runs for 30 days. Start it when you can work through Unit 5.
  • Saving the key file in the course folder. One git add . and it is in your history. Keep it in Downloads, then delete it after Step 5.
  • Missing /oauth/token or /v2. The SDK needs both endings. Let key_to_env.py add them.
  • Using orchestration version 1 examples. Older blogs use gen_ai_hub.orchestration. Use gen_ai_hub.orchestration_v2.
  • Hard-coding a model name everywhere. Model availability changes. Pass it as an option.

Exercise: record your Unit 5 access

  1. Run python check_unit05.py and copy its output.

  2. In unit05, create access_notes.md with these lines and fill them in:

    # My Unit 5 access
    
    - Access path (trial, company account, or sample only):
    - Trial start date and end date (if trial):
    - Resource group:
    - Models usable through orchestration (from the check):
    - Model I will use by default in Unit 5:
    - Tokens used by my first real call (in / out):
  3. Run python unit05/hello_genai_hub.py with two different models from your list, using --model. Add one line to access_notes.md comparing their answers and token counts.

  4. If you have no access yet, run the --sample path and write "sample only" on the first line.

  5. Commit unit05/access_notes.md with Git. Never paste secrets into it.

Done when: check_unit05.py ends with All set (or Your computer is ready on the sample path), and access_notes.md is committed with every line filled in. The model list feeds the next Unit 5 topic, on choosing and calling LLMs.

Check yourself

Pick one answer for each question. The explanation appears after you choose.
  1. 1Which two endings does key_to_env.py add to the service key's URLs?

    Answer: B. The SDK expects AICORE_AUTH_URL to be the token address and AICORE_BASE_URL to end in /v2. The service key gives only the base addresses, which is why the script adds both endings.
  2. 2Why does the test script not need a deployment ID?

    Answer: C. SAP's documentation says the default resource group contains a running orchestration deployment. Without a URL, OrchestrationService lists deployments in the resource group and picks a running one for the orchestration scenario.
  3. 3What does AICORE_RESOURCE_GROUP do, and why isn't it in the service key?

    Answer: D. A resource group partitions work inside one SAP AI Core instance and is sent as the AI-Resource-Group header. The service key belongs to the instance, so the SDK documentation says to set the group separately; this course uses default.
  4. 4The check shows "0 models usable through orchestration" but the token works. What is the likeliest cause?

    Answer: B. A working token proves the key is valid, so the instance exists. The generative AI hub is only in the extended plan, so a standard-plan instance offers no models for orchestration.
  5. 5Which SDK module should new Unit 5 code import for orchestration?

    Answer: C. The SDK's examples mark orchestration version 1 as deprecated, with decommissioning planned for October 2026. New code uses the version 2 module.
  6. 6You ran git status and see orchestrate-course.json listed. What do you do?

    Answer: D. The key file holds the client secret. It belongs outside the course folder, and once .env has the values it can be deleted. If it ever reached a remote repository, create a new key and delete the old one.
  7. 7Why does every script in this topic offer --sample?

    Answer: B. Not every learner has trial or company access on day one. The --sample paths make no calls and use made-up data, so the code still runs and shows what to expect.
  8. 8Where does the course send its first prompt, and why that example?

    Answer: D. The blocked sales order is a running order-to-cash example across the course. It uses a made-up order number, so no real customer data goes to a model provider.

Sources

Sign in to track your progress

We'll email you a one-time sign-in link. No password needed.

or

Tell us a little about you

Optional, every field. It helps us pitch answers to your questions at the right level and decide which topics to write next. It is never shown publicly, and you can change or clear it anytime from the account menu.

SAP areas you work in