DEV Community

Cover image for Mistral's New Agents SDK Runs Tool Calls Without Asking by Default. Set a Policy First
Gabriel Anhaia
Gabriel Anhaia

Posted on Edited on AI-assisted

Mistral's New Agents SDK Runs Tool Calls Without Asking by Default. Set a Policy First


You give your new agent two tools: one that reads an alert, one that opens an incident case. You never wrote an approval rule, so you assume it will ask before it opens anything. With Mistral's new Agents SDK, it won't. The default permission_mode is "auto", which Mistral's approvals docs define as: "follows the permission_policy, or runs when the Agent has none."

That SDK is the center of the Studio release Mistral shipped on November 5: twelve release-note entries, almost all of them public previews.

What shipped on November 5

The headline item in the release notes is Managed Agents: build an agent in Python with the Agents SDK, then run the same code on your own machines or on Mistral's infrastructure. The same day brought a workflow builder, an Apps CLI, an evaluation SDK, managed datasets, a managed search index, tracing for managed agents, webhooks and online evaluations.

Mistral's announcement leads with Mistral Large 4, nicknamed "Le Chonk," and lists skills, sandboxes, subagents and hooks as the building blocks of an agent. AlphaSignal's write-up adds the availability split: Managed Agents and Apps are in public preview on Mistral Cloud, and Workflows itself is generally available (the new builder is in preview). AlphaSignal also reports private-cloud and on-premises options at the end of November; Mistral's own pages don't give a date.

The Agents overview is blunt about the stage: "Managed Agents and the Agents SDK are in public preview," and the API, behavior and limits may change in ways that need code changes. Pin the version.

One agent, three places to run it

The SDK ships as mistralai-agents. The quickstart needs Python 3.12, 3.13 or 3.14, the standard build and not free-threaded 3.14t, and pins the version in its own example:

uv init --python 3.12 my_agent && cd my_agent
uv add "mistralai-agents==1.1.0"
export MISTRAL_API_KEY="<your-key>"
Enter fullscreen mode Exit fullscreen mode

The smallest agent in the overview is five lines:

import asyncio

from mistralai import agents

agent = agents.Agent(model="mistral-large-4")
result = asyncio.run(agent.run("Say hello"))
print(result.text)
Enter fullscreen mode Exit fullscreen mode

From there, per the overview, the same code runs three ways. In-process, the harness, tools and session live in your program and end with it. With agents serve, the harness and your tools run on your servers and Mistral stores the session. With agents deploy, everything runs on Mistral and you "host nothing."

Editorial illustration of one black agent silhouette stepping through three doorways side by side: a laptop, a server rack and an orange cloud
One agent definition, three runtimes: your process, your servers, or Mistral's.

Two deploy details are easy to miss. The deploy guide says agents deploy "builds the commit you pushed, not your working copy," and it refuses unpushed commits and branches without an upstream. And check your plan. Mistral's managed-deployment quotas, documented in the Workflows section, allow 0 concurrent deployments on Free and on Pro or Team without pay-as-you-go, 3 with pay-as-you-go, and 10 on Enterprise. Past the cap, creating or starting a deployment fails with a 403. Managed deployments cover agents, workflows and apps, so expect the same caps on agents deploy.

The default: your tools just run

An agent with no permission_policy and the default permission_mode="auto" runs every tool call it decides to make. The other two modes are "ask" and "deny" (approvals docs).

For anything that writes, add a policy. This one is Mistral's own example from the approvals page, rewrapped to fit, with the variable renamed to policy:

policy = agents.PermissionPolicy(
    default="deny",
    rules=[
        agents.PermissionRule(
            tools=["client.get_alert"], decision="allow"
        ),
        # opening a case asks
        agents.PermissionRule(
            tools=["client.open_case"], decision="ask"
        ),
    ],
)
Enter fullscreen mode Exit fullscreen mode

Building the policy changes nothing until the agent gets it:

agent = agents.Agent(
    model="mistral-large-4",
    permission_policy=policy,
)
Enter fullscreen mode Exit fullscreen mode

