Orchestrate

Writing a solution design document for an AI use case

Turn an AI idea into an agreed plan with a metric, options, design, risks, cost and decisions, and check the document before anyone builds.

Updated Oct 2, 2026Foundational 9 minDeep 35 min
Foundational layer · 9 min read

The 60-second version

A solution design document (SDD) is the short, written plan a team agrees on before it builds. It says what problem is being solved, how success will be measured, which options were compared, what the design is, what could go wrong and what it will cost.

For AI, the document has extra work to do. A model can be wrong, so the plan must say who checks its answers and how the team will test quality. A model is billed per use and can be retired by its provider, so the plan must name the cost and the replacement path. And the AI touches company data, so it must say whose permissions apply.

Writing it takes days, not weeks, and it is the cheapest point to find a flaw: a sentence is easier to change than a deployed service.

Why it matters to the business

AI pilots often stall on things nobody wrote down: no baseline to prove improvement, a late security review, an unestimated cost, or a model that disappears from the catalog.

Take the course's running example, blocked sales orders in order-to-cash. Over this unit, the team built an AI API that explains why an order is blocked, a CAP extension that clerks use, and a deployment on SAP BTP. Before that work goes in front of the order desk, a design document answers questions the business will ask anyway:

  • Is it worth it? "Cut the time a clerk needs to understand a block from 12 minutes to 4" can be measured. "Make the order desk more efficient" can't.
  • Why not a standard feature? The document shows the options compared, including SAP's own, and why one was chosen. That stops the same debate from restarting every quarter.
  • Is it safe? It names the data sent to the model, whose SAP permissions apply, and who checks the AI's answer before anyone acts on it.
  • What will it cost to run? Model calls on SAP's generative AI hub are metered per token. The document turns expected volume into a monthly figure the budget owner can sign.
  • Who owns it after go-live? It names the on-call owner, the runbook and how the team will react when a model is retired.

It also protects the approvers: months later, the decisions and their reasons are on record.

How SAP does it

SAP doesn't sell a "design document" product. As of October 2026, it offers several ingredients that a good AI design document draws on:

  • SAP Activate. SAP's implementation method runs in six phases: Discover, Prepare, Explore, Realize, Deploy and Run. In Explore, teams run fit-to-standard workshops to check what standard SAP already covers, and record gaps in a prioritized backlog. An AI design document belongs here: after the standard has been checked, before the Realize sprints build anything.
  • SAP Architecture Center. SAP publishes reference architectures and an "AI golden path" for building generative AI applications on SAP BTP. It covers building, deploying and running such apps, including evaluation, logging and planning for model retirement. Starting from a published reference architecture saves the team from designing the basics again.
  • SAP BTP solution diagram guideline. SAP publishes diagram templates for draw.io, so architecture pictures look the same across teams and partners.
  • Clean core levels. SAP rates extensions from level A (built only on released APIs) to level D (not clean core). The design should state its level, because it decides how safely the system can be upgraded.
  • Responsible AI. SAP's own AI ethics handbook, written for SAP employees, sorts AI use cases into standard, high-risk and red line. Personal data, automated decisions or use in areas such as HR can make a use case high-risk, which brings extra review. Customers can borrow the same approach for their own designs.
  • Model rates and retirement dates. SAP's documentation points to SAP Note 3437766 for the models available in the generative AI hub, their token conversion rates and their deprecation dates. A design that depends on a model should cite it.

Writing the doc is a core FDE skill: an FDE owns a number, and the design document is where that number is first written down.

What a good AI design document contains

Use this table to review a document someone hands you. Each section answers one question; if the answer is missing, ask for it before approving the build.

Section The question it answers Who should care most
Problem and success metric What will be better, by how much, and how will we know? Process owner, sponsor
Scope and non-goals What will this release not do? Everyone, to stop scope creep
Options considered Did we check standard SAP, and why build instead? Enterprise architect, sponsor
Architecture What are the parts and how do they connect? Architects, IT operations
Data and integration Which SAP data, through which APIs, at which clean core level? SAP basis, data protection
AI design Which model, which prompt version, what happens when it fails? Tech lead
Security and authorizations Who can call it, and whose SAP permissions apply? Security
Responsible AI Which risk class? Who can overrule the AI? Do users know it's AI? Compliance, works council where relevant
Evaluation plan How many test cases, and what score allows go-live? Process owner, tech lead
Operations Who is on call, where is the runbook, how do we swap a retired model? IT operations
Cost estimate What does a month of use cost, against what value? Budget owner
Risks What could go wrong, how likely, and who owns the fix? Sponsor
Decisions What did we decide, and why? Future team members
Approvals Who signed, and when? Everyone

For a use case like blocked orders, expect about 4 to 10 pages.

Questions to ask

  • What is the baseline today, how was it measured, and what target are we committing to by when?
  • Which standard SAP options did you check first, and why were they rejected?
  • What data goes to the model? Is any of it personal data, and is it masked?
  • When the AI's answer is wrong, who notices, and what is the worst thing that can happen before they do?
  • Which risk class did you assign, and who confirmed it?
  • How many test cases decide go-live, and who wrote the correct answers?
  • What does a month of use cost at expected volume, and at twice that volume?
  • Which model does this depend on, when could it be retired, and how will we test its replacement?

Common misconceptions

  • "Design documents are for waterfall projects." A design document records decisions and reasons; it doesn't fix a project plan. Agile teams use them to agree before a sprint builds the wrong thing.
  • "The vendor's reference architecture is our design." A reference architecture shows a pattern. Your design adds your metric, your data, your permissions, your cost and your risks.
  • "We'll measure success after go-live." Without a baseline taken before the change, there is nothing to compare against.
  • "AI cost is a licence question only." Generative AI on SAP BTP is metered per use, so cost grows with volume and prompt length. The design must estimate it.
  • "Once approved, the document is done." It changes as the build teaches the team things. New decisions are added; old ones are marked as replaced, not deleted.
  • "The model choice is the big decision." Models change often. Where the AI lives, which data it sees and who checks its answers usually matter more and last longer.

Key terms

  • Solution design document (SDD): the agreed, written plan for a solution: problem, metric, options, design, risks, cost and decisions.
  • Baseline: the measured value of the success metric before the change.
  • Non-goal: something the team states it will not do in this release.
  • Architecture decision record (ADR): a short record of one decision: its context, the decision, its consequences and its status.
  • Fit-to-standard: SAP Activate's check of what the standard product already covers before anything is built.
  • Reference architecture: a published, reusable design pattern, such as those in the SAP Architecture Center.
  • Clean core level: SAP's rating of an extension from A (released APIs only) to D (not clean core).
  • Risk class: in SAP's AI ethics approach, standard, high-risk or red line; it decides how much review a use case needs.
  • Human oversight: the people and steps that check, and can overrule, what the AI produces.
  • Token: the unit in which model input and output are counted and billed.

