Orchestrate

Report an issue

Something wrong, out of date or unclear? Tell us. Corrections are prioritized over new topics. You don't need to sign in.

0 / 2000

Don't include personal or confidential company details. Reports are reviewed with AI assistance.

AI opportunity assessment: AI, automation or neither?

Decide, for each framed problem, whether to fix the cause, use standard SAP, automate with rules, or prototype AI, and rank the results for a sponsor.

Updated Oct 10, 2026Foundational 9 minDeep 38 min
Foundational layer · 9 min read

The 60-second version

Once a problem is framed, someone has to decide what kind of fix it needs. That decision is the opportunity assessment. It has more answers than "AI" or "no AI":

  1. Fix the cause. The work exists because something upstream is broken: stale master data, a missing setting, an unclear policy. Fix that, and the work disappears.
  2. Use standard SAP. A function you already own does the job, but nobody switched it on or scheduled it.
  3. Automate with rules. The decision can be written down, experts agree on it, and the inputs are clean fields. A rule engine or workflow does it reliably and cheaply.
  4. Use AI. The input is text, documents or messy context, or the decision depends on patterns in history that nobody can write down. Then a prototype is worth it.
  5. Do nothing. The prize is too small, or the data or risk isn't ready yet.

Work through them in that order. Each step up adds cost, risk and things to maintain. Use AI where the problem needs it, not because the request said "AI".

The output is a short ranked list: each framed problem, the decision, the size of the prize and the next step, signed by the sponsor.

Why it matters to the business

An assessment protects money in both directions.

  • AI where rules would do costs more to run, needs evaluation and monitoring, and can be wrong in ways a rule never is. Google's machine learning guidance puts it bluntly. Its first rule is "Don't be afraid to launch a product without machine learning."
  • Rules where AI is needed become brittle. Google's third rule warns that a complex heuristic becomes hard to maintain, and that a learned model is then the better choice.
  • AI on top of a broken process hides the real cause. The assistant gets better at handling cases that should never have existed.

Take the course's procure-to-pay example: supplier invoices blocked for payment after the three-way match. The request was "an AI agent that clears blocked invoices". An assessment might find that almost half the blocks come from purchase order prices nobody updated, and that SAP's automatic release of invoices whose blocking reasons no longer apply was never scheduled. Fixing prices and scheduling the job could clear most of the backlog with no AI at all. What remains may suit rules. The AI budget then goes to a problem that needs it, such as the blocked sales orders, where analysts spend their time reading notes and context.

The assessment also tells a sponsor what to stop. Parking an idea until its data exists is a result, not a failure.

How SAP does it

SAP offers pieces of an assessment rather than one tool. As of October 2026:

  • Finding fixable causes. SAP Signavio Process Insights reads process data from SAP ERP and reports on more than 200 process performance indicators. SAP Learning says it offers over 160 correction recommendations, such as configuration changes or master data fixes.
  • Checking standard first. SAP's own processes already automate a lot. Invoice verification has automatic release of invoices blocked due to variances. Credit Management has scheduled jobs that update credit limits and scores. Situation Handling can alert planners to selected MRP exceptions.
  • Checking embedded AI. The SAP Business AI Feature Catalog in SAP Discovery Center lists embedded AI features with use cases, value, metrics and release stage. The Feature Estimator estimates the AI units a feature would consume.
  • Automating with rules. SAP Build Process Automation offers workflows, business rules in "spreadsheet-like decision tables", bots and document extraction.
  • Prioritizing. SAP AppHaus workshops place use cases on a Value Heatmap, usually business value against complexity, and end with a Next Steps Matrix of what, when and who.

None of these decides "AI, automation or neither" for you. That judgment is the forward deployed engineer's job, with the process owner.

The assessment on one page

Ask the questions in this order. The first answer that applies usually decides.

Question If yes SAP example
Do experts disagree on what the right decision is? Clarify the policy first. Neither people nor software can be measured against an unclear rule Planners rank the same exceptions differently
Does a fixable cause explain a large share of the cases? Fix first: data, settings, policy, training Invoice price blocks caused by outdated purchase order prices
Does a standard function already do it? Use standard: switch on, schedule, configure Automatic release of blocked invoices (MRBR)
Can the decision be written as rules, on clean fields? Automate with rules or workflow. No AI needed Proposing the next step for a quantity block with no goods receipt
Is the input text or documents, or the output a draft? Prototype generative AI Drafting a context note for a blocked sales order
Is the output a prediction from history, with enough recorded outcomes? Prototype a predictive model Which deliveries will be late
Does one case need actions across several systems? Prototype an agent, with approval steps Gathering context from SAP and email, then proposing a release
Is the prize small, or are data, risk or approvals not ready? Drop or park with a named condition Fewer than 20 hours a month to save

Two reminders. First, hybrids are normal: rules handle the clear cases and AI handles the rest. Second, every decision is provisional. After a fix or a standard function goes live, measure again and reassess what is left.

Questions to ask

Your team or partner:

  • What share of these cases would disappear if we fixed the data or the settings? How was that share counted?
  • Which standard SAP function did you check, in which release, and why doesn't it cover this?
  • Could an expert write the decision down as rules? Did two experts decide the same sample cases the same way?
  • If this needs a prediction, how many past cases have the real outcome recorded?
  • What happens when the output is wrong and nobody notices? Who checks each output?
  • Does anything change SAP data? Where does a person approve it?

Your vendor:

  • What is the best non-AI way to do this, and how does your product compare against it?
  • Which part of this needs AI, and which part is rules or workflow?

Yourself, as sponsor:

  • Am I funding the problem, or the technology in the original request?
  • Which ideas am I willing to park, and what would bring them back?

Common misconceptions

  • "If we don't use AI, we've failed at AI." The goal is the metric in the frame. A scheduled standard job that moves it is a win.
  • "Rules are old-fashioned; AI replaces them." Rules are cheap, explainable and exact when the decision is well defined. Most good AI systems keep rules for the clear cases.
  • "We can fix the data later." AI on bad data learns the bad data. Fixable causes come first.
  • "A big prize means do it now." A large prize with no data or no clear policy is a park, not a go.
  • "The assessment is a one-off." Each fix changes what is left. Reassess after every change that goes live.

Key terms

All course terms, A to Z, in the glossary

  • Opportunity assessment: the decision, per framed problem, between fixing the cause, standard SAP, rules automation, AI and doing nothing.
  • Fixable cause: an upstream reason for the work, such as master data, settings or policy, that can be removed rather than handled.
  • Rules automation: software that applies written-down rules to structured inputs, such as decision tables in a workflow.
  • Predictive AI: a model that learns from past outcomes to predict a number or category.
  • Generative AI: a model that produces text or other content, often from unstructured input.
  • Expert agreement: how often two experts make the same decision on the same cases. Low agreement means the task is not defined yet.
  • Gate: a condition that must hold before a prototype starts, such as data access or human review.
  • Value Heatmap: SAP AppHaus's chart for comparing use cases, usually business value against complexity.

Check yourself

Pick one answer for each question. The explanation appears after you choose.

1A sponsor asks for "an AI agent that clears blocked invoices". What should the opportunity assessment check first?

Answer: D. The assessment climbs from the cheapest fix upward. Outdated purchase order prices and an unscheduled automatic release could remove most of the work with no AI. The model choice only matters once AI is the right answer.

