MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1
Bounds and cancellation
Predict then observe repetition, budgets, cancellation and an unavailable dependency.
Objectives
- Use this page to understand: Bounds and cancellation.
Prepare a model-free experiment
Use a complete built distribution and start without --live. Transport is scripted but native agents, the loop and guarded tools are real. Record command, exit code, Status, ModelCall/ToolCall count and stopping reason. No business database is required.
Same argument, different arguments, no tool
dotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- repeatdotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- changingdotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- budgetdotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- incompleterepeat: one admitted attempt then RepeatedCall. changing: four admitted attempts with different identifiers then ToolBudget. budget: first read admitted, then ModelBudget on the next model call. incomplete: zero tools, “Review finished.” text retained under Incomplete. All return 2. Compare outcomes with limits instead of counting printed messages only.
{"Status":"RepeatedCall","Text":null,"Events":[{"Kind":"ModelCall","Name":"model","Count":1},{"Kind":"Middleware","Name":"read_ticket","Count":0},{"Kind":"ToolCall","Name":"read_ticket","Count":1},{"Kind":"ModelCall","Name":"model","Count":2},{"Kind":"Middleware","Name":"read_ticket","Count":1},{"Kind":"RepeatedCall","Name":"read_ticket","Count":1}]}Refusal, deadline and unavailability
dotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- forbiddendotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- deadlinedotnet run --project demos/Demo330_BoundedHarness/Demo330.App.csproj -c Release --no-build -- complete --live --AI:ChatProvider=Ollama --AI:LocalChat:Endpoint=http://127.0.0.1:1/ --AI:TimeoutSeconds=3forbidden: PermissionDenied before any tool body; deadline: expiry after one second; closed local endpoint: ProviderUnavailable with one transport attempt and no tool. The final trial explicitly selects Ollama and a test failure endpoint; it calls no cloud. Do not stop a server used by another application to manufacture the outage.
{"Status":"ProviderUnavailable","Text":null,"Events":[{"Kind":"ModelCall","Name":"model","Count":1}]}For manual cancellation, run deadline then Ctrl+C before expiry: expected outcome is 130, not DeadlineExceeded or fallback output. This race can be hard to produce manually; tests trigger cancellation in a controlled way inside the Harness and a tool body. This lot verifies cancellation through tests without claiming an interactive Ctrl+C during CLI checks.
Read verification at the execution boundary
dotnet test tests/Maf.Control.Tests/Maf.Control.Tests.csproj -m:1 -c Release --no-build --no-restoreTwoStepTaskCompletesOnBothNativeAgents checks three model calls and two tools. DirectInvocationCannotBypassPermission tests refusal outside the loop; ConcurrentDuplicateCallsReachBodyOnce checks one body entry across eight concurrent calls. CallerCancellationThroughNativeHarnessPropagates and CancellationReachesToolBody cover the token. Ep011CancellationCannotBecomeFallback checks failure/cancellation racing. These tests retain real MAF and tools with scripted transport.
Verification hints
Before reading the correction, record prediction and observation. Separate generated text, terminal state, decision and persisted state. If they differ, follow the file and test named in the procedure; do not remove the guard to obtain the expected result.
Explain what a bound does not do
A new invocation creates a new scope: the same read_ticket becomes admissible again. Setting Repetitions to two and ToolCalls to three in a local copy allows attempt prediction but creates no durable authorization. This exercise establishes neither maximum monetary cost, forced termination of a provider ignoring cancellation nor general injection resistance. For replay of an already committed effect use the previous chapter’s persistence protocol.
