In this section

0.3 The Tools and Their Versions

Module 0

Introduction

The course runs on a small set of free tools. This lesson names each one, says what it does in the lab and why the course needs it, and gives the version the course was built with, read from each tool when the lesson was generated. Lesson 0.4 installs them; this lesson is what you are installing and why.

Most of the tools come together. Microsoft's Azure Logic Apps (Standard) extension for Visual Studio Code installs the runtime's dependencies for you, so for most readers the list is Visual Studio Code, the extension, and Python for the harness. The rest of the lesson explains what the extension brought, so that when something goes wrong you know which piece to look at.

1

Seven Tools

What each one is for

The lab needs these, and nothing else, until Module 11:

{
  "the lab's tools": {
    "Visual Studio Code": "the editor, with the designer and run history",
    "Azure Logic Apps (Standard)": "the extension; installs the next three",
    "Azure Functions Core Tools": "starts the Logic Apps runtime locally",
    ".NET SDK": "what the runtime itself runs on",
    "Node.js": "inline code; also runs the lab's query engine",
    "Azurite": "local storage for run history and state",
    "Python": "runs the harness and run-spec"
  }
}

Visual Studio Code is where you edit the workflow files and, with the extension, open the workflow designer and the run history. The course works mostly in the workflow.json files directly, because they are what gets reviewed, versioned and deployed, but the designer is a good way to see a workflow's shape and the run history is where you read what a run did.

The Azure Logic Apps (Standard) extension is the piece that makes Visual Studio Code a Logic Apps workbench. Learn's page on creating Standard workflows in Visual Studio Code lists what it installs: Azure Functions Core Tools, the .NET SDK and Node.js.

Learn's older single-tenant page adds that from version 2.81.5 the extension's dependency installer puts them in a new binary folder of its own and leaves any versions you already have untouched, and that Azurite for Visual Studio Code is among its dependencies.

Azure Functions Core Tools starts the Logic Apps runtime on your machine: the Standard runtime is built on the Azure Functions host, and Core Tools is how that host runs locally. The .NET SDK is what the runtime runs on. Node.js runs JavaScript in the inline code action that Module 7 uses, and it also runs the course's query engine, which the harness uses to answer Log Analytics queries.

Azurite is a local copy of Azure Storage. Python runs the harness and run-spec. Both are explained below.

Each tool is there because removing it would remove something the course depends on. Without the runtime there is nothing to run the workflows on; without Azurite the runtime has nowhere to keep what it did; without the harness the workflows have nothing to call; without run-spec there is no way to check a change against the cases. Nothing on the list is a convenience.

Nothing on the list needs an Azure account. Learn's page is explicit that Azure access is needed only to deploy, to use managed connectors, or to work with existing Azure resources, and built-in operations do not need it. Every operation the playbook uses before Module 11 is built in.

2

Visual Studio Code and the Extension

Your workbench

Visual Studio Code runs on Windows, macOS and Linux, and so does everything the extension installs. The course was built on Linux and its commands are written for a bash shell; Lesson 0.4 gives the Windows equivalents where they differ.

The extension is installed from Visual Studio Code's Extensions view by searching for Azure Logic Apps Standard. When it creates a project, the first file it writes is the one the runtime reads before anything else:

{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle.Workflows",
    "version": "[1.*, 2.0.0)"
  }
}

That is host.json, the one file every Standard project has at its root, and the first of the files the extension creates for you. It names the extension bundle, the package that provides the workflow engine, by id and version range. The runtime reads it before any workflow, and the range means the runtime uses the newest bundle in the 1.x line it can find.

After the extension installs, Learn's page asks for two checks in its settings, and they are the first thing to look at if the runtime will not start.

The two settings are Project Runtime, which must be ~4, the version of the Functions runtime that Standard workflows run on, and, if you prefer, whether Azurite starts automatically when a project opens. Learn notes that ~4 is required for inline code. Leaving automatic updates on is also Learn's advice, and the course assumes it.

Creating a project is a menu step. In the Azure pane, the Workspace toolbar has an Azure Logic Apps menu with Create new logic app workspace; Learn's steps then ask for a folder, a workspace name, the Logic app project template and a workflow template, where the course always chooses Stateful Workflow.

A stateful workflow keeps its run history, inputs and outputs, which is what the course reads after every run.

Running is another. Start Debugging on the Run menu starts the runtime with your project, and the workflow's Overview page shows its callback URL, the address a request must be sent to, and its run history. Lesson 0.5 does both.

You do not have to use the designer. Everything the course does can be done by editing workflow.json and restarting the runtime, and the lessons show the JSON rather than designer screenshots so that you can see exactly what changed.

3

The Runtime

Core Tools, .NET and the settings file

The runtime is the Azure Functions host with the Logic Apps workflow extension loaded. Visual Studio Code starts it for you, and it can also be started from a terminal in the project folder with Core Tools' host start command. Either way, it reads one more file before it runs anything:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "APP_KIND": "workflowapp",
    "HarnessUrl": "http://127.0.0.1:8642"
  }
}