2Two experienced planners rank the same 30 MRP exceptions very differently. What does that tell you?

Answer: B. If experts disagree, there is no agreed right answer to automate or to measure a tool against. The first step is to clarify the policy with the process owner. Cleaning data or buying a tool doesn't settle what the right decision is.

3Which situation fits rules automation better than AI?

Answer: A. When the decision can be written down, experts agree on it, and the inputs are clean fields, rules are cheaper, exact and explainable. The other three involve text, documents or patterns in history, where AI earns its place.

4An idea would save many hours, but only 150 past cases have the outcome recorded. What is the sensible decision?

Answer: D. A predictive model learns from recorded outcomes, and 150 is too few to start. Parking with a named condition, such as recording outcomes for a few months, keeps the idea alive. A big prize doesn't fix missing data.

5Your partner presents an AI design for a process step. Which question best tests their assessment?

Answer: D. The best non-AI fix is the benchmark. If the partner can't name it, they haven't assessed whether AI is needed. Hosting and timing questions come after the decision.

6Fixing purchase order prices removed half the invoice blocks. What should happen next?

Answer: B. Each fix changes the remaining problem. The leftover cases may suit a standard function, rules, AI or nothing. The assessment is repeated, not done once.

7What does SAP AppHaus's Value Heatmap help a team do?

Answer: D. The Value Heatmap places use cases relative to each other, usually business value against complexity, to find quick wins. It doesn't produce a return on investment or pick technology. The business case and the Feature Catalog do other jobs.
Deep layer · 38 min read

Mental model

Use the least machinery that meets the frame.

Picture a ladder. Each rung adds machinery, and each piece of machinery is something you build, run, test and explain:

Rung What you add What you now own
0. Fix the cause Nothing new; you remove work A data or settings change, and keeping it fixed
1. Standard SAP Configuration or a scheduled job Settings, a job, monitoring it
2. Rules automation Decision tables or a workflow Rule maintenance when policy changes
3. Predictive AI A model trained on past outcomes Training data, retraining, drift, evaluation
4. Generative AI A language model with prompts and grounding Prompts, evaluation, token cost, guardrails
5. Agent A model that chooses tools and steps All of rung 4, plus tool security and approvals

You climb only when the rung below can't meet the frame. Google's problem framing guidance makes the same point for machine learning: optimize a non-ML solution first, then use it as the benchmark. Its Rules of Machine Learning add the counterweight: once rules turn into a complex heuristic and you have data, a learned model becomes easier to maintain. Both rules are true. The assessment finds where on the ladder a given problem sits.

This is a different question from Buy vs. build for SAP AI. That topic asks who supplies the solution: use, configure, extend, build or partner. This topic asks what kind of solution the problem needs. Answer this one first. A "use standard" result here often ends the sourcing question before it starts.

How it works

The assessment takes one signed frame from Problem framing and walks it through six passes. Each pass has a question, the evidence that answers it, and what a "yes" means.

flowchart TD
  F[Signed frame] --> P1{Experts agree?}
  P1 -->|no| C[CLARIFY policy]
  P1 -->|yes| P2{Large fixable cause?}
  P2 -->|yes| X[FIX FIRST]
  P2 -->|no| P3{Standard does it?}
  P3 -->|yes| S[USE STANDARD]
  P3 -->|no| P4[Shape: rules, predict, generate, agent]
  P4 --> P5{Gates pass?}
  P5 -->|no| K[PARK]
  P5 -->|yes| P6{Prize big enough?}
  P6 -->|no| D[DROP]
  P6 -->|yes| G[AUTOMATE or PROTOTYPE]
  X -.measure again.-> F
  S -.measure again.-> F

Pass 1: Is the work defined?

Take 20 to 30 past cases. Ask two experts to decide each one on their own. Count how often they agree.

High agreement means a correct answer exists and can be measured. Low agreement means the policy is unwritten or contested. Automating that, with rules or AI, just picks one expert's habits and hides the disagreement. The fix is a conversation with the process owner, not software. This course uses 60% as the line below which you clarify first, and 90% as the line above which rules are realistic. Both are starting points to adjust, not standards.

The agreement sample also becomes your first evaluation set later. If you prototype, these cases tell you how good "good" is: a tool that matches experts as often as they match each other is doing well.

Pass 2: Can the cause be removed?

For each case, ask why it exists. Then count the reasons from system data where you can. Typical fixable causes in SAP processes:

  • Master data: outdated purchase order prices causing price blocks, wrong planned delivery times causing MRP exceptions, credit limits nobody reviewed.
  • Settings: tolerances set too tight, a standard job not scheduled, an output or workflow not configured.
  • Policy and training: a rule people follow that nobody wrote down, a step done out of order.

SAP Signavio Process Insights exists for this pass. SAP Learning describes performance indicators across process flows and correction recommendations that include configuration changes and master data fixes. Without it, a few queries over the documents from the discovery baseline do the same job on a smaller scale.

If a fixable cause explains a large share of cases, fix it first. This course uses 30%. Then measure again: the rest of the assessment runs on what is left.

Pass 3: Does standard SAP already do it?

Check three places:

  1. The process's own functions. For blocked invoices, SAP Learning describes automatic release with MRBR for invoices blocked due to variances. The system deletes blocking reasons that no longer apply, such as a price block after the purchase order price changed, and releases the invoice once none are left. Program RM08RELEASE runs it in the background. Invoices with a manual payment block in the header are not released automatically.
  2. Alerts and jobs. SAP Credit Management has scheduled jobs such as Update Credit Limit for Business Partner and Update Score for Business Partner. For planning, an SAP S/4HANA RIG post shows Situation Handling with the template SAP_PP_MRP_MATERIAL_EXCEPTION. It notifies a team of planners about selected exceptions and opens Manage Material Coverage.
  3. Embedded AI. The SAP Business AI Feature Catalog lists features by use case, with release stage. Embedded AI across SAP applications and Where AI creates value in S/4HANA show how to search it.

Record what you checked, in which release, and the result: yes, partial or no. "Partial" is common. Situation Handling alerts on cancel exceptions, but it doesn't rank the rest. Write down the gap.

Pass 4: What shape is the work?

Now look at the work itself. Four questions pick the shape:

Question Points to
Can an expert write the decision down, experts agree, and are the inputs clean fields? Rules
Is the output a prediction (a number or category) learned from structured history? Predict
Is the input text, documents or mixed context, or is the output a draft? Generate
Does one case need actions across several systems, in an order that varies? Agent

Google's framing guidance draws the predictive and generative line clearly. Predictive models make predictions you can check against what really happened. Generative models produce content from the user's intent. They need different data and different evaluation, so they need different prototypes.

When rules cover some cases but not all, write it down as a hybrid. In the blocked sales order example, rules can flag orders under a value threshold for a fast path. A generative assistant then drafts context for the rest.

Pass 5: Gates

A gate is a condition that must hold before a prototype starts. Any failed gate parks the idea with a named reason.

Gate Passes when Why
Data access The solution can read its inputs at decision time, under the user's authorizations Google's list of good data includes "available": all inputs must exist when the prediction is made
Labels (predict only) Enough past cases have the real outcome recorded Predictive models learn from outcomes. This course starts at 1,000 and fails below 200
Error cost Costly mistakes are caught by a person before they take effect A wrong release of a blocked invoice is a payment made in error
Approval Any change to SAP data has a person approving it A rule of this course, from the frame's constraints
Risk Personal data, automated decisions about people and high-risk domains are flagged The SAP AppHaus Use Case Brief asks exactly these questions in its ethical view