Check yourself

Pick one answer for each question. The explanation appears after you choose.
  1. 1A sponsor asks why the team should write a design document before building the blocked-order explainer. What is the strongest reason?

    Answer: B. A sentence is cheaper to change than a deployed service, so problems found in the document cost least. SAP doesn't require a document to use BTP, and the document plans testing rather than replacing it.
  2. 2Which success statement belongs in a good AI design document?

    Answer: C. A useful metric has a measured baseline, a target and a date, so improvement can be proven. "More efficient" can't be measured, and the model choice is a means, not the goal.
  3. 3Where does an AI design document fit in SAP Activate?

    Answer: A. Explore is where fit-to-standard shows what the standard covers and gaps go into the backlog. The design document then plans the gap's solution before Realize builds it.
  4. 4A design document for an HR screening assistant marks the use case as "standard" risk. What should a reviewer do?

    Answer: D. SAP's ethics approach treats personal data, automated decisions and areas such as HR as high-risk triggers, which bring extra review. A different model doesn't change the use case's risk.
  5. 5The team says the generative AI hub "is already licensed", so the document needs no cost section. What is wrong with that?

    Answer: B. SAP meters generative AI in tokens that convert to capacity units, so each call has a cost that rises with volume and prompt length. The budget owner needs a monthly figure before approving.
  6. 6The model the design depends on gets a deprecation date. What should the document already contain?

    Answer: D. Models get retired, so the operations section should name who watches deprecation dates (SAP Note 3437766 lists them) and how a replacement is tested before switching. In-house training is rarely the answer.
  7. 7A partner presents SAP's reference architecture slide as their solution design. What is missing?

    Answer: C. A reference architecture is a reusable pattern. The design must apply it to your process, with your data, your security, your numbers and the decisions you made.
Deep layer · 35 min read

Mental model: a design document is a list of decisions you can still change cheaply

A design document is not a description of code. It is a set of decisions, each with its reasons, written early enough that a reviewer can change them with a comment instead of a rewrite. Malte Ubl's account of design docs at Google puts the emphasis on trade-offs: if a design has none, it probably didn't need a document.

For an AI use case, three kinds of decision need more care than in ordinary software:

  1. How you will know it works. Model output varies, so "it passed the demo" proves nothing. The document fixes a test set and a pass threshold before the build, while nobody has an incentive to lower the bar.
  2. What happens when it's wrong. Every AI feature is sometimes wrong. The document says who checks the output, what the fallback is, and the worst outcome if a wrong answer is acted on.
  3. What it depends on that can change. The model, its price and its availability belong to someone else. The document names the dependency and the plan for when it changes.

Everything else, from the diagram to the cost table, supports those decisions.

How it works

The lifecycle of a design document

A design document moves through a few stages. Ubl describes them as writing and fast iteration with close colleagues, a wider review, updates during implementation, and later use as a record for new team members.

flowchart LR
  D[Draft with<br/>close team] --> R[Review by<br/>owners and experts]
  R -->|changes| D
  R --> A[Approved]
  A --> B[Build in sprints]
  B -->|new decision| N[Add an ADR]
  N --> B
  B --> L[Living record<br/>after go-live]

Two rules keep it useful. First, update it when the build teaches you something; a document that disagrees with the system is worse than none. Second, keep decisions append-only: you add new records and mark old ones as replaced, so the history stays readable.

Sections that matter most for AI

The general shape of a design document is common: context and scope, goals and non-goals, the design, alternatives considered, and cross-cutting concerns such as security and privacy. The course template keeps that shape and adds sections AI work needs:

Section What it must contain Why AI makes it harder
Problem and success metric Metric, baseline with method, target with date Without a baseline, a fluent model looks like an improvement even when it isn't
Options considered At least one standard SAP option, and the chosen one marked SAP ships AI features each release; the check goes stale
Data and integration APIs, fields sent to the model, clean core level Prompts carry business data out of the system
AI design Model, prompt version, output format, fallback The model can fail, time out or be retired
Security and authorizations Callers, whose SAP permissions apply, where secrets live An AI layer can see more than the user it serves
Responsible AI Risk class, personal data, human oversight, transparency Wrong answers can harm people, not just processes
Evaluation plan Test set size and source, pass threshold, monitoring Quality is statistical, so it needs a number
Operations Owner, runbook, model lifecycle Model retirement is a scheduled outage you must plan for
Cost estimate Volume, tokens per request, your rates, runtime Cost scales with use and prompt length

Architecture decision records

Some decisions deserve their own short record. The architecture decision record (ADR) format, introduced by Michael Nygard, has a title, a date, a status, the context, the decision and its consequences. Status is one of proposed, accepted, rejected, deprecated or superseded. Consequences list the good, the neutral and the bad.

ADRs are not edited after acceptance. When a decision changes, you write a new ADR, mark the old one as superseded and link the two. That keeps the reasoning of the time visible, which is exactly what a new team member or an auditor needs.

Typical ADRs for an SAP AI use case: where the AI lives (embedded, Joule, side by side on BTP, or outside SAP), whether user permissions are passed through to SAP, which fallback to use, and whether to call the model directly or through SAP's orchestration service.

Diagrams

A design needs one context diagram: users, the new parts, the SAP systems and the model, with arrows for calls. A mermaid flowchart in the document is enough for review. For diagrams that go to customers or architecture boards, SAP's BTP solution diagram guideline offers official templates for draw.io, so shapes and colors match what SAP architects use.

How long?

Ubl suggests 10 to 20 pages for large projects and 1 to 3 pages for small, incremental changes. He also says to skip the document when the solution is obvious and nothing needs a trade-off. A single AI use case on an existing platform usually lands in between: 4 to 10 pages, plus ADRs.

Build it yourself: write and check a design document for blocked orders

You will create a design document from a template, compare it with a filled example for the blocked-order explainer, and run a small checker. The checker finds missing sections, leftover placeholders, a missing baseline, risks without owners and incomplete decision records. It also turns your volume and rate inputs into a monthly cost. Optionally, a model reviews the document and lists its five biggest gaps.

flowchart LR
  T[--new<br/>blank template] --> D[solution_design.md<br/>you write it]
  S[--sample<br/>filled example] -.compare.-> D
  D --> C[sdd_check.py<br/>checks + cost]
  C -->|--llm, optional| O[SAP orchestration<br/>service: review]

Before you start: complete Set up your computer for this course and Set up for Unit 6. They create your orchestrate-course folder with its .venv. For the optional model review (Step 6) you also need Set up for Unit 5, which puts the AICORE_ lines in .env and installs sap-ai-sdk-gen. This walkthrough doesn't repeat those steps.

