# 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: ```bash no-run pip install semantic-kernel withruntime ``` ```python check from semantic_kernel.agents import ChatCompletionAgent from semantic_kernel.functions import KernelPlugin, kernel_function from withruntime import AsyncRuntime from withruntime.tools import sandbox_tools async 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: ```python check from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior behavior = 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: ```python check from semantic_kernel.agents import ChatCompletionAgent async 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](/docs/security#secrets-sandboxes-never-see) 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](/docs/pricing)). See also [a code interpreter for chatbots](/use-cases/code-interpreter-for-chatbots), [code interpreter](/glossary/code-interpreter) and the [framework guide](/docs/frameworks#any-other-framework). New accounts get 50 free sandbox hours, no card: ```bash no-run npx withruntime sandbox run --trial -- python3 -c 'print(6 * 7)' ``` ## Related - [LLM tool use in a sandbox](/use-cases/llm-tool-use-sandbox) - [AutoGen in a sandbox](/integrations/autogen) - [What is an agent loop?](/glossary/agent-loop) ## Sources - [Microsoft Learn: Use code interpreter sessions in Semantic Kernel with Azure Container Apps](https://learn.microsoft.com/en-us/azure/container-apps/sessions-tutorial-semantic-kernel), updated 14 April 2026, read 25 September 2026 - [Microsoft Learn: Provide native code to your agents](https://learn.microsoft.com/en-us/semantic-kernel/concepts/plugins/adding-native-plugins), read 25 September 2026 - [Microsoft Learn: The ChatCompletionAgent](https://learn.microsoft.com/en-us/semantic-kernel/frameworks/agent/agent-types/chat-completion-agent), read 25 September 2026 - [semantic-kernel on PyPI](https://pypi.org/project/semantic-kernel/), version 1.44.1; `KernelPlugin` and the default function choice behavior were read from that release's source on 25 September 2026 Facts on this page were checked on 25 September 2026.