Risk flags usually warn rather than fail. They mean "involve data protection, legal or the works council before the prototype", not "stop".

Pass 6: Size the prize

Use the frame's numbers for a ceiling, not a forecast:

hours saved by the fix   = volume x fixable share x baseline minutes / 60
hours saved on the rest  = volume x (1 - fixable share) x (baseline - target) / 60

For the blocked sales orders: 6,000 orders a month, 15% fixable, 17 minutes today, 10 minutes target. The fix saves up to 6,000 × 0.15 × 17 / 60 = 255 hours a month. Reaching the target on the other 5,100 orders saves up to 5,100 × 7 / 60 = 595 hours.

These are ceilings at the target. Adoption, realization and run cost come later, in The AI business case. Here you only need to know whether the prize is big enough to bother with. This course drops anything under 20 hours a month unless it can be bundled with a related problem.

The decision

The passes produce one of seven decisions, checked in this order:

Decision When Next step
CLARIFY Experts agree on under 60% of cases Agree the policy, re-run the agreement test
FIX FIRST A fixable cause explains 30% or more Fix it, measure, reassess
USE STANDARD A standard function does it Configure or schedule it, measure, reassess
PARK A gate fails Meet the named condition, then reassess
DROP Under 20 hours a month Bundle with a related problem, or stop
AUTOMATE The shape is rules Build a decision table or workflow
PROTOTYPE The shape is predict, generate or agent Prototype against the benchmark (next in Unit 14)

Finally, rank the list for the sponsor. SAP AppHaus uses a Value Heatmap for this, placing use cases relative to each other on business value and complexity, and ends with a Next Steps Matrix: what, when, who. Your ranked list does the same job in text, and goes in Git.

Build it yourself: an opportunity assessor

You will build a small command-line tool that walks each framed problem through the six passes, explains its reasoning, and ranks the results into a one-page report for the sponsor.

Before you start: complete Set up your computer for this course and Set up for Unit 14. They create your orchestrate-course folder, its .venv and the unit14 folder. This script uses only Python's built-in modules, so there is nothing new to install. If you did the problem framing exercise, the tool reads your frames too, but you don't need them.

flowchart LR
  S[sample or new] --> A[(assessment files)]
  Fr[(frame files, optional)] -.-> A
  A --> R[assess: six passes]
  R --> K[rank]
  K --> M[assessment.md for sign-off]

What you need

  • Your course folder from the setup topics.
  • About 45 minutes.
  • No accounts and no cost. The sample assessments and their numbers are made up.
  • Optional: the frames in unit14/framing/ from the problem framing exercise.

Step 1: Open your course folder

  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 the unit14 folder exists:

    • Windows (PowerShell):

      dir unit14
    • macOS / Linux:

      ls unit14

    If you see an error saying the folder doesn't exist, create it with mkdir unit14.

Step 2: Create the script

  1. In VS Code, right-click the unit14 folder, choose New File, name it opportunity_assessor.py, paste the code below and save.
"""Opportunity assessor: decide whether a framed problem needs AI, automation or neither.

Commands:
  sample   write three made-up assessments for SAP processes
  new      write an empty assessment to fill in
  assess   walk one or more assessments through the passes and print the reasoning
  rank     print one line per opportunity, best first; --md writes a report

Uses only Python's built-in modules. No account, no network.
"""
import argparse
import glob
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
DEFAULT_DIR = HERE / "assessment"

# ---------------------------------------------------------------------------
# 1. The fields of an assessment. One "FIELD: value" per line.
# ---------------------------------------------------------------------------
FIELDS = {
    "NAME": "short name of the opportunity",
    "FRAME": "optional path to the problem frame; missing fields are read from it",
    "PROBLEM": "the framed problem, in business words",
    "UNITS": "unit of the metric; value is only computed for minutes",
    "BASELINE": "today's value of the metric (a number; text after | is a note)",
    "TARGET": "the target from the frame",
    "VOLUME": "cases per month (orders, invoices, planner days)",
    "HOURLY_COST": "loaded cost of one hour of the actor's time",
    "CAUSE_FIXABLE": "share of cases (0 to 1) caused by something you can fix: data, config, policy",
    "FIX": "what that fix is",
    "STANDARD": "yes, partial or no: does a standard SAP function already do this?",
    "STANDARD_DETAIL": "which function, and what you checked",
    "RULES_WRITABLE": "yes, partial or no: can an expert write the decision down as rules?",
    "EXPERTS_AGREE": "share of sample cases (0 to 1) where two experts decided the same",
    "INPUT": "structured, unstructured or mixed",
    "OUTPUT": "decision, prediction, text or actions",
    "LABELED_HISTORY": "past cases with the real outcome recorded",
    "TOOLS": "how many systems or tools the solution must use for one case",
    "DATA_ACCESS": "yes or no: can the solution read its inputs at decision time, within authorizations?",
    "ERROR_COST": "low, medium or high: what a wrong output costs if nobody catches it",
    "HUMAN_REVIEW": "yes or no: does a person check every output before it takes effect?",
    "CHANGES_SAP": "yes or no: would the output change SAP data?",
    "PERSONAL_DATA": "yes or no",
    "HIGH_RISK_DOMAIN": "yes or no: HR decisions about people, credit decisions about people, health",
}
CHOICES = {
    "STANDARD": ["yes", "partial", "no"],
    "RULES_WRITABLE": ["yes", "partial", "no"],
    "INPUT": ["structured", "unstructured", "mixed"],
    "OUTPUT": ["decision", "prediction", "text", "actions"],
    "DATA_ACCESS": ["yes", "no"],
    "ERROR_COST": ["low", "medium", "high"],
    "HUMAN_REVIEW": ["yes", "no"],
    "CHANGES_SAP": ["yes", "no"],
    "PERSONAL_DATA": ["yes", "no"],
    "HIGH_RISK_DOMAIN": ["yes", "no"],
}
NUMBERS = ["BASELINE", "TARGET", "VOLUME", "HOURLY_COST", "CAUSE_FIXABLE",
           "EXPERTS_AGREE", "LABELED_HISTORY", "TOOLS"]
REQUIRED = ["NAME", "BASELINE", "TARGET", "VOLUME", "CAUSE_FIXABLE", "STANDARD",
            "RULES_WRITABLE", "EXPERTS_AGREE", "INPUT", "OUTPUT", "DATA_ACCESS",
            "ERROR_COST", "HUMAN_REVIEW", "CHANGES_SAP"]
FROM_FRAME = ["PROBLEM", "UNITS", "BASELINE", "TARGET", "CHANGES_SAP"]

# Starting thresholds for this course. They are judgment calls, not standards:
# change them for your customer and say so in your report.
FIX_FIRST_SHARE = 0.30     # fix the cause first if it explains this share of cases
ALSO_FIX_SHARE = 0.10      # mention the fix if it explains at least this share
CLARIFY_BELOW = 0.60       # experts agree less often than this: the task is not defined
RULES_AGREE = 0.90         # rules need experts to agree at least this often
LABELS_OK = 1000           # labeled past cases to try a predictive model
LABELS_MIN = 200           # below this, collect labels before predicting