Three rules from the same page decide whether it does what you think. The first matching rule wins. A call that matches no rule gets the policy's default, so default="deny" is what turns this into an allowlist. And patterns match the tool ID, such as client.open_case, not the name the model sees. Check the IDs your agent actually reports before you trust a rule. A policy also needs permission_mode="auto"; the Agent raises an error with any other mode.

Editorial illustration of tool-call envelopes flowing through an open orange gate, with a second black gate beside it that holds most envelopes back and lets one through
With no policy, every call goes through. A deny-by-default policy lets through only what you listed.

Approval requests can be answered in code. An on_approval= callback returns AllowApproval(), DenyApproval() or KeepCallbackOpen(), and the last one leaves the call to a person. Mistral's own example auto-approves calls whose tool carries a read_only_hint annotation and hands everything else to a human (approvals docs).

The defaults Mistral did get right

Give the SDK its due. Several defaults fail closed.

An agent has no environment unless you give it one. The default is NoSandbox, which the environment docs describe as "no code execution." When you add one, the page recommends MistralSandbox, a Mistral-managed container. The option with no isolation at all, DangerousLocalSandbox, won't start unless you set ALLOW_DANGEROUS_LOCAL_HOST=1. If you only need file edits, access="files" gives the model read_file, write_file and edit and removes bash:

agent = agents.Agent(
    model="mistral-large-4",
    environment=agents.MistralSandbox(access="files"),
)
Enter fullscreen mode Exit fullscreen mode

A call nobody approves doesn't run either. It waits one hour, and then, per the approvals docs, "the call does not run, the model reads that nobody approved it, and the turn continues."

A deployed session ends after 4 hours idle or 24 hours in total by default, per the session lifecycle page, and a session ended by a limit can't resume. On Mistral-managed deployments you can raise those to 24 hours idle and a week total; with agents serve, both go up to a year. If your agent waits on a human over a weekend, plan for a new session.

Subagents need one more check. They "run in the root's sandbox and share its files," according to the subagents page, with at most 10 subagent turns at once and a tree two levels deep. The subagent approvals page has the catch for the policy above: "A default="deny" policy has no rule for agents.spawn, the tool that starts a subagent. Every start is denied." If you use subagents, add an allow or ask rule for agents.spawn. One on_approval handler answers approvals for the whole tree, so write it for every tool a subagent might call.

The search index leaves chunking to you

The managed search index is the other piece agents will lean on. The release notes describe it as "a hosted vector index from a name, an embedding model, and an optional schema." The Search Index overview says it supports vector, keyword and hybrid retrieval with filters, and is also in public preview.

Mistral hosts the index. Per the same page, your pipeline still splits content into chunks, embeds them and sends them with their fields. The Search Toolkit supplies splitting and embedding components. Whether your agent finds the right clause depends on the chunk boundaries you pick.

Tracing is on by default for managed agents. The release notes say agent, model and tool spans go to Studio with no extra package to install, and "Spans are redacted on the worker before they leave." Read what the redaction covers before you send customer data through a tool.

I haven't run the SDK myself. Everything above comes from Mistral's docs and announcement as of November 6, plus AlphaSignal's write-up for the availability split. Before your first agents deploy, check the tool IDs your agent reports and write the deny policy against those IDs.

Do you want agent SDKs to ask before every write by default, or is allow-by-default the right call for a developer tool? Tell me in the comments.


If this was useful

If you also work with Claude Code or Codex, I build Hermes IDE, an IDE for developers who ship with Claude Code and other AI coding tools. It's source-available (BSL 1.1) and runs on macOS, Windows and Linux; weigh the mention with that in mind, and star it on GitHub if it helps.

Mistral will host your vector index, but it still leaves chunking, embedding and retrieval quality to you. The RAG Pocket Guide covers that part: how to chunk, when to rerank, and how to tell whether retrieval is the reason an agent answered wrong. It's one of 8 short books in the Pocket Guides for Developers series, on agents, RAG, prompts, observability, events, databases and system design.

RAG Pocket Guide: Retrieval, Chunking, and Reranking Patterns for Production

Top comments (0)