Mistral Agents

Run Mistral Agents on Flyte, built on the Conversations API in mistralai 2.x. Mistral’s own runner drives the loop and executes tools. Flyte registers task-backed tools with it, records each conversation turn for replay, and renders the run into the task report.

Mistral is server-side, which changes two things relative to the other adapters: the transcript lives on Mistral’s side, and you can drive a pre-created agent by ID instead of an inline model.

Installation

pip install flyteplugins-agents-mistral

Requires Python 3.10 or later and mistralai[agents] 2.0 or later.

Quick start

import flyte
from flyteplugins.agents.mistral import run_agent, tool

env = flyte.TaskEnvironment(
    "mistral-agent",
    secrets=[flyte.Secret(key="mistral_api_key", as_env_var="MISTRAL_API_KEY")],
    image=flyte.Image.from_debian_base().with_pip_packages("flyteplugins-agents-mistral"),
)


@tool
@env.task(cache="auto", retries=3)
async def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return f"The weather in {city} is sunny, 22C."


@env.task(report=True, retries=3)
async def city_agent(question: str) -> str:
    return await run_agent(question, tools=[get_weather], model="mistral-large-latest")

run_agent raises with a clear message if the API key is missing, naming the environment variable it looked in.

How it maps to Flyte

Tools: Mistral’s RunContext takes plain Python functions and registers them with the runner. tool produces one whose body dispatches to task.aio(), so each call runs as a durable child action.

Model turns: The runner makes each turn by calling conversations.start_async or conversations.append_async, both in-process HTTP calls. With durable=True those two methods are wrapped, and each turn is recorded via flyte.trace. The ConversationResponse round-trips through pydantic JSON, including the polymorphic output entries.

That is the seam directly below the loop. The SDK still owns the loop; on a retry, completed turns replay from their records and completed tool calls come back from cache.

Observability: The turns, tool calls and final answer render into the report. The SDK’s RunResult exposes no token usage, but each turn’s ConversationResponse does, so the same wrapper tallies it and adds a usage row.

Replayed turns are counted as cached rather than fresh spend, so a retried run does not present a free replay as though it cost money.

Driving a pre-created agent

Mistral agents can be created server-side and referenced by ID. Pass agent_id instead of model and the tool calls still run as durable Flyte actions.

@env.task(report=True, retries=3)
async def support(request: str) -> str:
    return await run_agent(
        request,
        tools=[lookup_account],
        agent_id="ag_01jd...",
    )

Native handoffs work on this path too. A triage agent can hand the conversation to a billing or technical agent by ID, with the whole multi-agent run durable on Flyte.

Memory

await run_agent(message, model="mistral-large-latest", memory_key="user-alice")

Mistral keeps the transcript server-side, so there is nothing to copy. Flyte persists the thread’s conversation_id in a keyed MemoryStore and continues that conversation when the key recurs.

Bounding a run

timeout_ms is a per-turn request timeout that the SDK applies to each model call inside its loop. It bounds a single hung turn. It is not a whole-run cap, and Mistral exposes no turn-count limit.

To bound the entire agent run, including every turn and tool call, set timeout= on the enclosing task.

run_agent parameters

Parameter Type Default Description
input str required The user prompt
tools Sequence () Tools to expose. Accepts tool-wrapped tools or bare @env.task templates
model str | None "mistral-large-latest" Model for an inline run, when agent_id is not given
instructions str | None None System instructions
timeout_ms int | None None Per-turn request timeout in milliseconds. None uses the SDK default
durable bool True Record and replay each conversation turn
observability bool True Render the timeline into the task report
agent_id str | None None Drive an existing server-side agent instead of model
api_key_env_var str "MISTRAL_API_KEY" Environment variable holding the API key
memory_key str | None None Stable user or thread ID for cross-run memory

Returns the final text. Use run_agent_sync with the same signature from a sync task.

Examples

Full runnable examples live in the SDK repository under plugins/agents/mistral/examples:

  • mistral_durable_agent.py: a single durable agent with per-turn tracing.
  • mistral_crash_resume.py: the task crashes on its first attempt and replays completed turns on retry.
  • mistral_multi_agent.py: a planner, parallel researchers and an editor, each its own durable action.
  • mistral_agent_id.py: driving a pre-created server-side agent by ID.
  • mistral_memory.py: two separate runs sharing a memory_key.
  • mistral_handoffs.py: native handoffs to a specialist agent, which can pause on a Flyte condition for a human detail.
Docs version 2.5.16.1flyte-sdk 2.5.16flyteplugins-union 0.5.2