BLANK = "# Opportunity assessment. One FIELD: value per line. Lines starting with # are ignored.\n" + \
    "\n".join(f"{name}: ({help_text})" for name, help_text in FIELDS.items()) + "\n"

SAMPLES = {
    "blocked_orders.txt": """# Made-up assessment for order-to-cash. Frame: Unit 14, problem framing.
NAME: Blocked sales orders
FRAME: unit14/framing/blocked_orders.txt
PROBLEM: Credit analysts spend most of each blocked order gathering context from several screens and sales reps
UNITS: minutes
BASELINE: 17 | measured, shadowing of 8 orders
TARGET: 10
VOLUME: 6000
HOURLY_COST: 55
CAUSE_FIXABLE: 0.15 | system, blocks on customers whose credit limit was not reviewed in 12 months
FIX: Schedule the credit limit and score update jobs; review stale limits
STANDARD: partial
STANDARD_DETAIL: Credit Management jobs update scores and limits, but nothing gathers the context per order
RULES_WRITABLE: partial
EXPERTS_AGREE: 0.8 | measured, two analysts decided 20 past orders
INPUT: mixed
OUTPUT: text
LABELED_HISTORY: 0
TOOLS: 1
DATA_ACCESS: yes
ERROR_COST: medium
HUMAN_REVIEW: yes
CHANGES_SAP: no
PERSONAL_DATA: yes
HIGH_RISK_DOMAIN: no
""",
    "invoice_agent.txt": """# Made-up assessment for procure-to-pay. Frame: Unit 14, problem framing (reframed version).
NAME: Blocked supplier invoices
FRAME: unit14/framing/invoice_agent.txt
PROBLEM: Clerks spend most of each blocked invoice finding out why it is blocked and whether the reason still holds
UNITS: minutes
BASELINE: 22 | measured, shadowing of 10 invoices
TARGET: 12
VOLUME: 2500
HOURLY_COST: 50
CAUSE_FIXABLE: 0.45 | system, price blocks where the purchase order price was never updated
FIX: Buyers update purchase order prices when a supplier price changes
STANDARD: yes
STANDARD_DETAIL: Automatic release of invoices blocked due to variances (MRBR, background program RM08RELEASE) is not scheduled
RULES_WRITABLE: yes
EXPERTS_AGREE: 0.95 | measured, two clerks on 20 past invoices
INPUT: structured
OUTPUT: decision
LABELED_HISTORY: 30000
TOOLS: 1
DATA_ACCESS: yes
ERROR_COST: high
HUMAN_REVIEW: yes
CHANGES_SAP: no
PERSONAL_DATA: no
HIGH_RISK_DOMAIN: no
""",
    "mrp_exceptions.txt": """# Made-up assessment for plan-to-produce. Numbers are estimates on purpose.
NAME: MRP exception review
FRAME: unit14/framing/mrp_exceptions.txt
PROBLEM: Planners spend the start of each day working through exception messages before they can act on shortages
UNITS: minutes
BASELINE: 180 | estimate, the planning lead's estimate
TARGET: 90
VOLUME: 170 | 8 planners, about 21 working days a month
HOURLY_COST: 65
CAUSE_FIXABLE: 0.1 | estimate, exceptions caused by outdated lead times
FIX: Review planned delivery times for the materials with the most exceptions
STANDARD: partial
STANDARD_DETAIL: Situation Handling can alert planners to cancel exceptions; it does not rank the rest
RULES_WRITABLE: partial
EXPERTS_AGREE: 0.7 | measured, two planners ranked the same 30 exceptions
INPUT: structured
OUTPUT: prediction
LABELED_HISTORY: 150 | exceptions where we know whether the planner acted
TOOLS: 1
DATA_ACCESS: yes
ERROR_COST: medium
HUMAN_REVIEW: yes
CHANGES_SAP: no
PERSONAL_DATA: no
HIGH_RISK_DOMAIN: no
""",
}

# ---------------------------------------------------------------------------
# 2. Reading files
# ---------------------------------------------------------------------------

def show(path):
    """Print a path relative to the current folder when possible."""
    try:
        return str(Path(path).resolve().relative_to(Path.cwd().resolve()))
    except ValueError:
        return str(path)


def read_pairs(path):
    """Read FIELD: value lines into a dict. Unknown fields are kept but reported."""
    data, problems = {}, []
    for number, raw in enumerate(Path(path).read_text(encoding="utf-8").splitlines(), start=1):
        line = raw.strip()
        if not line or line.startswith("#"):
            continue
        if ":" not in line:
            problems.append(f"line {number}: no 'FIELD:' at the start")
            continue
        name, value = line.split(":", 1)
        data.setdefault(name.strip().upper(), value.strip())
    return data, problems


def read_assessment(path):
    """Read an assessment. Fields it leaves out are taken from its FRAME file, if found."""
    data, problems = read_pairs(path)
    frame_note = "no FRAME given"
    if data.get("FRAME"):
        frame_path = Path(data["FRAME"])
        if frame_path.exists():
            frame, _ = read_pairs(frame_path)
            taken = [f for f in FROM_FRAME if f not in data and f in frame]
            for field in taken:
                data[field] = frame[field]
            frame_note = f"frame found, {len(taken)} fields taken from it"
        else:
            frame_note = "frame not found; using this file only"
    for name in data:
        if name not in FIELDS:
            problems.append(f"unknown field '{name}'")
    return data, problems, frame_note


def number(text):
    """'0.15 | system, ...' -> 0.15. Returns None if there is no number first."""
    try:
        return float(text.split("|")[0].strip())
    except (ValueError, AttributeError):
        return None


def check_fields(data):
    """Return a list of problems that stop the assessment."""
    problems = []
    missing = [f for f in REQUIRED if not data.get(f) or data[f].startswith("(")]
    if missing:
        problems.append("missing fields: " + ", ".join(missing))
    for name in NUMBERS:
        if data.get(name) and not data[name].startswith("(") and number(data[name]) is None:
            problems.append(f"{name} must start with a number")
    for name in ["CAUSE_FIXABLE", "EXPERTS_AGREE"]:
        value = number(data.get(name, ""))
        if value is not None and not 0 <= value <= 1:
            problems.append(f"{name} must be between 0 and 1")
    for name, allowed in CHOICES.items():
        value = data.get(name, "").split("|")[0].strip().lower()
        if value and not value.startswith("(") and value not in allowed:
            problems.append(f"{name} must be one of: {', '.join(allowed)}")
    return problems


def choice(data, name, default="no"):
    return data.get(name, default).split("|")[0].strip().lower()

PHRASE = {"GENERATE": "a generative AI assistant", "PREDICT": "a predictive model",
          "AGENT": "an agent with approval steps", "RULES": "rules"}

# ---------------------------------------------------------------------------
# 3. The passes. Each adds lines to the report; the last one decides.
# ---------------------------------------------------------------------------