local.settings.json holds settings for this machine only. AzureWebJobsStorage tells the runtime where its storage is; UseDevelopmentStorage=true means the local emulator, Azurite. FUNCTIONS_WORKER_RUNTIME and APP_KIND tell the host it is running workflows.

The last value is the course's own: the address of the harness, which the workflows read through a parameter so that the same definition can point at the harness in the lab and at the real services in a tenant.

Every value in it is a string, even the ones that look like numbers or switches, because it is a list of environment settings. A workflow reads one through a parameter whose value is an app setting reference, which is how the harness address reaches the HTTP actions. In Module 3 the same mechanism carries the lab identities' client ids, and in Module 11 the tenant's managed identity ids.

The file is never deployed and never committed. Module 3 explains why, after the secrets for the lab identities are added to it, and Module 11 replaces it in a tenant with app settings and Key Vault.

Core Tools also installs the extension bundle the first time the runtime starts, downloading it from Microsoft and caching it on your machine. That first start therefore needs an internet connection and takes longer than later ones; after that, the runtime starts from the cache.

When the runtime has started, it prints the workflows it found and the address it is listening on, by default port 7071 on your machine. A workflow whose definition has an error is reported then, by name, before anything can call it, which is the fastest place to catch a mistake: a definition the runtime rejects never gets to run against anything.

A useful habit is to keep the runtime's terminal visible while you work. It prints each run as it starts and ends, and an error in a definition, a missing parameter or a refused connection appears there first, often before the run history shows anything. Most problems in the first modules are visible in that terminal within a second of sending a request.

The runtime runs every workflow in the project folder, so one runtime serves the triage workflow and every small workflow it calls. That is also how it runs in Azure, which is why a call from one workflow to another works the same way in both places.

4

Azurite

Storage on your own machine

A Standard logic app keeps its run history, its state and its queues in Azure Storage. On your machine that is Azurite, Microsoft's storage emulator:

# what the course runs; the extension can start the same emulator itself
azurite --silent --location ~/.au-lab/azurite
# the runtime then finds it through local.settings.json:
#   "AzureWebJobsStorage": "UseDevelopmentStorage=true"

The extension can start it whenever a project opens, which is the setting Learn mentions. The course's own runs start it from a terminal with a fixed folder, so that its data is in one known place.

That folder is worth knowing about, because it is where your run history lives. Deleting it clears every run, which is useful when a page of old runs makes the newest one hard to find, and harmless, because the workflows themselves are in your project folder, not in storage.

Azurite keeps nothing that matters beyond the runs. There is no setting in it to configure for the course, no account to create and no key to copy: the UseDevelopmentStorage value tells the runtime to use the emulator's well-known local address and key, which every copy of Azurite answers to. A fresh install works the first time.

If Azurite is not running when the runtime starts, the runtime cannot store anything and stops trying after a few attempts, with errors about connections refused on the emulator's port. It is the most common reason a first run fails, and the first thing to check.

The emulator listens on three local ports, one each for blobs, queues and tables. Learn's page on Standard billing describes how the runtime uses storage: queues to schedule trigger operations, and tables and blobs to keep workflow state.

Runs, their inputs and outputs and their history are all state, which is why the run history disappears when Azurite's folder is deleted but the workflow definitions, which live in your project folder, do not.

Nothing in the course reads Azurite directly. Everything goes through the runtime, which reads and writes storage the same way it would in Azure, so the lab exercises the real storage behavior without needing a storage account.

Azurite is the reason no cloud storage account is needed in the lab. In a tenant, Module 11's Bicep creates a real storage account and the logic app's settings point at it instead; the workflows do not notice the difference.

5

Python and Node.js

For the harness and its data

The harness is a Python program, and run-spec, the test runner, is another. Neither needs any package beyond Python's standard library. The harness answers Log Analytics queries by passing them to the course's query engine, which is JavaScript and runs on Node.js, against the data tables in the lab pack.

The lab pack carries the engine and only the tables the harness reads, 15 of them counting the watchlists, so the pack stays small enough to download quickly and the harness starts in seconds. When a lesson asks you to run a query yourself in the browser console instead, that console has the course's full set of tables.

So the lab is three processes: Azurite for storage, the harness for the services, and the runtime for the workflows. They start in that order, because the runtime needs storage to start and the workflows need the harness when they run, and they stop in the reverse order. Lesson 0.4 starts all three and checks each.

Checking the versions you have is one command each:

$ func --version
4.16.0
$ dotnet --version
8.0.428
$ azurite --version
3.37.0
$ node --version
v22.23.4
$ python3 --version
Python 3.13.18

Those are the build workspace's answers. Yours will differ in the last digits, and that is fine for every tool except one: Project Runtime must be ~4, which is a setting, not an install.

The harness listens on port 8642 by default, the runtime on 7071 and Azurite on 10000 to 10002.

