Skip to main content

maf-sandbox-bicep

PyPI Python License

Experimental. This package is early-stage (pre-1.0, Development Status :: 4 - Beta) — its API may change or be removed in a future release without notice. Importing it emits a one-time MafSandboxBicepExperimentalWarning; suppress it with warnings.filterwarnings("ignore", category=maf_sandbox_bicep.MafSandboxBicepExperimentalWarning) once you've read the notice.

This package is not affiliated with, endorsed by, or a product of Microsoft — it is a third-party reference implementation of microsoft/agent-framework#7568 for Microsoft Agent Framework.

Sandboxed Bicep validation as a Microsoft Agent Framework tool: bicep_validate writes the files an agent authored into a sandbox, runs bicep build and bicep lint there, and returns the compiler's SARIF diagnostics as structured text — T2 (compiler truth) instead of T0 (the model checking its own work).

app  ->  maf_sandbox  ->  a backend (maf-sandbox-acas, ...)  ->  this workload

This package is a sandbox kind in the sense of maf-sandbox's protocol. It contains no Azure import and no sandbox lifecycle code; it asks a SandboxRouter for a sandbox and gets back write_file and exec, so the same tool runs unchanged against ACA Sandboxes, a local Docker container or an in-process fake. Tests enforce both boundaries: one scans this package's sources for any Azure import, the other for any import outside what its manifest declares.

Quickstart

pip install maf-sandbox-bicep
from maf_sandbox_bicep import make_bicep_tools

tools = make_bicep_tools(router, file_store, "devops-engineer", context,
                         image="bicep-sandbox:0.46.1")

Pass router=None — or a router with no backend — and you get [] back: an unconfigured host attaches no tool rather than one that fails when called.

router, file_store and context are the host's, and this snippet shows none of them being built. samples/01_acas_bicep is the whole wiring as a runnable program: a one-turn agent that validates a deliberately flawed Bicep file and prints the compiler's diagnostics.

Threat model

Fixed command templates. No agent-authored text is interpolated into a shell command — the only substitution is a filesystem path, and only after that path is validated against the caller's file store listing (the injection guard: a name that isn't in the listing, or that resolves outside the work dir, is rejected before it reaches a template). Sanitized error surfaces. Failures the sandbox reports are cleaned before the model sees them, so a compiler or shell error cannot smuggle sandbox-internal detail back into the conversation. The egress allowlist. The only hosts Bicep is allowed to reach are the four an AVM module restore reads from — mcr.microsoft.com and *.data.mcr.microsoft.com for the artifacts, aka.ms and live-data.bicep.azure.com for the public module index — stated as a property of the spec (SandboxSpec.egress_allow), not of runtime configuration, because a deployment that could widen Bicep's egress after the fact could undo the containment the tool's design rests on. Nothing else is reachable, ARM above all.

What is Bicep-specific

What is Bicep-specific — the command templates, the accepted extensions, the SARIF parsing, the hosts Bicep is allowed to reach (the four an AVM module restore reads from) — lives here and only here. The spec pins the egress allowlist and work directory as properties of the workload, not of configuration: a deployment that could widen Bicep's egress could undo the containment the tool's design rests on.

Its companion artefacts live outside this package, because a container image and a registry are not Python: a pinned Bicep image on Azure Linux, and the registry and pull identity that serve it. The hard-won behaviours of the pinned CLI — SARIF on stderr for build but stdout for lint, build-params for .bicepparam, config discovery only by walking up from the source file — are documented where they bite, in _tool.py.

Upgrading to 0.14

0.14.0 requires maf-sandbox 0.34, which is where the sentence below can be committed at attach.

bicep_validate answers with a list of content items rather than one string. The first item is what it always returned — the diagnostics, or the sentence saying why there are none. The second is a standing sentence about the tool, labelled trusted, so a host whose information-flow middleware hides an untrusted result hides the diagnostics and leaves that sentence readable. Two kinds of host need no code change, and one does. A host that only lets the model read the result changes nothing — though the model does now read one sentence it did not before, which is the point of the change rather than a side effect of it. Neither does a host reading the framework's function-result content: .result there is the items' text joined with newlines — measured on agent-framework-core 1.13.0 and 1.17.0, the floor this package declares and the newest published — so the sentence simply arrives as a trailing line, with the items themselves on .items. What does change is a host reading the tool's answer directly, through invoke(..., skip_parsing=True) or by calling the body: that is a list[Content] where it was a str, and str() of a list renders item reprs rather than their text. Read .text off each item instead.