def assess(data, min_hours):
    lines = []          # (label, text) for the printed report
    gates = []          # (level, text) with level PASS, WARN or FAIL

    volume = number(data["VOLUME"])
    baseline, target = number(data["BASELINE"]), number(data["TARGET"])
    fixable = number(data["CAUSE_FIXABLE"])
    agree = number(data["EXPERTS_AGREE"])
    labels = number(data.get("LABELED_HISTORY", "0")) or 0
    tools = number(data.get("TOOLS", "1")) or 1
    hourly = number(data.get("HOURLY_COST", "")) or 0
    in_minutes = data.get("UNITS", "").strip().lower().startswith("minute")

    # Pass 1: is the work itself defined?
    lines.append(("Pass 1 Defined", f"experts agree on {agree:.0%} of sample cases"))

    # Pass 2: can the cause be removed instead of handled?
    fix_text = data.get("FIX", "(no fix named)")
    lines.append(("Pass 2 Cause", f"{fixable:.0%} of cases have a fixable cause: {fix_text}"))

    # Pass 3: does standard SAP already do it?
    standard = choice(data, "STANDARD")
    detail = data.get("STANDARD_DETAIL", "(not described)")
    lines.append(("Pass 3 Standard", f"{standard}: {detail}"))

    # Pass 4: which kind of solution does the work call for?
    rules = choice(data, "RULES_WRITABLE")
    source = choice(data, "INPUT")
    output = choice(data, "OUTPUT")
    if rules == "yes" and source == "structured" and agree >= RULES_AGREE:
        kind = "RULES"
        why = "the rules can be written down, experts agree, and the inputs are structured"
    elif output == "actions" and tools >= 2:
        kind = "AGENT"
        why = f"one case needs actions across {tools:g} systems, in an order that varies"
    elif output == "prediction" and source == "structured":
        kind = "PREDICT"
        why = "the output is a prediction from structured history"
    else:
        kind = "GENERATE"
        why = f"the input is {source} and the output is {output}; rules can't cover it"
    if kind != "RULES" and rules == "partial":
        why += "; rules can handle the clear cases first"
    lines.append(("Pass 4 Shape", f"{kind}: {why}"))

    # Pass 5: gates. Any FAIL stops the AI path until it is fixed.
    if choice(data, "DATA_ACCESS") == "no":
        gates.append(("FAIL", "Data: the inputs can't be read at decision time within authorizations"))
    else:
        gates.append(("PASS", "Data: inputs readable at decision time"))
    if kind == "PREDICT":
        if labels >= LABELS_OK:
            gates.append(("PASS", f"Labels: {labels:g} labeled past cases"))
        elif labels >= LABELS_MIN:
            gates.append(("WARN", f"Labels: only {labels:g} labeled past cases; expect a weak first model"))
        else:
            gates.append(("FAIL", f"Labels: {labels:g} labeled past cases; record outcomes before modeling"))
    review = choice(data, "HUMAN_REVIEW")
    error_cost = choice(data, "ERROR_COST")
    if error_cost == "high" and review == "no":
        gates.append(("FAIL", "Errors: wrong outputs are costly and nobody checks them"))
    elif error_cost == "high":
        gates.append(("WARN", "Errors: costly when wrong; the human check must be real, not a click"))
    else:
        gates.append(("PASS", f"Errors: cost when wrong is {error_cost}"))
    if choice(data, "CHANGES_SAP") == "yes" and review == "no":
        gates.append(("FAIL", "Approval: the output changes SAP data without a person approving it"))
    elif choice(data, "CHANGES_SAP") == "yes":
        gates.append(("WARN", "Approval: changes SAP data; enforce the approval in code"))
    if choice(data, "HIGH_RISK_DOMAIN") == "yes":
        gates.append(("WARN", "Risk: high-risk domain; involve legal and works council before a prototype"))
    if choice(data, "PERSONAL_DATA") == "yes":
        gates.append(("WARN", "Privacy: personal data; involve data protection early"))

    # Pass 6: size the prize. A ceiling at the target, not a business case.
    fix_hours = ai_hours = None
    if in_minutes and volume is not None:
        fix_hours = volume * fixable * baseline / 60
        ai_hours = volume * (1 - fixable) * max(baseline - target, 0) / 60
        money = f" (about {ai_hours * hourly:,.0f} a month at {hourly:g} an hour)" if hourly else ""
        value = ("Pass 6 Value", f"fixing the cause saves up to {fix_hours:,.0f} h a month; "
                                      f"reaching the target on the rest saves up to {ai_hours:,.0f} h a month{money}")
    else:
        value = ("Pass 6 Value", "not computed: the metric is not in minutes; use the business case calculator")

    # Decision, in order. The first rule that matches wins.
    fails = [text for level, text in gates if level == "FAIL"]
    also = []
    if ALSO_FIX_SHARE <= fixable < FIX_FIRST_SHARE:
        also.append(f"also fix: {fix_text}")
    if standard == "partial":
        also.append(f"compare with standard: {detail}")
    if standard == "yes" and fixable >= FIX_FIRST_SHARE and agree >= CLARIFY_BELOW:
        also.append(f"then use standard: {detail}")

    if agree < CLARIFY_BELOW:
        decision, step = "CLARIFY", "Agree the decision policy with the process owner; re-run the agreement test"
    elif fixable >= FIX_FIRST_SHARE:
        decision, step = "FIX FIRST", f"{fix_text}; then measure again and reassess what is left"
    elif standard == "yes":
        decision, step = "USE STANDARD", f"{detail}; configure it, measure, and reassess what is left"
    elif fails:
        decision, step = "PARK", fails[0]
    elif ai_hours is not None and ai_hours < min_hours:
        decision, step = "DROP", f"under {min_hours:g} h a month; bundle with a related problem or stop"
    elif kind == "RULES":
        decision, step = "AUTOMATE", "Write the rules as a decision table and automate them; no AI needed"
    else:
        decision, step = "PROTOTYPE", f"Prototype {PHRASE[kind]} and compare it with the benchmark"
    return {"lines": lines, "gates": gates, "value": value, "kind": kind, "decision": decision, "step": step,
            "also": also, "ai_hours": ai_hours, "fix_hours": fix_hours, "hourly": hourly}

# ---------------------------------------------------------------------------
# 4. Commands
# ---------------------------------------------------------------------------

def expand(patterns):
    """Expand *.txt patterns ourselves, so quoting works the same on Windows."""
    files = []
    for pattern in patterns:
        matches = sorted(glob.glob(pattern))
        files.extend(matches if matches else [pattern])
    return [Path(f) for f in files]


def load(files):
    """Read and check every file. Return (path, data, frame_note, problems) tuples."""
    loaded = []
    for path in expand(files):
        if not path.exists():
            loaded.append((path, None, "", [f"file not found: {show(path)}"]))
            continue
        data, problems, note = read_assessment(path)
        loaded.append((path, data, note, problems + check_fields(data)))
    return loaded


def cmd_sample(args):
    base = Path(args.dir)
    base.mkdir(parents=True, exist_ok=True)
    existing = [name for name in SAMPLES if (base / name).exists()]
    if existing and not args.force:
        print(f"Sample assessments already exist in {show(base)}. Add --force to overwrite them.")
        return 1
    for name, text in SAMPLES.items():
        (base / name).write_text(text, encoding="utf-8")
    print(f"Wrote {len(SAMPLES)} assessments to {show(base)}: " + ", ".join(SAMPLES))
    print('All of them are made up. Next: python unit14/opportunity_assessor.py assess "unit14/assessment/*.txt"')
    return 0