If another program already uses one of them, the process that starts second fails with an address-in-use error, and the fix is either to stop the other program or to start the lab process on another port and change the matching setting. The harness's port is the HarnessUrl value in local.settings.json, so moving it is a one-line change.

The order matters on the way down as well. Stopping the harness while a run is waiting on it leaves the run failing its next call, and stopping Azurite under a running runtime makes the runtime log storage errors until it is stopped too.

Python and Node.js are often already installed. If your Python is older than the one shown, the harness may still run, but the course was only tested on the version above, and an error from the harness on an older Python is worth checking against a current one before anything else.

6

Why the Versions Are Written Down

And what to do when yours differ

The versions the course was built with, as each tool reported them:

{
  "the build workspace, 13 November 2026": {
    "Azure Functions Core Tools": "4.16.0",
    ".NET SDK": "8.0.428",
    "workflows extension bundle": "1.194.31",
    "Azurite": "3.37.0",
    "Node.js": "v22.23.4",
    "Python": "3.13.18",
    "Bicep CLI (Module 11)": "0.49.2"
  }
}

Learn's pages do not pin versions. The extension installs what it currently installs, Core Tools updates, and the workflow engine arrives as an extension bundle whose exact version is chosen when the runtime starts, within the range host.json allows. The bundle version above is the one the build workspace's runtime downloaded.

Writing the versions down does two things. It tells you what the lessons' output came from, so that if your run shows something different you can check whether the difference is a newer tool. And it makes the course's claims checkable: a behavior shown in a lesson is the behavior of these versions, not of whatever is current when you read it.

When yours differ, the rule is simple. A newer patch version of anything should behave the same; if it does not, the run history and the runtime's output will say why. A newer extension can also change how the designer looks or where a menu sits, which affects nothing the course does, since the lessons work in the files.

A different major version of Core Tools or of the bundle could change behavior the course depends on, and the course's cases are the quickest way to find out: run them, and a change in behavior shows as a failing case with a reason.

The extension itself updates on its own if Learn's advice to leave automatic updates on is followed, and it can update the dependencies it installed.

That is convenient, and it is why a version check is the first step when a lesson's output and yours differ in a way the lesson does not explain. Two minutes comparing versions can save an hour of debugging a difference that is only a newer tool.

If you need to match the course exactly, Core Tools and the .NET SDK can be installed at a given version alongside the extension's own, and the runtime started from a terminal with that Core Tools. The course does not require it.

The course is kept current against these tools. When a lesson is rebuilt, its versions are read again, so the list above is always the one the lesson's runs used.

7

What You Do Not Need Yet

Saved for Module 11

Some tools appear in the course but are not needed for a long time:

{
  "not needed until Module 11": {
    "a subscription and a Sentinel workspace": "where the playbook is deployed",
    "Azure CLI": "deploys the Bicep and the workflow zip",
    "Bicep CLI": "compiles and lints the templates",
    "shellcheck": "checks the deployment scripts",
    "a GitHub repository": "for the pipeline in Lesson 11.6"
  }
}

Nothing in Modules 0 to 10 touches Azure. The workflows call the harness, the runtime keeps its state in Azurite, and the data comes from the pack.

Module 11 needs an Azure subscription where you can create resources, a Microsoft Sentinel workspace to deploy the playbook beside, and the rights to grant permissions to managed identities, and it needs the Azure CLI, the Bicep CLI and shellcheck on your machine. Lesson 11.1 lists them again with what each one checks.

That order is deliberate. A playbook should be proved in the lab before it reaches a tenant, and a learner should not need a subscription to learn how to build one.

If you have access to a tenant already, there is still no reason to use it before Module 11: the harness can fail calls on demand, which a tenant cannot, and nothing you do in the lab can isolate a real device by mistake.

You also do not need a Microsoft 365 license, a Defender for Endpoint license or a test device at any point before Module 11. The data in the lab pack stands in for all of them.

Nor do you need an approval service. Module 8 defines one as a contract, a small service that holds approval requests and calls the playbook back with the answer, and in the lab the harness plays it, answering on demand as a case asks. Module 11 explains what a team runs in its place in a tenant.

The same is true of the identities. Module 3 creates five identities in the harness, each with its own permissions, and they behave the way Entra ID app registrations and managed identities do: they get tokens for a service, and the harness checks those tokens on every call. You learn least privilege before you have a tenant to apply it to.

When you reach Module 11, you will install three more tools in the same way as the ones in this lesson, and the lesson will read their versions in the same way.

Do

Practice

Check what you already have
your tenant

Before installing anything, see which of the tools you already have and at what version.

Do this Check what you already have
  1. Run each version command in this lesson in a terminal, and note what answers.
  2. Compare your versions with the build workspace's list.
  3. Look for Visual Studio Code and the Azure Logic Apps (Standard) extension.
  4. List what is missing, which Lesson 0.4 installs.
Done when you know which tools you have, at which versions, and which you still need.

Lesson 0.4 installs the tools on Windows, macOS or Linux and downloads and checks the lab pack.