Runtime

Semantic Kernel code interpreter without Azure: a sandbox plugin

Wrap Runtime's sandbox functions with kernel_function into a KernelPlugin, and a Semantic Kernel agent runs code in a microVM.

On Runtime a Semantic Kernel agent gets a code sandbox without an Azure subscription. Semantic Kernel's built-in SessionsPythonTool runs Python in Azure Container Apps dynamic sessions, which means a session pool, its management endpoint and role assignments before the first cell runs. A Runtime sandbox needs a pip install and one browser approval, and gives the agent a whole Firecracker microVM with a shell, not only Python cells. It starts in 351 ms at the median (24 September 2026) and costs $0.03125 an hour for 2 vCPU and 4 GiB while the model is thinking. semantic-kernel 1.44.1 was the current PyPI release on 25 September 2026.

Built-in plugin or Runtime plugin

Question SessionsPythonTool Runtime plugin
Where code runs An Azure Container Apps dynamic session A Runtime Firecracker microVM
Setup before first run Resource group, session pool, pool endpoint, Session Executor role pip install withruntime and a browser approval
What the agent can do Run Python code Run any shell command, read, write, list files
Credentials in your app Azure identity (DefaultAzureCredential in Microsoft's tutorial) A Runtime key, or the machine's saved connection
State The same session across calls from one tool instance The same sandbox for the life of your block

The Azure column follows Microsoft's own tutorial for the Python SDK, updated 14 April 2026, which also advises a separate kernel and tool per end user so each user gets their own session.

Build the plugin

In Python, kernel_function marks a function for the kernel and reads its signature. Applied to the four Runtime functions, it produces a plugin whose functions the agent can call:

Terminalpip install semantic-kernel withruntime
Pythonfrom semantic_kernel.agents import ChatCompletionAgentfrom semantic_kernel.functions import KernelPlugin, kernel_functionfrom withruntime import AsyncRuntimefrom withruntime.tools import sandbox_toolsasync def solve(service, task: str) -> str:    async with AsyncRuntime() as runtime:        async with await runtime.sandboxes.create(timeout_seconds=900, on_lease_end="stop") as sbx:            plugin = KernelPlugin(name="runtime", functions=[kernel_function(f) for f in sandbox_tools(sbx)])            agent = ChatCompletionAgent(                service=service,                name="engineer",                instructions="Use the runtime plugin to run code in a Linux sandbox. Check exit codes.",                plugins=[plugin],            )            response = await agent.get_response(messages=task)            return str(response.content)

service is any chat completion service, for example OpenAIChatCompletion(ai_model_id=...) or AzureChatCompletion(). Because the sandbox is an AsyncSandbox, the four functions are coroutines and never block the event loop. The model sees them as runtime-runtime_exec, runtime-runtime_read_file and so on, the plugin name joined to the function name.

This agent ran on 25 September 2026 against semantic-kernel 1.44.1 with a scripted OpenAI-style endpoint: the agent called runtime_exec, got the exit code and output, and answered from them.

How many tool calls the agent may make

A ChatCompletionAgent built this way uses automatic function calling. In 1.44.1 its default allows five automatic invocation rounds per response. For a longer task, such as install, run, fix and rerun, pass your own behavior:

Pythonfrom semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehaviorbehavior = FunctionChoiceBehavior.Auto(maximum_auto_invoke_attempts=15)# ChatCompletionAgent(..., function_choice_behavior=behavior)

Continue a conversation in the same sandbox

get_response returns a thread. Pass it back and the agent remembers the conversation, while the sandbox remembers the files and installed packages:

Pythonfrom semantic_kernel.agents import ChatCompletionAgentasync def two_turns(agent: ChatCompletionAgent) -> str:    first = await agent.get_response(messages="Write primes.py that prints primes under 100, then run it.")    second = await agent.get_response(messages="Now make it take the limit as an argument.", thread=first.thread)    return str(second.content)

Both turns work on /workspace/primes.py in one machine.

Security settings that hold even if the model is tricked

Semantic Kernel filters can inspect a function call before it runs, which is a good place for policy. The sandbox adds limits no prompt can talk its way past, because the host enforces them outside the microVM:

  • network={"internet": False} on the create for pure computation, or an allow list of hosts for package installs.
  • timeout_seconds and on_lease_end="stop", so an abandoned conversation does not keep a machine running.
  • max_cost_micros, which refuses the create if its first lease would cost more than you set.
  • A daily spending limit on the application's key. Past it, creates fail with spending_limit_reached and nothing is charged.
  • Runtime secrets for any token the code needs: the sandbox sees a placeholder, and the real value is added on requests to the named hosts only.

Which to use

Choose SessionsPythonTool when the application already runs on Azure, uses Azure identity throughout, and Python cells are enough. Choose the Runtime plugin when the agent must work outside Azure, needs a shell, pip, apt or Docker (sudo enable-docker), or the team wants a price billed on CPU used: $0.025 per vCPU-hour and $0.0075 per GiB-hour, with no plan fee (pricing).

See also a code interpreter for chatbots, code interpreter and the framework guide. New accounts get 50 free sandbox hours, no card:

Terminalnpx withruntime sandbox run --trial -- python3 -c 'print(6 * 7)'

Sources

Facts on this page were checked on 25 September 2026.