def cmd_new(args):
    out = Path(args.out)
    if out.exists() and not args.force:
        print(f"{show(out)} already exists. Add --force to overwrite it.")
        return 1
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_text(BLANK, encoding="utf-8")
    print(f"Wrote an empty assessment to {show(out)}. Replace every (...) with your answer.")
    return 0


def cmd_assess(args):
    errors = 0
    for path, data, note, problems in load(args.files):
        print(f"== {show(path)}")
        if problems:
            errors += 1
            for problem in problems:
                print(f"  ERROR  {problem}")
            print("  -> fix these lines and run again\n")
            continue
        result = assess(data, args.min_hours)
        print(f"  {data['NAME']} ({note})")
        for label, text in result["lines"]:
            print(f"  {label:<16} {text}")
        for level, text in result["gates"]:
            print(f"  {'Pass 5 ' + level:<16} {text}")
        print(f"  {result['value'][0]:<16} {result['value'][1]}")
        print(f"  -> {result['decision']}: {result['step']}")
        for extra in result["also"]:
            print(f"     {extra}")
        print()
    return 1 if errors else 0


ORDER = ["FIX FIRST", "USE STANDARD", "AUTOMATE", "PROTOTYPE", "CLARIFY", "PARK", "DROP"]


def cmd_rank(args):
    rows, errors = [], 0
    for path, data, _, problems in load(args.files):
        if problems:
            errors += 1
            print(f"Skipped {show(path)}: {problems[0]}")
            continue
        result = assess(data, args.min_hours)
        hours = (result["fix_hours"] or 0) + (result["ai_hours"] or 0)
        rows.append((ORDER.index(result["decision"]), -hours, data, result, hours))
    rows.sort(key=lambda r: (r[0], r[1]))
    print(f"{'Opportunity':<28} {'Decision':<13} {'Shape':<9} {'h/month':>8}  Next step")
    for _, _, data, result, hours in rows:
        print(f"{data['NAME'][:28]:<28} {result['decision']:<13} {result['kind']:<9} {hours:>8,.0f}  {result['step']}")
    if args.md and rows:
        out = Path(args.md)
        out.parent.mkdir(parents=True, exist_ok=True)
        md = ["# Opportunity assessment", "",
              "Hours are ceilings at the target, not forecasts. Decisions use the course's starting thresholds.", "",
              "| Opportunity | Decision | Shape | h/month | Next step |", "| --- | --- | --- | ---: | --- |"]
        for _, _, data, result, hours in rows:
            md.append(f"| {data['NAME']} | {result['decision']} | {result['kind']} | {hours:,.0f} | {result['step']} |")
        md += ["", "## Open points", ""]
        for _, _, data, result, _ in rows:
            for level, text in result["gates"]:
                if level != "PASS":
                    md.append(f"- {data['NAME']}: {level} {text}")
            for extra in result["also"]:
                md.append(f"- {data['NAME']}: {extra}")
        md += ["", "Signed off by: ____________________  Date: __________", ""]
        out.write_text("\n".join(md), encoding="utf-8")
        print(f"\nWrote {show(out)}")
    return 1 if errors else 0


def main(argv=None):
    p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    sub = p.add_subparsers(dest="cmd", required=True)
    s = sub.add_parser("sample", help="write three made-up assessments")
    s.add_argument("--dir", default=str(DEFAULT_DIR), help="folder for the files (default: unit14/assessment)")
    s.add_argument("--force", action="store_true", help="overwrite existing sample files")
    n = sub.add_parser("new", help="write an empty assessment")
    n.add_argument("out", help="file to create, e.g. unit14/assessment/my_problem.txt")
    n.add_argument("--force", action="store_true")
    for name, text in [("assess", "explain the decision for each file"), ("rank", "one line per file, best first")]:
        c = sub.add_parser(name, help=text)
        c.add_argument("files", nargs="+")
        c.add_argument("--min-hours", type=float, default=20,
                       help="below this many hours saved a month, drop or bundle (default 20)")
        if name == "rank":
            c.add_argument("--md", help="also write a Markdown report to this file")
    args = p.parse_args(argv)
    handler = {"sample": cmd_sample, "new": cmd_new, "assess": cmd_assess, "rank": cmd_rank}[args.cmd]
    return handler(args) or 0


if __name__ == "__main__":
    sys.exit(main())

Step 3: Write the sample assessments

  1. Run:

    python unit14/opportunity_assessor.py sample
  2. You should see:

    Wrote 3 assessments to unit14/assessment: blocked_orders.txt, invoice_agent.txt, mrp_exceptions.txt
    All of them are made up. Next: python unit14/opportunity_assessor.py assess "unit14/assessment/*.txt"
  3. Open unit14/assessment/blocked_orders.txt. Each line is one field:

    Field What it holds
    NAME, FRAME, PROBLEM A short name, the path to the frame (optional), and the problem in business words
    UNITS, BASELINE, TARGET From the frame. Value is only computed when the units are minutes
    VOLUME, HOURLY_COST Cases per month, and what an hour of the actor's time costs
    CAUSE_FIXABLE, FIX Share of cases with a fixable cause (0 to 1), and what the fix is
    STANDARD, STANDARD_DETAIL yes, partial or no, and which SAP function you checked
    RULES_WRITABLE, EXPERTS_AGREE Can the decision be written as rules, and how often two experts agreed (0 to 1)
    INPUT, OUTPUT structured, unstructured or mixed; decision, prediction, text or actions
    LABELED_HISTORY, TOOLS Past cases with the real outcome recorded; systems one case touches
    DATA_ACCESS, ERROR_COST, HUMAN_REVIEW, CHANGES_SAP The gate answers
    PERSONAL_DATA, HIGH_RISK_DOMAIN The risk flags

    Text after a | is a note for people. The script reads only the number or word before it. Always write where a number came from: system, measured or estimate, as in the discovery and framing topics.

If you see Sample assessments already exist, you ran this before. Add --force to overwrite them.

Step 4: Assess the three samples

  1. Run:

    python unit14/opportunity_assessor.py assess "unit14/assessment/*.txt"

    Keep the quotes. They make the pattern work the same way in PowerShell and on macOS or Linux.

  2. You should see three reports. The first one looks like this:

    == unit14/assessment/blocked_orders.txt
      Blocked sales orders (frame not found; using this file only)
      Pass 1 Defined   experts agree on 80% of sample cases
      Pass 2 Cause     15% of cases have a fixable cause: Schedule the credit limit and score update jobs; review stale limits
      Pass 3 Standard  partial: Credit Management jobs update scores and limits, but nothing gathers the context per order
      Pass 4 Shape     GENERATE: the input is mixed and the output is text; rules can't cover it; rules can handle the clear cases first
      Pass 5 PASS      Data: inputs readable at decision time
      Pass 5 PASS      Errors: cost when wrong is medium
      Pass 5 WARN      Privacy: personal data; involve data protection early
      Pass 6 Value     fixing the cause saves up to 255 h a month; reaching the target on the rest saves up to 595 h a month (about 32,725 a month at 55 an hour)
      -> PROTOTYPE: Prototype a generative AI assistant and compare it with the benchmark
         also fix: Schedule the credit limit and score update jobs; review stale limits
         compare with standard: Credit Management jobs update scores and limits, but nothing gathers the context per order

    If you did the problem framing exercise, the second line says frame found, 0 fields taken from it instead. That is fine: the sample file already holds the numbers.

  3. Read the last lines of the other two reports:

      -> FIX FIRST: Buyers update purchase order prices when a supplier price changes; then measure again and reassess what is left
         then use standard: Automatic release of invoices blocked due to variances (MRBR, background program RM08RELEASE) is not scheduled
      Pass 5 FAIL      Labels: 150 labeled past cases; record outcomes before modeling
      ...
      -> PARK: Labels: 150 labeled past cases; record outcomes before modeling

