Microsoft.Agents.AI.LocalCodeAct
1.24.0-preview.261006.1
Prefix Reserved
dotnet add package Microsoft.Agents.AI.LocalCodeAct --version 1.24.0-preview.261006.1
NuGet\Install-Package Microsoft.Agents.AI.LocalCodeAct -Version 1.24.0-preview.261006.1
<PackageReference Include="Microsoft.Agents.AI.LocalCodeAct" Version="1.24.0-preview.261006.1" />
<PackageVersion Include="Microsoft.Agents.AI.LocalCodeAct" Version="1.24.0-preview.261006.1" />
<PackageReference Include="Microsoft.Agents.AI.LocalCodeAct" />
paket add Microsoft.Agents.AI.LocalCodeAct --version 1.24.0-preview.261006.1
#r "nuget: Microsoft.Agents.AI.LocalCodeAct, 1.24.0-preview.261006.1"
#:package Microsoft.Agents.AI.LocalCodeAct@1.24.0-preview.261006.1
#addin nuget:?package=Microsoft.Agents.AI.LocalCodeAct&version=1.24.0-preview.261006.1&prerelease
#tool nuget:?package=Microsoft.Agents.AI.LocalCodeAct&version=1.24.0-preview.261006.1&prerelease
Microsoft.Agents.AI.LocalCodeAct
Local CodeAct integration for Microsoft Agent Framework.
This package runs LLM-generated Python code in the local environment. It is NOT a Python security sandbox and is not safe for untrusted prompts or code on a developer workstation or production host without an external sandbox.
Microsoft.Agents.AI.LocalCodeAct is intended for environments that already
provide process, filesystem, network, and credential isolation (e.g., Azure
container instances, VMs, or Foundry hosted agents). It provides the familiar
CodeAct provider pattern used by the Hyperlight package while executing Python
locally in the agent environment.
Installation
dotnet add package Microsoft.Agents.AI.LocalCodeAct --prerelease
This is a preview package.
Basic Usage
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.LocalCodeAct;
var options = new LocalCodeActProviderOptions()
{
ExecutionLimits = new ProcessExecutionLimits { TimeoutSeconds = 5 },
};
using var provider = new LocalCodeActProvider("/usr/bin/python3", options);
// Register provider with your AIAgent's context providers.
What the Package Controls
- AST validation (default on): Validates generated code against allow-lists before execution.
- Subprocess execution: Runs generated code in a child Python process.
- Explicit Python path: the provider and standalone function constructors require a Python executable path (no default).
- Isolated environment: Does not inherit host environment variables unless explicitly provided.
- No shell invocation: Launches Python directly without a shell.
- Resource limits: Applies timeout, stdout, stderr, and result-size limits.
- Tool gating: Only provider-owned host tools can be invoked from generated
code via
await call_tool("<name>", ...). - File capture: Captures new files under configured read-write mounts while skipping symlinks. Modifications to pre-existing files are not captured.
These are defense-in-depth controls, not a containment boundary. The AST
validator blocks common dangerous operations (eval, exec,
import subprocess, attribute access for os.system, __class__, etc.) but
does not make Python execution safe on an unsandboxed host.
What the Package Does NOT Protect
- Malicious Python code working within allowed imports and operations.
- Network access unless the surrounding environment blocks it.
- Prompt-injected exfiltration through allowed host tools.
- Resource exhaustion outside the configured limits.
- Log, stdout, stderr, or result poisoning.
Use Azure container instances, VMs, Foundry hosted agents, or equivalent infrastructure as the actual security boundary.
Host Tools
Register host tools via the options or on the provider directly:
var addFunction = AIFunctionFactory.Create(
(int a, int b) => a + b,
name: "add",
description: "Adds two integers.");
using var provider = new LocalCodeActProvider("/usr/bin/python3", new LocalCodeActProviderOptions
{
Tools = new[] { addFunction },
});
// Or mutate after construction:
provider.AddTools(addFunction);
Inside execute_code:
total = await call_tool("add", a=2, b=3)
print(total)
Tool Approval
Generated code reaches registered tools through call_tool(...), which invokes
them directly. A per-tool approval interaction cannot be surfaced at that point,
so approval is bundled onto execute_code instead:
- If any registered tool is an
ApprovalRequiredAIFunction,execute_codeitself requires approval before the code runs. LocalCodeActApprovalMode.AlwaysRequiremakesexecute_coderequire approval regardless of the registered tools.
var deploy = new ApprovalRequiredAIFunction(
AIFunctionFactory.Create(RunDeployment, name: "deploy"));
using var provider = new LocalCodeActProvider("/usr/bin/python3", new LocalCodeActProviderOptions
{
Tools = new[] { deploy },
// ApprovalMode = LocalCodeActApprovalMode.AlwaysRequire, // optional, opt-in
});
For LocalCodeActProvider, approval is recomputed on every run, so tools added
via AddTools after construction are taken into account. LocalExecuteCodeFunction
captures its tools at construction time and exposes the approval requirement
through GetService<ApprovalRequiredAIFunction>().
Code Validation
By default, the package validates Python code against allow-lists before
execution. The validator runs in its own short-lived Python subprocess with a
dedicated timeout (ProcessExecutionLimits.ValidationTimeoutSeconds).
- Allowed imports:
math,random,json,datetime,pathlib,os, etc. OS access is limited to lexicalos.pathtransformations and read-only access to the scrubbedos.environmapping. - Blocked imports:
subprocess,sys,socket,importlib, network and threading modules, etc. - Allowed builtins:
print,len,str, type constructors, etc. - Blocked builtins:
__builtins__,__loader__,__spec__,eval,exec,compile,__import__,open,getattr,setattr, etc.
str.format and str.format_map method access is blocked because replacement
fields perform runtime attribute and item traversal that is invisible to AST
validation. Use f-strings or the format() builtin instead; f-string
expressions are validated as regular AST nodes.
Runtime annotation evaluation is restricted as well. Access to ForwardRef
evaluation methods (_evaluate, evaluate), annotation helpers (_eval_type,
evaluate_forward_ref, get_type_hints, get_annotations), and the
functools.singledispatch/singledispatchmethod factories is blocked.
These helpers can evaluate annotation strings outside the inspected AST,
including during annotation-inferred dispatch registration.
Ordinary typing constructs, ForwardRef construction, unevaluated annotation
declarations, and other functools utilities remain available. Generator
expressions, async-generator expressions, and async functions are also allowed,
but access to their gi_frame, ag_frame, and cr_frame attributes is
blocked.
Frame payload attributes (f_builtins, f_globals, and f_locals) are also
blocked regardless of how a frame is obtained. Generated code may inspect
non-payload task stack information, but it cannot recover the runner's builtin,
global, or local namespaces from those frames.
Capability restrictions apply at attribute access and from-import acquisition, before references can be aliased. Receiver types are not statically knowable, so unrelated attributes with the same names are also rejected. This includes harmless annotation resolution, non-evaluating modes of the blocked helpers, and otherwise-safe explicit-type singledispatch registration.
OS-derived aliases retain the same restrictions. Filesystem-querying path helpers, environment mutation, unknown descendants, and reflective access are rejected by default.
See Resources/validator.py for the full default
allow-lists.
Customizing Validation
Override the default lists:
using var provider = new LocalCodeActProvider("/usr/bin/python3", new LocalCodeActProviderOptions
{
AllowedImports = new[] { "math", "datetime", "mymodule" },
BlockedImports = new[] { "subprocess", "sys" },
AllowedBuiltins = new[] { "print", "len", "str", "int" },
BlockedBuiltins = new[] { "eval", "exec", "compile" },
});
Custom lists replace the defaults (not augment).
Fixed attribute and AST-node restrictions remain in effect independently of these lists. Allowing a module does not enable its blocked capability or runtime-traversal attributes.
Disabling Validation
Set ValidationDisabled = true to skip the AST validator entirely. Doing so
removes a critical defense-in-depth control. Only disable when the generated
code is trusted or when running inside a strong external sandbox.
File Mounts
Mount host directories to expose them to generated code:
using var provider = new LocalCodeActProvider("/usr/bin/python3", new LocalCodeActProviderOptions
{
FileMounts = new[]
{
new FileMount("/tmp/data", "/input", FileMountMode.ReadOnly),
new FileMount("/tmp/output", "/output", FileMountMode.ReadWrite),
},
});
Generated code accesses mounts via HostPath. MountPath is descriptive
metadata only — the subprocess sees the real host path. Read-write mounts are
scanned for new files after execution, and those files are returned as
DataContent. Symlinks are skipped.
Environment Variables
Pass environment variables explicitly. The subprocess does NOT inherit the host environment by default. On Windows, the system variables required for Python to load its standard library are retained:
using var provider = new LocalCodeActProvider("/usr/bin/python3", new LocalCodeActProviderOptions
{
Environment = new Dictionary<string, string>
{
["API_KEY"] = "...",
["LOG_LEVEL"] = "INFO",
},
});
Standalone Function
If you do not want the provider machinery you can expose execute_code directly:
var function = new LocalExecuteCodeFunction("/usr/bin/python3");
LocalExecuteCodeFunction snapshots tools and mounts at construction time and
is safe to reuse across invocations.
Execution Modes
The .NET implementation only supports subprocess execution. There is no "unsafe in-process" mode in .NET.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Agents.AI.Abstractions (>= 1.24.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.10.1)
-
net8.0
- Microsoft.Agents.AI.Abstractions (>= 1.24.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.10.1)
- System.Text.Json (>= 10.0.12)
-
net9.0
- Microsoft.Agents.AI.Abstractions (>= 1.24.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.10.1)
- System.Text.Json (>= 10.0.12)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Microsoft.Agents.AI.LocalCodeAct:
| Package | Downloads |
|---|---|
|
ProCode.Engine.Logic
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.24.0-preview.261006.1 | 189 | 10/7/2026 |
| 1.23.0-preview.260928.1 | 623 | 9/29/2026 |
| 1.22.0-preview.260918.1 | 3,673 | 9/18/2026 |
| 1.21.0-preview.260911.1 | 308 | 9/11/2026 |
| 1.20.0-preview.260831.1 | 6,493 | 8/31/2026 |
| 1.19.0-preview.260822.1 | 861 | 8/22/2026 |
| 1.18.0-preview.260818.1 | 411 | 8/18/2026 |
| 1.17.0-preview.260804.1 | 10,019 | 8/4/2026 |
| 1.16.0-preview.260730.1 | 397 | 7/30/2026 |