What you need

  • Your course folder with the Unit 6 setup done.
  • About 45 to 60 minutes to run the steps, plus time to write your own document.
  • Cost: free. Step 6 makes one model call, a small per-request charge on a paid SAP AI Core account; on a trial, check what your plan allows.
  • The deployment_runbook.md you wrote in Deploying AI apps on SAP BTP helps but isn't required.

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
  4. Check that Python answers:

    python --version

    You should see Python 3. followed by a version number. The checker uses only built-in modules, so there is nothing to install.

Run every command in this topic from the course folder.

Step 2: Save the checker

  1. In VS Code's file list, right-click unit06, choose New File, name it sdd_check.py, paste the code below and save.
"""Write, check and cost a solution design document (SDD) for an AI use case.

  python unit06/sdd_check.py --new unit06/solution_design.md      write a blank template
  python unit06/sdd_check.py --sample unit06/sample_design.md     write a filled example
  python unit06/sdd_check.py unit06/sample_design.md              check a document and estimate cost
  python unit06/sdd_check.py unit06/sample_design.md --llm        also ask a model for a review

--llm needs the AICORE_ lines in .env from "Set up for Unit 5". Everything else needs only Python.
"""
import argparse
import re
import sys
from pathlib import Path

FENCE = "`" * 3   # three backticks, built here so this file can sit inside a markdown page

SECTIONS = ["Summary", "Problem and success metric", "Scope and non-goals", "Users and process",
            "Options considered", "Architecture", "Data and integration", "AI design",
            "Security and authorizations", "Responsible AI", "Evaluation plan", "Operations",
            "Cost estimate", "Risks", "Decisions", "Open questions", "Approvals"]

ADR_STATUSES = {"proposed", "accepted", "rejected", "deprecated", "superseded"}
RISK_CLASSES = {"standard", "high-risk", "red line"}

TEMPLATE = f"""# Solution design: TODO name of the use case

Version: 0.1 (draft) · Author: TODO · Last changed: TODO date

## Summary

TODO: three sentences. The problem, the proposed AI solution, the number it should move.

## Problem and success metric

TODO: who has the problem today, in which SAP process, and what it costs.

- Metric: TODO what you will measure
- Baseline: TODO today's value, with a number and how you measured it
- Target: TODO the value you promise, with a number and a date
- Measured by: TODO where the number comes from (report, log, sample)

## Scope and non-goals

In scope:

- TODO

Non-goals:

- TODO what this release will not do, so nobody expects it

## Users and process

TODO: who uses it, at which step of the process, and what they do with the answer.

## Options considered

| Option | Pros | Cons | Verdict |
| --- | --- | --- | --- |
| TODO standard SAP feature | TODO | TODO | TODO write chosen or rejected |
| TODO your own build | TODO | TODO | TODO write chosen or rejected |

## Architecture

TODO: one paragraph, then a diagram.

{FENCE}mermaid
flowchart LR
  U[TODO user] --> A[TODO app]
  A --> S[TODO SAP system]
{FENCE}

## Data and integration

- SAP APIs used: TODO name each API and whether it is released
- Data sent to the model: TODO fields, and whether any are personal data
- Clean core level: TODO A, B, C or D

## AI design

- Model: TODO
- Prompt version: TODO
- Output format: TODO
- Fallback: TODO what happens when the model fails or times out

## Security and authorizations

- Who may call: TODO
- Whose authorizations apply to SAP data: TODO
- Secrets: TODO where keys live (never in this document)

## Responsible AI

- Risk class: TODO standard, high-risk or red line
- Personal data: TODO
- Human oversight: TODO who checks or can overrule the AI
- Transparency: TODO how users know an answer came from AI

## Evaluation plan

- Test set: TODO how many cases, from where
- Pass threshold: TODO the score that allows go-live
- Monitoring after go-live: TODO

## Operations

- Owner: TODO the person or team on call
- Runbook: TODO link
- Model lifecycle: TODO how you learn about model retirement and switch

## Cost estimate

| Input | Value |
| --- | --- |
| Requests per working day | TODO |
| Working days per month | TODO |
| Input tokens per request | TODO |
| Output tokens per request | TODO |
| Price per 1M input tokens | TODO from your rate card |
| Price per 1M output tokens | TODO from your rate card |
| Runtime cost per month | TODO |
| Currency | TODO |
| Minutes saved per request | TODO optional |
| Staff cost per hour | TODO optional |

## Risks

| Risk | Likelihood | Impact | Mitigation | Owner |
| --- | --- | --- | --- | --- |
| TODO | TODO | TODO | TODO | TODO |

## Decisions

### ADR-1: TODO title

- Status: TODO proposed, accepted, rejected, deprecated or superseded
- Context: TODO
- Decision: TODO
- Consequences: TODO

## Open questions

- TODO

## Approvals

| Role | Name | Date |
| --- | --- | --- |
| Process owner | TODO | |
| Security | TODO | |
"""