Three problems, three different answers. The blocked orders are a good AI candidate. The invoice "agent" needs a data fix and a scheduled standard job first. The MRP ranking idea has value, but no recorded outcomes to learn from yet, so it is parked with a clear condition.

Step 5: Reassess after the fix

Suppose the buyers fixed their prices and automatic release is now scheduled. Fewer invoices are blocked, and the reasons that remain are different. Reassess what is left.

  1. In VS Code, right-click unit14/assessment, choose New File, name it invoice_after.txt, paste this and save:

    # Made-up reassessment after the price fix and the scheduled automatic release.
    NAME: Blocked invoices, after fix
    PROBLEM: Clerks spend most of each blocked invoice finding out why it is blocked and whether the reason still holds
    UNITS: minutes
    BASELINE: 22 | measured, shadowing of 10 invoices
    TARGET: 12
    VOLUME: 900 | system, blocks left after automatic release was scheduled
    HOURLY_COST: 50
    CAUSE_FIXABLE: 0.05 | system, after the buyers fixed purchase order prices
    FIX: Buyers update purchase order prices when a supplier price changes
    STANDARD: no
    STANDARD_DETAIL: Automatic release is now scheduled; these blocks are the ones it can't clear
    RULES_WRITABLE: yes
    EXPERTS_AGREE: 0.95 | measured, two clerks on 20 past invoices
    INPUT: structured
    OUTPUT: decision
    LABELED_HISTORY: 30000
    TOOLS: 1
    DATA_ACCESS: yes
    ERROR_COST: high
    HUMAN_REVIEW: yes
    CHANGES_SAP: no
    PERSONAL_DATA: no
    HIGH_RISK_DOMAIN: no
  2. Run:

    python unit14/opportunity_assessor.py assess unit14/assessment/invoice_after.txt
  3. The last lines should be:

      Pass 6 Value     fixing the cause saves up to 16 h a month; reaching the target on the rest saves up to 142 h a month (about 7,125 a month at 50 an hour)
      -> AUTOMATE: Write the rules as a decision table and automate them; no AI needed

The request was for an AI agent. The honest answer, after two cheaper steps, is a decision table that proposes the next step for each remaining block, with a clerk still deciding. SAP Build Process Automation's decision tables are one way to build it; a small rules function in your own code is another.

Step 6: Rank and write the report

  1. Run:

    python unit14/opportunity_assessor.py rank "unit14/assessment/*.txt" --md unit14/assessment/assessment.md
  2. You should see:

    Opportunity                  Decision      Shape      h/month  Next step
    Blocked supplier invoices    FIX FIRST     RULES          642  Buyers update purchase order prices when a supplier price changes; then measure again and reassess what is left
    Blocked invoices, after fix  AUTOMATE      RULES          159  Write the rules as a decision table and automate them; no AI needed
    Blocked sales orders         PROTOTYPE     GENERATE       850  Prototype a generative AI assistant and compare it with the benchmark
    MRP exception review         PARK          PREDICT        280  Labels: 150 labeled past cases; record outcomes before modeling
    
    Wrote unit14/assessment/assessment.md
  3. Open unit14/assessment/assessment.md. It holds the table, an Open points list with every warning and failed gate, and a line for the sponsor's signature.

The order is deliberate. Cheap fixes come first because they change everything after them, then rules, then AI prototypes, then parked and dropped ideas. Within a decision, bigger prizes come first. The hours column adds both savings and is a ceiling, not a promise.

How the code works

Part of the script What it does
FIELDS, CHOICES, NUMBERS, REQUIRED Define every field, the allowed words, which fields are numbers, and which must be filled
Thresholds (FIX_FIRST_SHARE and the others) The course's starting cut-offs. Change them for a real customer and say so in the report
SAMPLES The three made-up assessments, for order-to-cash, procure-to-pay and plan-to-produce
read_assessment Reads FIELD: value lines; if FRAME points to a file that exists, fills missing fields from it
check_fields Stops with a clear error when a field is missing, not a number, or not an allowed word
assess, passes 1 to 4 Records agreement, the fixable cause, the standard check, and picks the shape
assess, pass 5 Builds the gates; any FAIL parks an AI or rules path
assess, pass 6 Computes the two hour ceilings, only when the metric is in minutes
Decision block Checks the seven decisions in order; the first match wins
cmd_rank Sorts by decision order, then by hours, and writes the Markdown report

Use your own problems

  1. Create an empty assessment:

    python unit14/opportunity_assessor.py new unit14/assessment/my_problem.txt
  2. Open it and replace every (...) with your answer. If you have a frame, set FRAME: unit14/framing/my_frame.txt: the tool then reads PROBLEM, UNITS, BASELINE, TARGET and CHANGES_SAP from it, so you can delete those lines.

  3. Run assess on it until there are no ERROR lines.

If something goes wrong