Why the sentence exists: an untrusted result the framework hides is replaced by a variable reference, which reads exactly like a compile that found nothing. The sentence says that a result the model cannot read is not a clean validation, and it is on every return path — refusals included — because that is what licenses labelling it trusted at all. The tool commits that sentence when it is attached, so maf-sandbox refuses a result departing from it rather than taking this package's word.

Upgrading to 0.9

0.9.0 requires maf-sandbox 0.19, which made the egress mode a thing a workload declares rather than a thing a backend is merely checked against.

bicep_sandbox_spec takes an egress argument, and it defaults to Egress.ALLOWLIST. That is the mode the kind has always wanted — the module hosts it fetches from are its reason for having an allowlist at all — but it is now asked for rather than implied, and the router refuses a backend that cannot enforce it:

SandboxEgressNotEnforced: sandbox backend 'docker' cannot enforce the 'allowlist'
egress the 'bicep' workload runs in (it enforces closed).

A deployment that worked before can hit that on upgrade with nothing else changed, because until 0.19 a closed backend serving an allowlist spec was permitted with a warning and simply failed at whatever it could not fetch.

Two ways out, and which is right depends on what you meant. If validation is supposed to reach the module registry, give the backend a mode that can enforce an allowlist — for maf-sandbox-docker that means configuring egress_proxy_image. If it is supposed to run offline, say so: bicep_sandbox_spec(egress=Egress.CLOSED) drops the host list with it, and restore failures then surface as diagnostics rather than as a refusal at attach.

Egress.UNRESTRICTED is accepted too, and is the honest choice for a backend that confines nothing — a no-isolation local backend, say — rather than letting it claim a confinement it does not perform.

Upgrading to 0.6

0.6.0 follows maf-sandbox 0.11, which retired the word workspace from the vocabulary. It requires that release; there is no version of this package that works against both.

make_bicep_tools takes file_store where it took workspace_store. It is the second positional parameter, so a call that passes it positionally needs no edit at all — only a keyword one does.

safe_workspace_path is safe_listed_path. Same signature, same behaviour; it validates a name against the caller's file store listing, which is what the new name says and the old one did not.

Provenance

Split out of maf-sandbox-acas (which keeps the ACAS backend and nothing else) so this workload's dependency set states its portability: maf-sandbox + agent-framework-core, nothing more. Extracted from a production agent application, where it runs against real infrastructure code an agent wrote — which is where every behaviour documented above was learned.


Maintained by SOKOLAI BV.

Release files for maf-sandbox-bicep 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for maf-sandbox-bicep 0.14.0
File Size Uploaded
maf_sandbox_bicep-0.14.0.tar.gz 23.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for maf-sandbox-bicep 0.14.0
File Interpreter ABI Platform
maf_sandbox_bicep-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 48.9 kB

Release files / maf_sandbox_bicep-0.14.0.tar.gz

Download URL maf_sandbox_bicep-0.14.0.tar.gz
Size 23.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9ec46a677e61671954cbaf0ebb47504d8c19b3c99d5d3911079924197be8698e
BLAKE2b-256 checksum
How to use checksums
11cbf69d84d9a4d8720bf681ac5c02478b96a39208f210a5e83fdacae638c4f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release files / maf_sandbox_bicep-0.14.0-py3-none-any.whl

Download URL maf_sandbox_bicep-0.14.0-py3-none-any.whl
Size 25.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f8fc836832aa82def47613dfa2451767676368b5efe7fdb0a373701f4c8f582e
BLAKE2b-256 checksum
How to use checksums
aea9e1355cadacd30bf95bebbfe2302d33466c5e296cc082e7a821b77e9f2044
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 6, 2026.

Transparency log

Release history Release notifications | RSS feed

0.21.1

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.16.1

2 release files

0.16.0

2 release files

0.15.1

2 release files

0.15.0

2 release files

This release

0.14.0 This release

2 release files

0.10.0

2 release files

0.9.8

2 release files

0.9.7

2 release files

0.9.6

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page