SAMPLE = f"""# Solution design: blocked-order explainer

Version: 0.3 (draft) · Author: course learner · Last changed: 2026-10-02

> Example for a made-up company. Every number, name and price in it is invented for practice.

## Summary

Clerks at the order desk spend too long finding out why a sales order is blocked. An AI service reads
the order through released SAP APIs and explains the block in plain words, with a suggested next step.
The goal is to cut the time a clerk needs to understand a block from 12 minutes to 4.

## Problem and success metric

About 400 sales orders a day stop on a delivery or credit block. A clerk opens several screens to see why,
then emails sales or credit management. Customers wait and clerks lose most of a morning.

- Metric: median clerk minutes to understand why an order is blocked
- Baseline: 12 minutes (timed sample of 60 orders, two weeks in September)
- Target: 4 minutes by end of Q1, with no drop in correct next steps
- Measured by: the same timed sample, repeated after four weeks of use

## Scope and non-goals

In scope:

- Explaining delivery and credit blocks on standard sales orders
- Suggesting one next step from a fixed list

Non-goals:

- Releasing or changing any order (only people with the right SAP role do that)
- Returns, consignment and intercompany orders

## Users and process

Order-desk clerks in order-to-cash, at the step where they work through the list of blocked orders.
They read the explanation, check it against the order, then act in SAP as they do today.

## Options considered

| Option | Pros | Cons | Verdict |
| --- | --- | --- | --- |
| Standard SAP AI feature | No build; SAP maintains it | None found for this exact need in our release | rejected for now; recheck each release |
| Joule agent | Inside SAP's own user experience | Needs Joule Studio skills we don't have yet | rejected for release 1 |
| CAP extension on SAP BTP with our AI API | Clean core; reuses Unit 6 work; full control | We own operations and cost | chosen |

## Architecture

The CAP extension reads the order through a released API, calls the AI API, stores the explanation and
returns it to the clerk. The AI API calls the model through SAP's orchestration service.

{FENCE}mermaid
flowchart LR
  C[Clerk] --> X[CAP extension on BTP]
  X -->|released OData API| S[SAP S/4HANA]
  X --> A[AI API on Cloud Foundry]
  A --> O[Orchestration service]
  O --> M[Model]
{FENCE}

## Data and integration

- SAP APIs used: Sales Order (A2X), released; read only
- Data sent to the model: order number, block reason, amounts, dates, customer name; no contact details
- Clean core level: A

## AI design

- Model: chosen from the generative AI hub; name recorded per release
- Prompt version: explain-v3, stored in Git with the code
- Output format: JSON with explanation and next_step, checked against a schema
- Fallback: a fixed-rule explanation from the block reason when the model fails or times out after 30 seconds

## Security and authorizations

- Who may call: clerks with the order-desk role, through company sign-in
- Whose authorizations apply to SAP data: the clerk's own, passed through to SAP
- Secrets: in a bound service on BTP; rotated every 90 days

## Responsible AI

- Risk class: standard (no automated decision; customer names are business data, contact details excluded)
- Personal data: customer names only; masked before the model call
- Human oversight: the clerk decides every action; the AI cannot change an order
- Transparency: every explanation is labelled "AI-generated, check before acting"

## Evaluation plan

- Test set: 120 past blocked orders with a correct explanation written by two senior clerks
- Pass threshold: 90% of explanations judged correct, and 100% of next steps from the allowed list
- Monitoring after go-live: clerks rate each explanation; weekly review of every "not helpful"

## Operations

- Owner: order-to-cash product team, business hours support
- Runbook: unit06/deployment_runbook.md
- Model lifecycle: check SAP Note 3437766 monthly for deprecation dates; test the replacement on the test set

## Cost estimate

| Input | Value |
| --- | --- |
| Requests per working day | 400 |
| Working days per month | 21 |
| Input tokens per request | 1,200 |
| Output tokens per request | 250 |
| Price per 1M input tokens | 0.50 (example, not a real price) |
| Price per 1M output tokens | 2.00 (example, not a real price) |
| Runtime cost per month | 150 (example) |
| Currency | EUR |
| Minutes saved per request | 8 |
| Staff cost per hour | 40 (example) |

## Risks

| Risk | Likelihood | Impact | Mitigation | Owner |
| --- | --- | --- | --- | --- |
| Explanation is wrong and a clerk acts on it | Medium | Medium | Label as AI; clerk checks; weekly review of ratings | Product owner |
| Model is retired by the provider | High | Medium | Monthly check of SAP Note 3437766; re-run test set on replacement | Tech lead |
| Token cost grows with volume | Low | Low | Monthly cost report; cache repeated orders | Tech lead |

## Decisions

### ADR-1: Build side by side on SAP BTP, not inside S/4HANA

- Status: accepted
- Context: no standard feature covers the need; we must keep the core clean
- Decision: a CAP extension that reads released APIs and calls our AI API
- Consequences: clean core level A; we own a BTP app, its cost and its on-call

### ADR-2: Keep a rule-based fallback

- Status: accepted
- Context: the model can time out or be unavailable; clerks still need an answer
- Decision: return a fixed explanation from the block reason when the model fails
- Consequences: clerks always get an answer; fallback answers are less helpful and are counted

## Open questions

- Should credit managers get a different explanation from clerks?

## Approvals

| Role | Name | Date |
| --- | --- | --- |
| Process owner | (example) Head of order desk | |
| Security | (example) BTP security lead | |
"""


# ---------- reading the document ----------

def split_sections(text: str) -> dict:
    """Map each '## ' heading (lower case) to the text below it."""
    sections, current = {}, None
    for line in text.splitlines():
        if line.startswith("## "):
            current = line[3:].strip().lower()
            sections[current] = []
        elif current is not None:
            sections[current].append(line)
    return {k: "\n".join(v) for k, v in sections.items()}


def field(section: str, name: str) -> str:
    """Return the text after '- Name:' in a section, or ''."""
    match = re.search(rf"^\s*-?\s*{re.escape(name)}:\s*(.*)$", section, re.IGNORECASE | re.MULTILINE)
    value = match.group(1).strip() if match else ""
    return "" if value.upper().startswith("TODO") else value


def table_rows(section: str) -> list:
    """Return the data rows of the first markdown table in a section, as lists of cell texts."""
    rows = [line for line in section.splitlines() if line.strip().startswith("|")]
    cells = [[c.strip() for c in row.strip().strip("|").split("|")] for row in rows]
    return [r for r in cells[1:] if not all(set(c) <= set("-: ") for c in r)]


def number(text: str):
    """The first number in a cell, ignoring thousands separators; None if there is none."""
    match = re.search(r"\d[\d,]*(\.\d+)?", text)
    return float(match.group(0).replace(",", "")) if match else None


# ---------- the checks ----------