What you see What it means What to do
python: command not found or 'python' is not recognized Python isn't installed or isn't on the path Redo Set up your computer. On macOS or Linux, try python3
ModuleNotFoundError You ran a different script, or a file named like a built-in module (such as glob.py) sits in unit14 This script needs no libraries. Check the file name, and rename any file called glob.py, argparse.py or pathlib.py
A message about a missing API key You ran another unit's script This tool needs no key and no account
A proxy or network error You ran another unit's script This tool never uses the network, so it works behind any proxy
can't open file ... opportunity_assessor.py The terminal isn't in orchestrate-course, or the file is elsewhere Run cd to your course folder; check the file is in unit14
ERROR missing fields: ... Lines still hold (...) or are missing Fill in each listed field
ERROR STANDARD must be one of: yes, partial, no A typo or another word Use exactly one of the listed words before any |
file not found: unit14/assessment/*.txt No files match the pattern Run sample first, or check the folder name
frame not found; using this file only FRAME points to a file that doesn't exist Fine if the assessment has the numbers itself; otherwise fix the path
Pass 6 Value not computed UNITS isn't minutes Use the business case calculator for other metrics

The SAP way

The ladder maps onto SAP offerings. Status and names below are as of October 2026, from the sources listed.

Rung 0: finding fixable causes

SAP Signavio Process Insights extracts data from SAP ERP and reports process performance indicators. SAP Learning lists over 200 indicators across more than 90 process flows, and over 160 correction recommendations, such as configuration changes or master data fixes. It flags blockers by the share of documents affected. Use it, or your own queries, for pass 2.

Rung 1: standard functions

  • Invoice verification. Automatic release with MRBR, in the background with RM08RELEASE, deletes blocking reasons that no longer apply and releases the invoice. Authorization object M_RECH_SPG controls which blocking reasons a user may delete. Any rules or AI built on top must not do more than the clerk is allowed to.
  • Credit Management. Scheduled jobs update credit limits and scores for business partners. A blocked order caused by a stale limit is a job-scheduling problem before it is an AI problem.
  • Situation Handling. For MRP, the template SAP_PP_MRP_MATERIAL_EXCEPTION alerts a team of planners about selected exceptions and opens Manage Material Coverage. The RIG post is from 2021; check the template in your release.
  • Embedded AI. The SAP Business AI Feature Catalog and Feature Estimator in SAP Discovery Center list embedded features with release stage, and estimate AI units. Licensing and AI units are covered in Embedded AI across SAP applications.

Rung 2: rules and workflow

SAP Build Process Automation offers a workflow builder, a business rules editor with decision tables and flowcharts, attended and unattended bots, and document information extraction. sap.com says LLM-based extraction without templates is in the premium edition. Joule can generate processes, forms and decisions from natural language at design time. That is AI helping you build the rules; the rules still run as rules.

Rungs 3 to 5: AI

Prioritizing with SAP AppHaus

The AppHaus Explore workshop places use cases on a Value Heatmap. The guide's examples are business value against complexity, or against time to market. It also lists reach, risks and costs as possible dimensions. Its Use Case Brief has a technical view with Limitation Cards, and an ethical view asking about personal data, automated decisions and high-risk domains such as HR. The workshop ends with a Next Steps Matrix: what, when, who. The assessor's gates and report cover the same ground, in a form you can keep in Git and rerun.

Build vs. SAP

Need Your own assessment (this topic) SAP offering
Find fixable causes at scale Queries over process data, sampled cases SAP Signavio Process Insights, if licensed
Check standard first Your notes, per release Process documentation, Feature Catalog
Compare and rank in a workshop Ranked list and report AppHaus Value Heatmap and Next Steps Matrix
Repeatable, versioned decisions Assessment files in Git, rerun after each fix No direct equivalent found in the sources opened
Build the rules once decided A rules function in your code SAP Build Process Automation decision tables

A practical mix: run an AppHaus-style workshop for buy-in, then keep the decisions as assessment files that you rerun when the numbers change.

Production concerns

An assessment is not software in production, but it drives decisions that are. Treat it with the same care.

  • Evidence labels. Every number carries system, measured or estimate. A decision built on estimates is provisional; say so in the report.
  • Authorizations. The data access gate means the solution reads data under the user's own authorizations, not a broad technical user. An assessment that assumes broad access will fail later in security review.
  • Approval. Anything that changes SAP data needs a person approving it, enforced in code. Mark it at assessment time so the prototype is designed for it.
  • Privacy. Assessment files describe business processes and may hold volumes and costs. Keep them in the private part of your repository, as Set up for Unit 14 describes for discovery notes.
  • Clean core. Rungs 0 to 2 often mean configuration and scheduling, not custom code. Prefer them. When you build, build on released APIs beside the core.
  • Cost. Lower rungs are cheaper to run. A rule costs nothing per case; a language model call costs tokens; an agent costs several calls per case. Token economics shows the arithmetic.
  • Reassessment. Schedule a reassessment after each fix or go-live. The thresholds in the script are judgment calls; record any you change.

Pitfalls

  • Assessing the request, not the frame. "An agent that clears invoices" can only be built. Assess the framed problem.
  • Skipping pass 2 because it is boring. Fixable causes are where the cheapest wins hide.
  • Checking "standard" from memory. Check the release the customer actually runs, and write down the date.
  • Calling everything a hybrid. A hybrid needs a clear split: which cases rules handle, which the AI handles, and how you know.
  • Treating hours as savings. The hours are ceilings at the target. Real savings depend on adoption and realization.
  • Parking without a condition. "Park" needs a named condition and an owner, such as "record planner actions for three months".
  • Letting thresholds become law. The course's 30%, 60%, 90%, 1,000 and 20 hours are starting points. Change them with reasons.

Exercise

Assess your own framed problem next to the samples, and write the report your next prototype starts from.

  1. Create your assessment, unless my_problem.txt already exists from Use your own problems:

    python unit14/opportunity_assessor.py new unit14/assessment/my_problem.txt
  2. Fill it in from unit14/framing/my_frame.txt, your problem framing exercise. Set FRAME to that file. If you have no frame, use the late-delivery example: deliveries predicted from shipping history, OUTPUT: prediction, INPUT: structured.

  3. For STANDARD, check at least one SAP source for your process step, and put the source and date in STANDARD_DETAIL.

  4. For EXPERTS_AGREE, if you can, ask two people to decide the same ten cases. Otherwise write a number and label it estimate.

  5. Run assess on it until there are no ERROR lines:

    python unit14/opportunity_assessor.py assess unit14/assessment/my_problem.txt
  6. Write the report for all your assessments:

    python unit14/opportunity_assessor.py rank "unit14/assessment/*.txt" --md unit14/assessment/assessment.md
  7. Under the table in assessment.md, add one sentence for your own problem: the decision, and the single fact that would change it.

  8. Save your work:

    git add unit14/opportunity_assessor.py unit14/assessment/
    git commit -m "Unit 14: opportunity assessor and assessment report"

Done when assess on my_problem.txt prints a decision with no ERROR lines, assessment.md lists your problem with its decision and next step, and your sentence names the fact that would change the decision. Keep it: rapid prototyping, next in Unit 14, starts from a problem marked PROTOTYPE.

Check yourself

Pick one answer for each question. The explanation appears after you choose.

1Why does the assessment check fixable causes before the shape of the work?

Answer: D. Removing a cause removes cases, and the remaining cases can have a different shape. In the invoice sample, fixing prices and scheduling automatic release left 900 blocks that suited rules. The shape question only makes sense on what is left.

2In the script, a file has RULES_WRITABLE: yes, INPUT: structured and EXPERTS_AGREE: 0.8. Which shape does pass 4 pick, and why?

Answer: C. The rules branch needs all three conditions, and 0.8 is below the 0.9 threshold. The script then checks the other shapes. CLARIFY is a separate decision, used only below 0.6.

3What does the data access gate check?

Answer: C. Google's guidance says inputs must be available when the prediction is made. Reading them under the user's own authorizations keeps the solution from seeing more than the user may. Row counts belong to the labels gate, and only for predictive work.

4You are assessing MRP exception ranking. Planners agree on 70% of cases, there is no large fixable cause, and only 150 exceptions have a recorded planner action. What would you do?

Answer: B. The output is a prediction from structured history, so the labels gate applies and fails below 200. Parking with a named condition keeps the idea. Switching to a generative assistant just to dodge the gate changes the solution, not the problem.

5Which standard SAP function does the course suggest checking before any AI for blocked supplier invoices?

Answer: C. Automatic release deletes blocking reasons that no longer apply and releases the invoice when none are left. RM08RELEASE runs it in the background. The other functions belong to planning, credit or AI-unit estimates.

6How does the script compute the hours on the rest for blocked sales orders?

Answer: A. The rest is the orders the fix doesn't remove, at the minutes the target saves. That gives 595 hours, a ceiling. The fix's 255 hours is the separate line, and adoption comes later in the business case.

7An assessment returns AUTOMATE for an output that would change SAP data. What must the build include?

Answer: B. This course requires a person to approve any change to SAP data, whatever the technology. Deterministic rules can still be wrong for a case. A broad technical user would also break the authorization principle.

8How is SAP AppHaus's Value Heatmap different from the assessor's ranked report?

Answer: A. The heatmap places use cases relative to each other, usually on value and complexity, to build agreement. The report records each decision with its evidence, and you rerun it when numbers change. The two work well together.

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