{"id":5293,"date":"2026-04-23T07:24:23","date_gmt":"2026-04-23T14:24:23","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/agent-framework\/?p=5293"},"modified":"2026-04-23T07:24:23","modified_gmt":"2026-04-23T14:24:23","slug":"codeact-with-hyperlight","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/agent-framework\/codeact-with-hyperlight\/","title":{"rendered":"CodeAct in Agent Framework: Faster Agents with Fewer Model Turns"},"content":{"rendered":"<p>Modern AI agents often aren&#8217;t bottlenecked by model quality, they are bottlenecked by orchestration overhead. When an agent chains together many small tool calls, each step typically requires a new model turn, driving up latency and token usage.<\/p>\n<p>With CodeAct support in Agent Framework, agents can collapse those multi-step plans into a single executable code block, cutting end-to-end latency by ~50% and token usage by over 60% in representative workloads, without compromising on safety or isolation. CodeAct ships in the new <code>agent-framework-hyperlight<\/code> (alpha) package, which runs the model-generated code in a fresh, locally isolated <a href=\"https:\/\/github.com\/hyperlight-dev\/hyperlight\">Hyperlight<\/a> micro-VM per call.<\/p>\n<p>In this post, we walk through a concrete, realistic scenario where CodeAct provides meaningful gains: an agent task that involves many small, chainable tool calls (fetching data, performing light computation, assembling a result). Traditionally, this forces the agent into a loop of model \u2192 tool \u2192 model \u2192 tool interactions. Using CodeAct, the agent instead expresses the full plan as a short Python program that runs once in a sandboxed environment. The tools remain the same, the model remains the same, only the wiring changes. Later, we quantitatively compare both approaches on the same task to show where the latency and token savings come from, and more importantly, when those savings are worth pursuing in your own agents.<\/p>\n<p>Concretely, wiring CodeAct into an agent looks like this. All later snippets build on it, reusing the same imports and the <code>get_weather<\/code> tool defined here:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">from agent_framework import Agent, tool\r\nfrom agent_framework_hyperlight import HyperlightCodeActProvider\r\n\r\n@tool\r\ndef get_weather(city: str) -&gt; dict[str, float | str]:\r\n    \"\"\"Return the current weather for a city.\"\"\"\r\n    return {\"city\": city, \"temperature_c\": 21.5, \"conditions\": \"partly cloudy\"}\r\n\r\n\r\ncodeact = HyperlightCodeActProvider(\r\n    tools=[get_weather],\r\n    approval_mode=\"never_require\",\r\n)\r\n\r\nagent = Agent(\r\n    client=client,\r\n    name=\"CodeActAgent\",\r\n    instructions=\"You are a helpful assistant.\",\r\n    context_providers=[codeact],\r\n)\r\n\r\nresult = await agent.run(\r\n    \"Get the weather for Seattle and Amsterdam and compare them.\"\r\n)\r\n<\/code><\/pre>\n<h2 class=\"wp-block-heading\">Why CodeAct<\/h2>\n<p>Modern agents are increasingly limited not by model quality, but by how much tool-calling overhead they incur. An agent that needs to read a table, filter it, multiply a few values, and summarize the result will typically burn four or five tool-call round trips, one per step, each one a separate request to the model.<\/p>\n<p>The <a href=\"https:\/\/arxiv.org\/abs\/2402.01030\">CodeAct pattern<\/a> collapses that loop. Instead of asking the model to choose a tool, wait for the result, and choose the next tool, we give the model a single <code>execute_code<\/code> tool and let it express the entire plan as a short Python program. Tools the agent would otherwise call directly are exposed inside the program as <code>call_tool(...)<\/code>. The model writes the code once, the sandbox runs it, and the agent gets back a single consolidated result.<\/p>\n<p>Agents that do a lot of tool calling (data wrangling, light computation, chained lookups, report generation) benefit most. A five-step plan that used to be five model turns becomes one <code>execute_code<\/code> turn containing a short Python script that calls the same tools via <code>call_tool(...)<\/code>. You save latency, you save tokens, and you keep the reasoning trace compact and auditable, because the full plan lives in a single code block instead of being scattered across several tool-call messages.<\/p>\n<h2 class=\"wp-block-heading\">How CodeAct works in Agent Framework<\/h2>\n<p>The <code>agent-framework-hyperlight<\/code> package ships two entry points (<code>HyperlightCodeActProvider<\/code> and <code>HyperlightExecuteCodeTool<\/code>) plus typed helpers for file mounts and network policy. The sections below walk through both wirings, explain how approvals interact with sandboxed code, and show how to grant the sandbox controlled access to the host filesystem and network.<\/p>\n<h3 class=\"wp-block-heading\">The provider, and the minimal setup<\/h3>\n<p>The recommended entry point is <code>HyperlightCodeActProvider<\/code>, a <code>ContextProvider<\/code> that:<\/p>\n<ul class=\"wp-block-list\">\n<li>Registers an <code>execute_code<\/code> tool on every agent run.<\/li>\n<li>Injects CodeAct instructions into the system prompt, describing the sandbox, the available helpers, and the tools reachable via <code>call_tool(...)<\/code>.<\/li>\n<\/ul>\n<p>The minimal setup shown at the top of the post is the recommended shape: construct the provider with your tools, pass it to the agent via <code>context_providers=[...]<\/code>, and let it handle <code>execute_code<\/code> registration and prompt injection for you.<\/p>\n<h3 class=\"wp-block-heading\">How a tool gets invoked<\/h3>\n<p>Hyperlight does provide isolation, but it isolates the <em>model-generated<\/em> code, not your tools. The tools you write and register live in your application&#8217;s runtime, with whatever access your process has. The Python program the model writes inside <code>execute_code<\/code> runs inside the Hyperlight sandbox, with no host access except the file mounts and allowed domains you opted into. When that sandboxed program calls <code>call_tool(\"name\", ...)<\/code>, Hyperlight bridges the call back out to your runtime, runs your tool there, and returns the result into the sandbox. <code>call_tool(...)<\/code> is that bridge; it is not an in-sandbox reimplementation of your tool.<\/p>\n<p>That split is the point. Your tools stay deterministic, fully managed code that you reviewed and shipped, and they keep the access they need to do their job (files, network, credentials, internal APIs). The model-generated glue that decides which tools to call, in what order, and how to combine the results stays in the sandbox, where it cannot touch anything except what you explicitly allowed. If you do want the model itself to read a file or hit an HTTP endpoint directly from inside <code>execute_code<\/code>, you can grant that with <code>file_mounts<\/code> and <code>allowed_domains<\/code> on the provider, and only those resources become reachable from sandboxed code.<\/p>\n<h3 class=\"wp-block-heading\">Approvals<\/h3>\n<p>Agent Framework tools carry an <code>approval_mode<\/code> that controls whether a call is auto-invoked or paused for a human-in-the-loop decision. The two modes are <code>never_require<\/code> (the framework invokes the tool automatically) and <code>always_require<\/code> (every call raises a function-approval request the agent host has to resolve before the tool runs). This is the primary knob for deciding how much autonomy a given tool gets.<\/p>\n<p>With that in mind, the two registration sites differ like this:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Tools passed to <code>HyperlightCodeActProvider(tools=...)<\/code><\/strong> are not shown to the model as direct tools. The model only sees the single <code>execute_code<\/code> tool, and it reaches your tools by writing a line of Python that calls <code>call_tool(\"name\", ...)<\/code>. Approval, if any, applies to the <code>execute_code<\/code> call as a whole, not to individual <code>call_tool(...)<\/code> invocations within it. Right now, if the <code>execute_code<\/code> tool or any of the tools passed to the provider require approval (regardless of whether they are invoked) the entire code block is gated behind a single approval prompt.<\/li>\n<li><strong>Tools passed to <code>Agent(tools=...)<\/code><\/strong> are surfaced to the model as first-class tools. Each call is a separate tool message the model chooses explicitly, and each one honors its own <code>approval_mode<\/code>.<\/li>\n<li><strong>Tools passed to <code>HyperlightCodeActProvider(tools=...)<\/code> and <code>Agent(tools=...)<\/code><\/strong> are surfaced to the model as first-class tools as well as being available inside the sandbox. The model can choose to call them directly as a first-class tool call, or indirectly via <code>call_tool(...)<\/code> inside the sandbox. Approval applies according to how the model calls them: if called directly, the tool&#8217;s own <code>approval_mode<\/code> applies; if called via <code>call_tool(...)<\/code>, the <code>execute_code<\/code> tool&#8217;s approval mode applies. This means that the same tool can have different approval modes depending on how the model chooses to invoke it. For instance, if another tool passed to the provider has <code>approval_mode=\"always_require\"<\/code>, the model can choose to call it via <code>call_tool(...)<\/code> inside the sandbox, in which case it will be gated by the provider&#8217;s approval mode, or it can call it directly as a first-class tool, in which case it might not be need approval. This also allows the model to decide per-step what the easiest way of calling that tool is, if it just needs the raw result of that tool and only that tool, then it can call it directly, if it needs to manipulate the result or combine it with others, then it can call it via <code>call_tool(...)<\/code> inside the sandbox and do all the processing in one turn. <code>approval_mode<\/code>.<\/li>\n<\/ul>\n<p>This gives you a clean rule of thumb. If a tool is cheap, pure, and safe to chain (data lookups, computations, formatting helpers, read-only API calls), register it on the provider so the model can compose many calls into a single <code>execute_code<\/code> turn. If a tool has side effects you want the user to gate individually (sending email, spending money, writing to production systems), keep it on the agent directly, typically with <code>approval_mode=\"always_require\"<\/code>, so the model has to request each invocation as a first-class tool call. The same tool can also be passed to both; the model will then decide per-step whether to call it via <code>call_tool(...)<\/code> inside <code>execute_code<\/code> or as a first-class tool call.<\/p>\n<p>Building on the setup above, adding <code>send_email<\/code> as a direct, approval-gated tool alongside the sandboxed <code>get_weather<\/code> looks like this; everything else stays the same:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\"># ... same imports, tools, and provider as above ...\r\n\r\n@tool(approval_mode=\"always_require\")\r\ndef send_email(to: str, subject: str, body: str) -&gt; str:\r\n    \"\"\"Send an email. Requires approval on every call.\"\"\"\r\n    ...\r\n\r\nagent = Agent(\r\n    client=client,\r\n    name=\"MixedToolsAgent\",\r\n    instructions=\"You are a helpful assistant.\",\r\n    context_providers=[codeact],\r\n    tools=[send_email],           # invoked directly by the model, approval-gated\r\n)\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<h3 class=\"wp-block-heading\">The standalone <code>HyperlightExecuteCodeTool<\/code><\/h3>\n<p><code>HyperlightExecuteCodeTool<\/code> exposes the same sandbox plumbing as a standalone <code>tool<\/code> you add to <code>Agent(tools=...)<\/code> yourself, instead of letting the provider wire it in. Use it when you want full control over how <code>execute_code<\/code> is presented, for example to label it, wrap it in middleware, or build the CodeAct instructions once and embed them in a static agent definition.<\/p>\n<p>The tool takes the same <code>tools=...<\/code> list as the provider, and those tools are still reached from sandboxed code via <code>call_tool(...)<\/code>. The key difference from the provider is that the provider injects CodeAct instructions into the system prompt for you on every run; with the standalone tool, you are responsible for putting those instructions in the agent&#8217;s <code>instructions<\/code> yourself. Otherwise the model will see the <code>execute_code<\/code> tool as a regular tool that can run python code, but without guidance on how to use it or which tools are available inside the sandbox. <code>HyperlightExecuteCodeTool<\/code> exposes <code>build_instructions(...)<\/code> as a helper that produces exactly that prompt fragment, derived from the tools and sandbox configuration you passed in:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\">from agent_framework_hyperlight import HyperlightExecuteCodeTool\r\n\r\nexecute_code = HyperlightExecuteCodeTool(\r\n    tools=[get_weather],\r\n    approval_mode=\"never_require\",\r\n)\r\n\r\nagent = Agent(\r\n    client=client,\r\n    name=\"StandaloneToolAgent\",\r\n    instructions=(\r\n        \"You are a helpful assistant.\\n\\n\"\r\n        + execute_code.build_instructions()\r\n    ),\r\n    tools=[execute_code, send_email],\r\n)\r\n<\/code><\/pre>\n<p>Because <code>build_instructions()<\/code> runs once at construction time, this path skips the per-run provider lifecycle entirely, useful for fully static agent definitions where the tool set and sandbox configuration do not change between runs.<\/p>\n<h3 class=\"wp-block-heading\">Controlled filesystem and network access<\/h3>\n<p>By default the sandbox has no access to the host. When a workload needs more, you opt in explicitly on the provider (or on the standalone tool), leaving the rest of the setup unchanged:<\/p>\n<pre class=\"prettyprint language-py\"><code class=\"language-py\"># ... same imports and tools as above ...\r\n\r\ncodeact = HyperlightCodeActProvider(\r\n    tools=[get_weather],\r\n    approval_mode=\"never_require\",\r\n    file_mounts=[\r\n        \"\/host\/data\",                                  # same path inside the sandbox\r\n        (\"\/host\/models\", \"\/sandbox\/models\"),           # host \u2192 sandbox mapping\r\n    ],\r\n    allowed_domains=[\r\n        \"api.github.com\",                              # all methods\r\n        (\"internal.api.example.com\", \"GET\"),           # GET only\r\n    ],\r\n)\r\n<\/code><\/pre>\n<p>Mounted paths show up in the generated CodeAct instructions so the model knows where to read from and where to write artifacts. Allowed domains are enforced at the sandbox boundary, not by convention.<\/p>\n<p><div class=\"alert alert-info\">Because tools always run on the host, they are not constrained by the sandbox&#8217;s <em>file_mounts<\/em> or <em>allowed_domains<\/em>. If the model needs to read a file outside the mounted paths, or hit an API outside the allow-list, the recommended approach is usually not to open a hole in the sandbox. Instead, expose a narrow host tool that does exactly the operation you want, and let the model call that tool (directly or via call_tool(&#8230;)). The sandbox then stays locked down, and the sensitive I\/O lives in code you reviewed and shipped.<\/div><\/p>\n<h2 class=\"wp-block-heading\">Hyperlight: the sandbox under the hood<\/h2>\n<p>Hyperlight is a micro-VM runtime designed for very small, very fast, strongly isolated guests. Each <code>execute_code<\/code> call runs in a fresh guest with its own memory, no access to the host filesystem beyond what you explicitly mount, and no network access beyond the domains you allow. Guest startup is measured in milliseconds, so the isolation is essentially free at the granularity of a single tool call.<\/p>\n<p>The result is a local, protected, deterministic place to run the code your model writes: no container daemon, no remote code-interpreter service, no shared Python process with the host agent.<\/p>\n<h3 class=\"wp-block-heading\">Why Hyperlight<\/h3>\n<p>The trade-off CodeAct has historically had to make is safety. Running model-generated code against a host process, or even against a general-purpose container, is a real risk: long-lived shared state, broad filesystem and network reach, and a startup cost high enough that you would not spin up a fresh sandbox per call. Hyperlight removes that trade-off. Because every <code>execute_code<\/code> call gets its own freshly created micro-VM, with only the mounts and domains you opted into, the sandbox is cheap enough to be disposable and strict enough to be the default. You keep the latency and token wins of CodeAct, and you do not pay for them in blast radius.<\/p>\n<h2 class=\"wp-block-heading\">Benchmark: same task, same tools, different wiring<\/h2>\n<p>The repository contains a <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/blob\/main\/python\/packages\/hyperlight\/samples\/codeact_benchmark.py\"><code>codeact_benchmark.py<\/code> sample<\/a> that compares the two wirings on a workload that is realistic for this style of agent: compute the grand total of every user&#8217;s orders, where the model has to look up users, look up each user&#8217;s orders, look up discount and tax rates, and call a single line-total computation tool for each order line. The dataset has eight users and a handful of orders each, so finishing the task takes dozens of tool calls.<\/p>\n<p>Both runs use the same <code>FoundryChatClient<\/code>, the same model, the same five tools (<code>list_users<\/code>, <code>get_orders_for_user<\/code>, <code>get_discount_rate<\/code>, <code>get_tax_rate<\/code>, <code>compute_line_total<\/code>), the same prompt, and the same structured output schema. The only difference is whether those tools are passed to <code>Agent(tools=...)<\/code> directly or registered on a <code>HyperlightCodeActProvider<\/code> behind a single <code>execute_code<\/code> tool. On a recent run the sample reports:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Wiring<\/th>\n<th>Time<\/th>\n<th>Tokens<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Traditional<\/td>\n<td>27.81s<\/td>\n<td>6,890<\/td>\n<\/tr>\n<tr>\n<td>CodeAct<\/td>\n<td>13.23s<\/td>\n<td>2,489<\/td>\n<\/tr>\n<tr>\n<td>Improvement<\/td>\n<td>52.4%<\/td>\n<td>63.9%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2 class=\"wp-block-heading\">When to use CodeAct, and when not to<\/h2>\n<p>The benchmark above is one data point. CodeAct is not a free win for every agent. A rough guide:<\/p>\n<h3 class=\"wp-block-heading\">Reach for CodeAct when<\/h3>\n<ul class=\"wp-block-list\">\n<li>The task naturally decomposes into many small, chainable tool calls (lookups, joins, light computation, formatting).<\/li>\n<li>The tools are cheap, deterministic, and safe to invoke in sequence without per-call human gating.<\/li>\n<li>You care about latency, token cost, or trace compactness, and individual tool calls do not need their own approval prompts.<\/li>\n<li>You are running model-generated code and want strong, per-call isolation by default.<\/li>\n<\/ul>\n<h3 class=\"wp-block-heading\">Stay with traditional tool-calling when<\/h3>\n<ul class=\"wp-block-list\">\n<li>The agent already does only one or two tool calls per turn; there is little overhead to collapse.<\/li>\n<li>Each tool call has side effects you want the user to approve individually (sending email, spending money, writing to production systems). These belong on the agent directly with <code>approval_mode=\"always_require\"<\/code>.<\/li>\n<li>Tool descriptions are sparse or ambiguous. Because the model writes Python that calls your tools by name, docstrings, parameter annotations, and return-type hints become part of the contract the model is reasoning about. Weak descriptions hurt CodeAct more than they hurt direct tool-calling, because models by now are heavily optimized and tweaked for accurate tool calling.<\/li>\n<\/ul>\n<p>If you are unsure, continuously run a benchmark dataset against your own tool set and prompt before committing.<\/p>\n<h2 class=\"wp-block-heading\">Getting started<\/h2>\n<p>To try it out, run:<\/p>\n<pre class=\"prettyprint language-bash\"><code class=\"language-bash\">pip install agent-framework-hyperlight --pre\r\n\r\n# or:\r\n\r\nuv add --prerelease=allow agent-framework-hyperlight<\/code><\/pre>\n<p>The hyperlight package depends on <code>agent-framework-core<\/code> but does not install any connectors, like <code>Foundry<\/code> or <code>OpenAI<\/code>.<\/p>\n<p>Samples are available under <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/python\/packages\/hyperlight\/samples\"><code>python\/packages\/hyperlight\/samples\/<\/code><\/a>. There are multiple samples which walk through the three integration styles described above.<\/p>\n<p>The package is currently alpha, and it depends on the platform-specific Hyperlight backend being available; <code>execute_code<\/code> will report a clear error at runtime on unsupported platforms.<\/p>\n<h2 class=\"wp-block-heading\">Current limitations and what we want feedback on<\/h2>\n<p>This is the first shape of the integration, and we are deliberately releasing it as alpha so we can iterate based on what you hit in practice. A few things to be aware of:<\/p>\n<ol class=\"wp-block-list\">\n<li><strong>Platforms.<\/strong> The backend is available for Linux and Windows today. macOS support is on the way.<\/li>\n<li><strong>Languages.<\/strong> The integration currently targets Python. A .NET counterpart for Agent Framework is coming.<\/li>\n<li><strong>Guest runtime.<\/strong> The sandbox runs a Python guest. Hyperlight itself can host other guests &#8211; JavaScript, for instance, and we are open to adding them, but each additional guest means a different set of CodeAct instructions, a different <code>call_tool<\/code> surface, and different ergonomics. We would like to hear whether a non-Python guest is something you would reach for before we build it.<\/li>\n<li><strong>Approvals.<\/strong> The approval mechanism today is intentionally simple: approvals apply to the <code>execute_code<\/code> call as a whole, not to individual <code>call_tool(...)<\/code> invocations within a single code block. That keeps the model&#8217;s reasoning intact inside one turn, but it also means that if you want per-operation gating you currently have to keep those operations as direct agent tools. There is room to grow here: per-tool prompts inside <code>execute_code<\/code>, post-hoc audit hooks, policy-driven approval. We would like to hear which of those shapes would actually help you.<\/li>\n<\/ol>\n<p>If you run into a bug or have a feature request, please open an issue on <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/issues\">the repository<\/a>.<\/p>\n<p>For broader feedback on the limitations above, especially on approval ergonomics and non-Python guests, please join <a href=\"https:\/\/github.com\/microsoft\/agent-framework\/discussions\/5328\">the discussion here<\/a>.<\/p>\n<h2 class=\"wp-block-heading\">Thanks<\/h2>\n<p>A big thank you to the Hyperlight team for the collaboration that made this integration possible. Their work on fast, minimal, strongly isolated guests is what lets us treat a secure sandbox as a normal part of an agent&#8217;s inner loop instead of a heavyweight piece of infrastructure. We are looking forward to building more on top of it.<\/p>\n<h2 class=\"wp-block-heading\">Useful links<\/h2>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\">Microsoft Agent Framework repository<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/python\/packages\/hyperlight\"><code>agent-framework-hyperlight<\/code> package<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/tree\/main\/python\/packages\/hyperlight\/samples\">Hyperlight CodeAct samples<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/blob\/main\/python\/packages\/hyperlight\/samples\/codeact_benchmark.py\">CodeAct vs. traditional tool-calling benchmark<\/a><\/li>\n<li><a href=\"https:\/\/pypi.org\/project\/agent-framework-hyperlight\/\"><code>agent-framework-hyperlight<\/code> on PyPI<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/hyperlight-dev\/hyperlight\">Hyperlight project<\/a><\/li>\n<li><a href=\"https:\/\/arxiv.org\/abs\/2402.01030\">CodeAct paper (Wang et al., 2024)<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/issues\">Report a bug or request a feature<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/microsoft\/agent-framework\/discussions\/5328\">Alpha feedback discussion<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Modern AI agents often aren&#8217;t bottlenecked by model quality, they are bottlenecked by orchestration overhead. When an agent chains together many small tool calls, each step typically requires a new model turn, driving up latency and token usage. With CodeAct support in Agent Framework, agents can collapse those multi-step plans into a single executable code [&hellip;]<\/p>\n","protected":false},"author":150044,"featured_media":5298,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143,27,34,16],"tags":[153,152],"class_list":["post-5293","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-agent-framework","category-agents","category-python-2","category-tools","tag-codeact","tag-hyperlight"],"acf":[],"blog_post_summary":"<p>Modern AI agents often aren&#8217;t bottlenecked by model quality, they are bottlenecked by orchestration overhead. When an agent chains together many small tool calls, each step typically requires a new model turn, driving up latency and token usage. With CodeAct support in Agent Framework, agents can collapse those multi-step plans into a single executable code [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/5293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/users\/150044"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/comments?post=5293"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/5293\/revisions"}],"predecessor-version":[{"id":5343,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/5293\/revisions\/5343"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media\/5298"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media?parent=5293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/categories?post=5293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/tags?post=5293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}