def check(text: str) -> tuple:
    """Run every check. Returns (results, sections), where results are (level, name, message)."""
    s = split_sections(text)
    get = lambda name: s.get(name.lower(), "")
    results = []
    add = lambda level, name, msg: results.append((level, name, msg))

    missing = [name for name in SECTIONS if name.lower() not in s]
    add("FAIL" if missing else "OK", "Sections",
        "missing: " + ", ".join(missing) if missing else f"all {len(SECTIONS)} present")

    todo_lines = [i for i, line in enumerate(text.splitlines(), 1) if "TODO" in line]
    add("FAIL" if todo_lines else "OK", "Placeholders",
        f"{len(todo_lines)} lines still say TODO (first on line {todo_lines[0]})" if todo_lines else "none left")

    secret = re.search(r"(?i)(secret|password|api[ _-]?key|token)\s*[:=]\s*\S{20,}", text)
    add("FAIL" if secret else "OK", "Secrets",
        "something that looks like a key is in the document; remove it and rotate it" if secret
        else "no keys or passwords found in the text")

    problem = get("Problem and success metric")
    base, target, by = field(problem, "Baseline"), field(problem, "Target"), field(problem, "Measured by")
    if number(base) is not None and number(target) is not None and by:
        add("OK", "Success metric", f"from {base.split('(')[0].strip()} to {target.split(',')[0].strip()}")
    else:
        add("FAIL", "Success metric", "needs Baseline and Target lines with numbers, and Measured by")

    scope = get("Scope and non-goals")
    non_goals = scope.lower().split("non-goals:")[-1] if "non-goals:" in scope.lower() else ""
    listed = re.search(r"^\s*- (?!todo)\S", non_goals, re.MULTILINE)
    add("OK" if listed else "WARN", "Non-goals", "listed" if listed else "none listed; say what this release will not do")

    options = table_rows(get("Options considered"))
    chosen = [r for r in options if "chosen" in r[-1].lower() and "TODO" not in r[-1]]
    if len(options) < 2:
        add("FAIL", "Options", f"{len(options)} option(s); compare at least two, including a standard SAP one")
    elif len(chosen) != 1:
        add("FAIL", "Options", f"{len(chosen)} rows say 'chosen'; exactly one should")
    else:
        add("OK", "Options", f"{len(options)} compared, chosen: {chosen[0][0]}")

    add("OK" if "mermaid" in get("Architecture") else "WARN", "Diagram",
        "found" if "mermaid" in get("Architecture") else "no diagram in Architecture")

    level = field(get("Data and integration"), "Clean core level").upper()[:1]
    if level not in {"A", "B", "C", "D"}:
        add("FAIL", "Clean core", "needs 'Clean core level: A, B, C or D'")
    else:
        add("OK" if level in {"A", "B"} else "WARN", "Clean core",
            f"level {level}" + ("" if level in {"A", "B"} else "; explain why, and plan to move up"))

    ai = get("AI design")
    add("OK" if field(ai, "Fallback") else "FAIL", "Fallback",
        "described" if field(ai, "Fallback") else "say what happens when the model fails")

    sec = get("Security and authorizations")
    gaps = [n for n in ("Who may call", "Whose authorizations apply to SAP data", "Secrets") if not field(sec, n)]
    add("WARN" if gaps else "OK", "Security", "missing: " + ", ".join(gaps) if gaps else "callers, SAP authorizations and secrets covered")

    rai = get("Responsible AI")
    risk_class = field(rai, "Risk class").lower()
    found = next((c for c in RISK_CLASSES if risk_class.startswith(c)), None)
    approvals_text = get("Approvals").lower()
    if not found:
        add("FAIL", "Risk class", "needs 'Risk class: standard, high-risk or red line'")
    elif found == "red line":
        add("FAIL", "Risk class", "red line: this use case should not be built")
    elif found == "high-risk" and not any(w in approvals_text for w in ("privacy", "ethics", "legal")):
        add("FAIL", "Risk class", "high-risk needs a privacy, ethics or legal approver in Approvals")
    else:
        add("OK", "Risk class", found)
    add("OK" if field(rai, "Human oversight") else "FAIL", "Human oversight",
        "described" if field(rai, "Human oversight") else "say who checks or can overrule the AI")

    ev = get("Evaluation plan")
    ok = number(field(ev, "Test set")) is not None and number(field(ev, "Pass threshold")) is not None
    add("OK" if ok else "FAIL", "Evaluation", "test set and pass threshold have numbers" if ok
        else "needs 'Test set:' and 'Pass threshold:' lines with numbers")

    ops = get("Operations")
    gaps = [n for n in ("Owner", "Runbook", "Model lifecycle") if not field(ops, n)]
    add("WARN" if gaps else "OK", "Operations", "missing: " + ", ".join(gaps) if gaps else "owner, runbook and model lifecycle named")

    risks = table_rows(get("Risks"))
    incomplete = [r[0] for r in risks if len(r) < 5 or not r[3] or not r[4]]
    if len(risks) < 3 or incomplete:
        add("FAIL", "Risks", f"{len(risks)} listed, {len(incomplete)} without mitigation or owner; aim for 3 or more, all complete")
    else:
        add("OK", "Risks", f"{len(risks)} listed, each with a mitigation and an owner")

    adrs = re.split(r"^### ", get("Decisions"), flags=re.MULTILINE)[1:]
    bad = []
    for adr in adrs:
        status = field(adr, "Status").lower().split()[0] if field(adr, "Status") else ""
        if status not in ADR_STATUSES or not all(field(adr, n) for n in ("Context", "Decision", "Consequences")):
            bad.append(adr.splitlines()[0][:40])
    if not adrs or bad:
        add("FAIL", "Decisions", "no decision records" if not adrs else "incomplete: " + "; ".join(bad))
    else:
        add("OK", "Decisions", f"{len(adrs)} recorded with status, context, decision and consequences")

    dated = [r for r in table_rows(get("Approvals")) if len(r) > 2 and re.search(r"\d{4}-\d{2}-\d{2}", r[2])]
    add("OK" if dated else "INFO", "Approvals", f"{len(dated)} signed" if dated else "none signed yet (still a draft)")
    return results, s


def cost(section: str) -> list:
    """Turn the cost table into report lines. Prices are the reader's inputs, never SAP's."""
    values = {r[0].lower(): r[1] for r in table_rows(section) if len(r) > 1}
    find = lambda start: next((v for k, v in values.items() if k.startswith(start)), "")
    keys = {"per_day": "requests per working day", "days": "working days per month",
            "tok_in": "input tokens per request", "tok_out": "output tokens per request",
            "p_in": "price per 1m input tokens", "p_out": "price per 1m output tokens",
            "runtime": "runtime cost per month"}
    n = {k: number(find(v)) for k, v in keys.items()}
    missing = [keys[k] for k, v in n.items() if v is None]
    if missing:
        return ["Cost estimate skipped. Missing numbers for: " + ", ".join(missing)]
    cur = find("currency") or ""
    requests = n["per_day"] * n["days"]
    t_in, t_out = requests * n["tok_in"], requests * n["tok_out"]
    model = t_in / 1e6 * n["p_in"] + t_out / 1e6 * n["p_out"]
    total = model + n["runtime"]
    lines = ["Cost estimate (from your inputs; prices are yours, not SAP's):",
             f"  Requests per month:      {requests:,.0f}",
             f"  Model tokens per month:  {t_in + t_out:,.0f} ({t_in:,.0f} in, {t_out:,.0f} out)",
             f"  Model cost per month:    {model:,.2f} {cur}",
             f"  Runtime cost per month:  {n['runtime']:,.2f} {cur}",
             f"  Total per month:         {total:,.2f} {cur}",
             f"  Cost per request:        {total / requests:,.4f} {cur}" if requests else ""]
    minutes, rate = number(find("minutes saved per request")), number(find("staff cost per hour"))
    if minutes is not None and rate is not None:
        value = requests * minutes / 60 * rate
        lines.append(f"  Time value per month:    {value:,.2f} {cur} ({requests * minutes / 60:,.0f} staff hours)")
        lines.append("  Time saved is not cash saved: say what the team will do with the hours.")
    return [line for line in lines if line]


# ---------- optional model review ----------

REVIEW_SYSTEM = ("You review solution design documents for AI use cases on SAP as a senior solution architect. "
                 "List the five most important gaps or risks in the document, most serious first. For each, "
                 "give one line on the problem and one line on the fix. Use only what the document says; "
                 "if something is missing, say it is missing. Do not praise the document.")
REVIEW_USER = "<document>\n{{?doc}}\n</document>"


