Build autonomous or semiautonomous workflows with safeguards and approval flow controls
AI-103 › Unit 2: Implement generative AI and agentic solutions › Build agents by using Foundry › Build autonomous or semiautonomous workflows with safeguards and approval flow controls
Build autonomous or semiautonomous workflows with safeguards and approval flow controls
Autonomy is a spectrum, and building on it means adding the safeguards the chosen point requires. A fully autonomous agent needs bounds and reversibility because nobody is watching; a semiautonomous one needs a pause that is durable, a reviewer who can actually judge, and a resumption path. This objective is the construction detail behind those choices.
Why This Matters
The approval must interrupt the action, not report it. A control that fires after the call has already gone out is auditing, not approval. That distinction decides questions.
A pause is only safe if it is durable. An approval that may take hours needs checkpoints — "save and restore workflow progress" — or a restart discards the work.
Autonomy needs bounds even when the actions are safe. Without a termination condition an autonomous agent can loop indefinitely, which is a cost and reliability failure rather than a safety one.
Prerequisites
require_approvalas a per-tool pre-action control.- Human-in-the-loop as "pause for external input and resume", and checkpoints.
- That instructions are not a security boundary.
- Indirect prompt injection, and that its shield is off by default.
Learning Objectives
By the end of this lesson you will be able to:
- Place a workload on the autonomy spectrum and name what each point requires.
- Implement an approval flow that interrupts, informs, and resumes.
- Add bounds — turn limits, budgets, termination conditions.
- Design for reversibility and idempotency where autonomy is high.
- Combine content controls and action constraints against injection.
Building Blocks
The autonomy spectrum.
| Point | Human role | Requires |
|---|---|---|
| Autonomous | Reviews afterwards | Bounds, reversibility, strong instrumentation |
| Semiautonomous | Approves consequential calls | require_approval + durable pause |
| Supervised | Approves everything | Rare; degrades into rubber-stamping |
The approval mechanism. require_approval on a tool pauses the run before invocation, surfaces the intended call and its arguments, and continues only on approval.
Durability. Checkpoints "save and restore workflow progress"; human-in-the-loop is "pause for external input and resume". Together, a wait is persisted state rather than a held-open process.
Bounds. Termination conditions, maximum turns, and budget limits. Nothing in an orchestration stops by itself.
Structural constraints. Not attaching a tool; scoping the agent's Entra identity; a private tool catalog; a pinned toolbox version; an AI gateway for rate limits and IP restrictions.
Injection defence. Prompt Shields for indirect attacks is GA but off by default and requires document embedding and formatting.
Approval against logging
| Attribute | ||
|---|---|---|
| When | Before invocation | After the fact |
| Can prevent | Yes | No |
| Shows the reviewer | The call and its arguments | What already happened |
| Satisfies | "A human must authorise" | "We must be able to show what happened" |
| Mechanism |
| Traces plus a durable store |
Deep Dive
Placing the workload, then building for it
Each point on the spectrum comes with obligations.
Autonomous fits reversible, low-value, read-mostly work. Because nobody is watching in real time, it needs the compensating controls: an explicit termination condition, a budget or turn limit, tool actions that are reversible or idempotent, and instrumentation strong enough that a bad run is caught by monitoring rather than by a customer.
Semiautonomous is the working default for mixed surfaces. Reads run freely; the consequential calls pause. The obligations are the approval mechanics below.
Supervised — approving everything — is appropriate only where every action is irreversible or regulated, and its failure mode is documented: reviewers facing routine approvals stop reading. The appearance of oversight is worse than none because it is trusted.
The classification rule is consequence, not capability. "What happens if this call is wrong?" is the question, not "how powerful is this tool?". Reads, drafts, and simulations are safe even from a powerful tool; a write to a system of record is not, even from a simple one.
Building a semiautonomous flow
Classify every tool by consequence
Reversible → autonomous. Writes, payments, outbound communication, deletion → gated.
Building the approval flow
Three properties make an approval real.
It interrupts. require_approval pauses before invocation. A design that logs the call and lets it proceed satisfies auditing and not approval — the money already moved. Any option that reviews after the fact is wrong when the requirement says a human must authorise.
It informs. The reviewer sees the intended call and its arguments. This is the property most often lost in implementation: a prompt saying "the agent wants to issue a refund — approve?" without the amount, the account, and the reason gives the reviewer nothing to judge, and produces approval-by-default.
It resumes durably. Because approval can take hours, the pause must be checkpointed. Otherwise the run is a process held open, and a deployment or restart discards it. A scenario mentioning overnight approval, resilience across restarts, or a queue of pending approvals is pointing at checkpoints.
A fourth property is worth adding in practice: what happens on rejection. An agent whose call is denied and has no instruction for that case will often try a variant. State the behaviour — report the refusal, escalate, or stop — the "give the model an out" technique applied to approvals.
Bounds and reversibility for autonomous work
When nobody approves each step, the safeguards move into the design.
Termination. Every orchestration needs an explicit stopping rule — goal met, turn limit, orchestrator decision. Its absence appears as Task Navigation Efficiency failures and as cost.
Budget. A token or call budget bounds the worst case independently of whether the logic is correct.
Reversibility and idempotency. Where actions are autonomous, prefer operations that can be undone or safely repeated. This matters more than it first appears because retries exist at several layers — the SDK retries twice by default, and a non-idempotent action retried is performed twice. Building the reversal path is often cheaper than proving the action can never be wrong.
Fail-safe defaults. When a tool errors or returns nothing, the agent must be instructed to stop or escalate rather than to proceed on assumption. Untreated, this is a Tool Output Utilization failure with real-world consequences in an autonomous flow.
Injection, where content and action meet
Autonomous agents ingesting third-party content are the highest-risk configuration, because a successful injection produces an action rather than merely bad text.
The content control is Prompt Shields for indirect attacks — GA, off by default, requiring document embedding and formatting. The direct-attack shield is on but inspects the user's prompt, which is not where the payload arrived.
The action controls are the constraints: an agent with no tool for the forbidden operation cannot be redirected into it; a scoped Entra identity makes the attempt fail at the platform; an approval gate puts a human between the injected instruction and the effect.
The framing worth carrying: filters lower probability, constraints lower consequence. Scenarios describing an autonomous agent that ingests supplier documents, web pages, or email are usually testing whether you reach for both — and whether you remember the indirect shield's default.
Worked Examples
Example 1 — approval that is not approval. An agent issues refunds and posts every issued refund to a review queue. Compliance asks for human authorisation.
The queue is logging: the refund already happened. Move to require_approval on the refund tool so the run pauses before invocation, surface the amount, account, and reason so the reviewer can judge, and checkpoint the pause so a wait across shifts survives restarts.
Example 2 — an autonomous agent that loops. An overnight reconciliation agent occasionally runs for hours without converging and consumes a large token budget.
A missing termination condition and no budget bound. Add an explicit stopping rule, a turn limit, and a token budget, and monitor Task Navigation Efficiency. Nothing in an orchestration stops by itself, and autonomy removes the human who would otherwise notice.
Example 3 — an autonomous agent reading supplier email. An agent processes supplier email and can update purchase orders. Security asks how injected instructions are prevented from causing an unauthorised update.
Both layers. Enable indirect-attack Prompt Shields — GA but off by default — to lower probability, and constrain consequence: require_approval on the update tool, an identity scoped so unauthorised writes fail at the platform, and no tool attached for operations that must never occur. Instructions alone are what the injected instruction competes with.
Visual Explanations
The spectrum and its obligations:
An approval that actually works:
Common Mistakes
Treating an after-the-fact queue as approval. It is logging.
Surfacing a summary instead of the call and arguments. The reviewer cannot judge.
Pausing without checkpoints. A restart discards the run.
Leaving rejection behaviour undefined. The agent tries a variant.
Gating everything. Rubber-stamping, exactly where attention mattered.
Classifying by capability instead of consequence.
Omitting termination and budget bounds in autonomous flows.
Ignoring idempotency where retries exist. The SDK retries twice by default.
Relying on the default filter set against injection. The indirect shield is off.
Practice Exercises
- Name the three properties an approval must have, and what each prevents.
- Why is an after-the-fact review queue insufficient when a human must authorise?
- What must be added to an autonomous flow that a semiautonomous one gets from the human?
- An autonomous agent ingests supplier documents and can update records. Name the control at each layer.
- Why does idempotency matter more as autonomy increases?
▶Answers
- It interrupts —
require_approvalpauses before invocation, preventing the action rather than recording it. It informs — the reviewer sees the actual call and arguments, preventing approval-by-default. It resumes durably — checkpoints save and restore progress, preventing a restart from discarding the run. - Because the action has already occurred. The queue satisfies auditing; the requirement is a pre-action control, which only
require_approvalprovides. - Explicit bounds — a termination condition, turn limit, and budget — reversibility or idempotency in the actions, fail-safe behaviour on empty or failed tool results, and instrumentation strong enough that a bad run is caught by monitoring.
- Content layer — enable indirect-attack Prompt Shields (GA, off by default), which lowers probability. Action layer —
require_approvalon the update tool, a scoped Entra identity so unauthorised writes fail at the platform, and not attaching tools for operations that must never occur. Instructions are not a control here. - Because retries exist at several layers — the SDK retries twice by default — and a non-idempotent action retried is performed twice, with no human present to notice. Reversibility also bounds the damage of a wrong autonomous action.
Summary & Concept Map
Autonomy is chosen and then paid for. Autonomous work needs bounds (termination, turn limits, budget), reversible or idempotent actions, fail-safe behaviour on empty and failed results, and instrumentation that catches a bad run before a customer does. Semiautonomous work needs an approval that has all three properties: it interrupts before invocation via require_approval, it informs by surfacing the actual call and arguments, and it resumes durably through checkpoints — with rejection behaviour defined so a refused agent does not simply try a variant. Classification is by consequence, not capability, and blanket gating fails by rubber-stamping. Against injection, combine layers: the indirect-attack shield is off by default and lowers probability, while unattached tools, scoped identities, and approval gates lower consequence.
Sources and freshness
Written against current Microsoft Learn documentation for the AI-103 skills measured (16 April 2026), reviewed 2026-08-20. Microsoft Learn controls every changing product contract — availability, preview status, quotas, limits, regional support, naming, and retirement dates all move independently of this lesson. Where a scenario turns on a specific number or a GA/preview boundary, confirm it against the product's own page before relying on it.