def llm_review(text: str, model_name: str) -> str:
    """Ask a model for a reviewer's critique through SAP's orchestration service (version 2)."""
    import os
    from dotenv import load_dotenv
    load_dotenv()
    needed = ["AICORE_CLIENT_ID", "AICORE_CLIENT_SECRET", "AICORE_AUTH_URL", "AICORE_BASE_URL",
              "AICORE_RESOURCE_GROUP"]
    missing = [n for n in needed if not os.environ.get(n)]
    if missing:
        return "Review skipped. Missing in .env: " + ", ".join(missing) + ". See 'Set up for Unit 5', Step 5."
    try:
        from gen_ai_hub.orchestration_v2 import (LLMModelDetails, ModuleConfig, OrchestrationConfig,
                                                 OrchestrationError, OrchestrationService,
                                                 PromptTemplatingModuleConfig, SystemMessage, Template,
                                                 UserMessage)
    except ImportError:
        return "Review skipped. The SAP Cloud SDK for AI isn't installed: see 'Set up for Unit 5', Step 2."
    template = Template(template=[SystemMessage(content=REVIEW_SYSTEM), UserMessage(content=REVIEW_USER)])
    config = OrchestrationConfig(modules=ModuleConfig(prompt_templating=PromptTemplatingModuleConfig(
        prompt=template, model=LLMModelDetails(name=model_name, params={"max_tokens": 700},
                                               timeout=60, max_retries=1))))
    try:
        response = OrchestrationService(config=config).run(placeholder_values={"doc": text})
    except OrchestrationError as error:
        return f"Review failed: orchestration error {error.code}: {error.message}"
    except Exception as error:   # network errors, timeouts, expired credentials
        return f"Review failed: {type(error).__name__}. Run python check_unit05.py to find the cause."
    return response.final_result.choices[0].message.content or "(empty answer)"


# ---------- command line ----------

def write_new(path: Path, content: str, what: str) -> None:
    if path.exists():
        sys.exit(f"{path} already exists. Choose another name, so your work isn't overwritten.")
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")
    print(f"Wrote {what} to {path}. Open it in VS Code, then check it with:\n  python unit06/sdd_check.py {path}")


def main() -> None:
    parser = argparse.ArgumentParser(description="Write, check and cost a solution design document.")
    parser.add_argument("doc", nargs="?", help="the design document to check")
    parser.add_argument("--new", metavar="FILE", help="write a blank template to FILE")
    parser.add_argument("--sample", metavar="FILE", help="write a filled example to FILE")
    parser.add_argument("--llm", action="store_true", help="also ask a model for a review (needs SAP AI Core)")
    parser.add_argument("--model", default="gpt-4o-mini", help="model name for --llm")
    args = parser.parse_args()

    if args.new:
        return write_new(Path(args.new), TEMPLATE, "a blank template")
    if args.sample:
        return write_new(Path(args.sample), SAMPLE, "the example design")
    if not args.doc:
        parser.error("give a document to check, or use --new or --sample")
    path = Path(args.doc)
    if not path.exists():
        sys.exit(f"Can't find {path}. Run from your orchestrate-course folder, or create it with --new.")
    text = path.read_text(encoding="utf-8")

    results, sections = check(text)
    print(f"Checking {path}\n")
    for level, name, message in results:
        print(f"{level:<5} {name + ':':<17} {message}")
    print()
    for line in cost(sections.get("cost estimate", "")):
        print(line)
    problems = sum(1 for r in results if r[0] == "FAIL")
    warnings = sum(1 for r in results if r[0] == "WARN")
    print(f"\nResult: {problems} problem(s), {warnings} warning(s). "
          + ("Ready for review." if problems == 0 else "Fix the FAIL lines, then run this again."))
    if args.llm:
        print("\nModel review (a second opinion, not a sign-off):\n")
        print(llm_review(text, args.model))
    sys.exit(1 if problems else 0)


if __name__ == "__main__":
    main()
  1. Check that it starts:

    python unit06/sdd_check.py --help

    You should see a usage line that starts with usage: sdd_check.py and lists --new, --sample, --llm and --model.

Step 3: Write the example and check it (no account needed)

  1. Write the filled example for the blocked-order explainer:

    python unit06/sdd_check.py --sample unit06/sample_design.md
    Wrote the example design to unit06/sample_design.md. Open it in VS Code, then check it with:
      python unit06/sdd_check.py unit06/sample_design.md
  2. Open unit06/sample_design.md in VS Code. To see it formatted, press Ctrl+Shift+V (Windows) or Cmd+Shift+V (macOS). Read it once from top to bottom: it is about five pages, the size this topic recommends.

  3. Check it:

    python unit06/sdd_check.py unit06/sample_design.md
    Checking unit06/sample_design.md
    
    OK    Sections:         all 17 present
    OK    Placeholders:     none left
    OK    Secrets:          no keys or passwords found in the text
    OK    Success metric:   from 12 minutes to 4 minutes by end of Q1
    OK    Non-goals:        listed
    OK    Options:          3 compared, chosen: CAP extension on SAP BTP with our AI API
    OK    Diagram:          found
    OK    Clean core:       level A
    OK    Fallback:         described
    OK    Security:         callers, SAP authorizations and secrets covered
    OK    Risk class:       standard
    OK    Human oversight:  described
    OK    Evaluation:       test set and pass threshold have numbers
    OK    Operations:       owner, runbook and model lifecycle named
    OK    Risks:            3 listed, each with a mitigation and an owner
    OK    Decisions:        2 recorded with status, context, decision and consequences
    INFO  Approvals:        none signed yet (still a draft)
    
    Cost estimate (from your inputs; prices are yours, not SAP's):
      Requests per month:      8,400
      Model tokens per month:  12,180,000 (10,080,000 in, 2,100,000 out)
      Model cost per month:    9.24 EUR
      Runtime cost per month:  150.00 EUR
      Total per month:         159.24 EUR
      Cost per request:        0.0190 EUR
      Time value per month:    44,800.00 EUR (1,120 staff hours)
      Time saved is not cash saved: say what the team will do with the hours.
    
    Result: 0 problem(s), 0 warning(s). Ready for review.

    INFO isn't a problem: a draft has no signatures yet. "Ready for review" means the document is complete enough for people to read, not that it is right.

Step 4: See what failure looks like

Make three mistakes on purpose in the example, so you know what the checker catches.

  1. In unit06/sample_design.md, change Risk class: standard to Risk class: high-risk.

  2. Change Clean core level: A to Clean core level: C.

  3. In the Risks table, delete the text Tech lead from the last row, leaving the cell empty (| |). Save.

  4. Check again:

    python unit06/sdd_check.py unit06/sample_design.md

    Among the OK lines you now see:

    WARN  Clean core:       level C; explain why, and plan to move up
    FAIL  Risk class:       high-risk needs a privacy, ethics or legal approver in Approvals
    FAIL  Risks:            3 listed, 1 without mitigation or owner; aim for 3 or more, all complete
    ...
    Result: 2 problem(s), 1 warning(s). Fix the FAIL lines, then run this again.
  5. Undo the three changes (Ctrl+Z or Cmd+Z in VS Code), save, and check again until it says Ready for review.

A FAIL sets exit code 1, so a pipeline can refuse to move on. A WARN is a question for the reviewer: level C can be acceptable, but the document must say why.

Step 5: Start your own document

  1. Write a blank template:

    python unit06/sdd_check.py --new unit06/solution_design.md
  2. Check it straight away, to see the to-do list:

    python unit06/sdd_check.py unit06/solution_design.md
    OK    Sections:         all 17 present
    FAIL  Placeholders:     55 lines still say TODO (first on line 1)
    ...
    Result: 10 problem(s), 2 warning(s). Fix the FAIL lines, then run this again.

    This is the valid "empty" result: every section is there and nothing is filled in. The Exercise below walks you through filling it.

Neither --new nor --sample overwrites an existing file, so you can't lose your work by running them twice.

Step 6 (optional): Ask a model for a review

This step needs the AICORE_ lines in .env from Set up for Unit 5. It sends the whole document to the model, one call.

  1. Run the check with a review:

    python unit06/sdd_check.py unit06/sample_design.md --llm
  2. After the usual check lines you see a section like this (the model's wording will differ):

    Model review (a second opinion, not a sign-off):
    
    1. Problem: the evaluation plan has no test for orders with several blocks at once.
       Fix: add such orders to the test set and state the expected explanation.
    ...

    If your account doesn't offer gpt-4o-mini, run python check_unit05.py to list usable models and add --model MODEL_NAME.

Treat the review as one more reviewer's comments. Some points will be wrong or already covered; decide each one yourself.

What the code does

Part What it does
SECTIONS The 17 headings every document must have, in order
TEMPLATE and SAMPLE The blank template and the filled blocked-order example that --new and --sample write
split_sections Splits the document at each ## heading
field Reads a - Name: value line in a section; TODO counts as empty
table_rows Reads the rows of the first table in a section
check Runs every check and returns OK, WARN, FAIL or INFO lines
Secrets check Fails if something that looks like a key or password is in the text
Risk class check Fails on red line; for high-risk, demands a privacy, ethics or legal approver
cost Turns volume, tokens per request and your rates into a monthly figure, plus the value of time saved
llm_review Optional: sends the document to a model through SAP's orchestration service (version 2) and prints its critique
write_new Writes the template or example, refusing to overwrite an existing file
Exit code 1 when any check fails, 0 otherwise

If something goes wrong

What you see What it means What to do
python is not recognized, or command not found Python isn't on PATH, or .venv is off Turn on .venv (Step 1); see Set up your computer if Python itself is missing
can't open file ... sdd_check.py You're not in the course folder, or the file has another name Open orchestrate-course in VS Code; check the file is unit06/sdd_check.py
Can't find unit06/solution_design.md The document doesn't exist yet, or you're in another folder Run Step 5, or check the path
... already exists. Choose another name --new or --sample protects your file Use another file name, or delete the old file if you really want a fresh copy
Cost estimate skipped. Missing numbers for: ... A cost row is empty or still says TODO Put a number in each named row; text after the number is fine
A section you wrote shows as missing The heading differs from the template, for example ## Risk instead of ## Risks Use the headings exactly as the template writes them
Review skipped. Missing in .env: AICORE_... The Unit 5 settings aren't in .env Follow Step 5 of Set up for Unit 5, or leave out --llm
Review skipped. The SAP Cloud SDK for AI isn't installed sap-ai-sdk-gen isn't in this .venv Follow Step 2 of Set up for Unit 5
Review failed: ... with a network or sign-in error Credentials expired, or a proxy blocks SAP's servers Run python check_unit05.py; ask IT about the proxy; the check itself still works without --llm
Review failed: orchestration error 400 or 404 The model name isn't offered in your account Use --model with a name from check_unit05.py

The SAP way

Nothing in SAP writes the design document for you. As of October 2026, these SAP resources supply its contents and its review points.

SAP Activate: where the document sits

SAP Activate has six phases: Discover, Prepare, Explore, Realize, Deploy and Run. Explore runs fit-to-standard workshops, records gaps in a prioritized product backlog, and time-boxes a high-level design for the top items. Realize then builds configuration and custom extensions in sprints.

An AI use case fits that rhythm. The fit-to-standard result goes into Options considered: it is your evidence that a standard feature doesn't cover the need. The design document is the time-boxed design for that backlog item. Its ADRs grow during Realize.

SAP Architecture Center: the starting pattern

The SAP Architecture Center's AI golden path for generative AI applications walks through build, deploy and run. Several of its recommendations map directly to document sections:

Golden path recommendation Where it goes in your document
A CAP-based backend, with Destinations for SAP connectivity and role-based access Architecture; Security and authorizations
Packaging as a multitarget application (MTA) with CI/CD Operations
Prompts managed in the Prompt Registry rather than hard-coded AI design (prompt version)
The Evaluation Service to test use cases across models Evaluation plan
Logging, tracing and metering Operations; Cost estimate
Planning for model deprecation, versioning and fallback AI design; Operations; Risks

Start from the matching reference architecture, then write down where your design differs and why. Those differences are often your most important ADRs.

Clean core levels

SAP's clean core model rates extensions A to D. Level A uses released APIs and extension points; B uses classic APIs; C touches internal objects not released for customers; D, not clean core, includes modifications and unsupported writes to SAP tables. An extension is rated by its lowest-ranked part, so one internal call drags the whole design down. The checker asks for the level and warns below B.

Responsible AI and the risk class

SAP's AI ethics handbook is written for SAP's own teams, but its classification is a practical model for customers. Teams classify a use case as red line (not to be built), high-risk or standard before they build. High-risk triggers include processing personal or sensitive personal data, automated decision making, and use in areas such as employment and HR, healthcare, public services and law enforcement. High-risk cases get additional review before they go ahead.

The handbook also sets expectations a design should answer: AI decisions can always be overruled by a human, through human-in-the-loop, human-on-the-loop or human-in-command oversight; users must be able to tell they are dealing with AI; and data and decision processes are documented for traceability. Your company's own policy and the law that applies to you come first; use SAP's model to structure the section, not to replace your compliance review.

Model dependencies, rates and dates

The generative AI hub documentation points to SAP Note 3437766 for available models, token conversion rates, rate limits and deprecation dates. SAP AI Core's documentation (September 2026 edition) explains that generative AI is metered in tokens, input and output separately, converted to capacity units with a factor per model, and that output tokens tend to cost more than input tokens.

The same documentation shows why dated dependencies belong in the document. It lists retired models with recommended replacements, and it states that version 1 of the orchestration API is scheduled for decommissioning on 31 October 2026, with workflows to move to version 2. A design that names its model and API version, and the owner who watches these notices, turns such changes into planned work.

Diagrams

SAP's BTP solution diagram guideline provides templates for draw.io (with Lucidchart and PowerPoint as alternatives), based on SAP's Horizon design principles. Use it for diagrams that leave the team; keep the mermaid diagram in the document for day-to-day review.

Build vs. SAP

Here the choice is how much of the document practice to build yourself.

Approach Use it when Watch out for
Your own markdown template and ADRs in Git (this topic) Small team, one use case, developers review in pull requests Business reviewers may not use Git; export to PDF or a wiki for them
SAP Activate deliverables and your partner's method templates A larger SAP program already runs on Activate Generic templates may lack AI sections: add evaluation, risk class, model lifecycle and token cost
SAP Architecture Center reference architecture as the base A published pattern matches your use case The pattern isn't your design; record your differences as ADRs
A company architecture board's standard template Your company requires it for any new system Map this topic's AI sections onto it rather than writing two documents

Most teams combine them: the company template as the frame, a reference architecture as the starting design, and ADRs in Git for decisions.

Production concerns

  • Version and review it like code. Keep the document and ADRs in the same repository as the solution, review changes in pull requests, and tag the version that was approved. Run sdd_check.py in the pipeline so an incomplete document fails the build.
  • Keep secrets and customer data out. The document names where secrets live, never their values. Use made-up or masked examples. The checker's secret scan is a safety net, not a guarantee.
  • Classify the document itself. A design that describes permissions, data flows and weaknesses is sensitive. Store and share it like other internal architecture documents.
  • Trace to tests. Each promise in the document, such as the fallback or the pass threshold, should map to a test or a monitor. If nothing checks a promise, it will drift.
  • Re-review on change. A new model, a new data field sent to the model, a wider user group or a different risk class all need a new ADR and, often, a new sign-off.
  • Budget for twice the volume. Token use grows when users like the tool and when prompts get longer. Show the cost at expected and at double volume.
  • Clean core stays visible. If the design ever needs a level C or D part, record why, what it touches and the plan to replace it.

Pitfalls

  • Writing it after the build. A design document written to describe what was built finds no flaws. Write it while choices are still open.
  • A metric without a baseline. "4 minutes" means nothing if nobody measured today's number the same way.
  • Only one option. If the document doesn't compare a standard SAP option, reviewers will ask, and the decision isn't defensible.
  • Copying the reference architecture. Pasting a pattern without your data, permissions and numbers gives reviewers nothing to review.
  • Editing old decisions. Changing an accepted ADR hides why the team acted as it did. Supersede it with a new one.
  • Treating the checker's "Ready for review" as approval. The script checks completeness, not truth. People still need to read it.
  • Leaving operations to "later". A design without an owner, a runbook and a model-retirement plan is not ready for users.
  • Example prices in a real document. Use your own rates; invented numbers in a signed document become a budget problem.

Exercise: write the design document for your blocked-order explainer

You will turn your blank template into a complete design for the service you built in this unit, check it, get one review, and commit it. Unit 8 reuses its success metric and evaluation plan, and the Unit 14 capstone builds on the whole document.

  1. Open unit06/solution_design.md (from Step 5) and unit06/sample_design.md side by side: right-click the second file's tab and choose Split Right.

  2. Fill Summary, Problem and success metric and Scope and non-goals for your own version of the use case. If you have no real baseline, write how you would measure it (for example, "timed sample of 50 orders over two weeks") and use a clearly marked estimate.

  3. Fill Options considered with at least two rows, one of them a standard SAP option. Write chosen in the Verdict column of exactly one row.

  4. Fill Architecture with your own mermaid diagram, using the parts you built in this unit: the AI API, the CAP extension and the Cloud Foundry deployment.

  5. Fill Data and integration, AI design and Security and authorizations from your code: the fields your AI API sends to the model, its fallback, its timeout, and how callers prove who they are.

  6. Fill Responsible AI. Decide the risk class and write one sentence on why.

  7. Fill Operations. For Runbook, write unit06/deployment_runbook.md if you did the last topic's exercise.

  8. Fill Cost estimate with your own volume. For prices, use your company's rates or write 0.00 (unknown) and add an open question about where to get them.

  9. Write at least three Risks, each with a mitigation and an owner, and at least two Decisions as ADRs. One ADR must record where the AI lives.

  10. Check it until there are no FAIL lines:

    python unit06/sdd_check.py unit06/solution_design.md
  11. Get one review: ask a colleague or fellow learner to read it, or run Step 6 with --llm. Write each point you accept as a change, and each point you reject as a line under Open questions or a new ADR with status rejected.

  12. Commit your work from the course folder:

    git add unit06/sdd_check.py unit06/solution_design.md unit06/sample_design.md
    git commit -m "Add the solution design document for the blocked-order explainer"

    git status should not list .env.

Done when: python unit06/sdd_check.py unit06/solution_design.md ends with Ready for review., the document has your own baseline (or a marked estimate with a measuring plan), at least three complete risks and two ADRs, one review has been answered, and the work is committed.

Check yourself

Pick one answer for each question. The explanation appears after you choose.
  1. 1Why does the course template require the evaluation plan's pass threshold before the build starts?

    Answer: C. Quality of model output is statistical, so it needs a number. Fixing it before results exist stops the team from moving the bar to fit what they built. The threshold isn't a training target or an SAP AI Core setting.
  2. 2Your team accepted ADR-1 ("call the model directly") last month. Now you will route calls through SAP's orchestration service. What do you do with the record?

    Answer: B. ADRs are not edited once accepted. A new record captures the new decision and its context, and the old one is marked superseded with links both ways, so the earlier reasoning stays visible.
  3. 3The checker prints "WARN Clean core: level C". What does it mean for the design?

    Answer: D. Level C means internal SAP objects that aren't released for customers, and an extension is rated by its lowest part. It isn't forbidden, but it carries upgrade risk the document must explain. Level A is released APIs only.
  4. 4In the checker, why does a "high-risk" class fail unless the Approvals table names a privacy, ethics or legal approver?

    Answer: A. In SAP's ethics approach, high-risk cases, such as those with personal data or automated decisions, get extra review. The checker turns that into a required approver. It says nothing about which services may be used.
  5. 5You run the cost estimate and get 9.24 EUR a month for model calls. A manager wants to put that number in the budget. What should you say?

    Answer: B. The checker multiplies your inputs; the example's rates are invented. Real rates come from your agreement, with model conversion factors in SAP Note 3437766. Token use grows with adoption and prompt length, so show a higher-volume case too.
  6. 6The model your design depends on gets a deprecation date. Which parts of a good document already cover this?

    Answer: C. Model retirement is a planned change. The operations section names who watches SAP Note 3437766, and the risks table gives the mitigation: test the replacement on the evaluation set before switching.
  7. 7What would you do if a team lead says the design is approved because sdd_check.py printed "Ready for review"?

    Answer: D. The script finds missing sections, placeholders and incomplete records. It can't tell whether the baseline is true or the design is sound. The model review is a second opinion, not an approval; the Approvals table needs real names and dates.
  8. 8Which part of the document should the SAP Architecture Center's golden path most directly shape?

    Answer: C. The golden path describes how to build, deploy and run generative AI apps on BTP: CAP backend, Destinations, Prompt Registry, evaluation, logging and model lifecycle. Your metric, risk class and approvers come from your own process and company.

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