mini-swe-agent Documentation

The 100 line AI agent that solves GitHub issues or helps you in your command line. Radically simple, no huge configs, no giant monorepo—but scores >74% on...

5,972 stars Python Python 1 file · ~16,436 tokens #agent#agentic-ai#agentic-ai-cli#ai#ai-agent#textual
RAW Doc

File: README.md

The minimal AI software engineering agent

📣 mini-swe-agent now powers Ramp SWE-Bench
📣 mini-swe-agent beats Claude Code and Codex on DeepSWE
📣 Run mini-swe-agent on our new & extremely challenging benchmark, ProgramBench
📣 New tutorial on building minimal AI agents



[!WARNING]
This is mini-swe-agent v2. Read the migration guide. For the previous version, check out the v1 branch.

In 2024, we built SWE-bench & SWE-agent and helped kickstart the coding agent revolution.

We now ask: What if our agent was 100x simpler, and still worked nearly as well?

mini is

  • Widely adopted: Used by Meta, NVIDIA, Essential AI, IBM, Nebius, Anyscale, Princeton University, Stanford University, and many more.
  • Minimal: Just some 100 lines of python for the agent class (and a bit more for the environment,
    model, and run script) — no fancy dependencies!
  • Performant: Scores >74% on the SWE-bench verified benchmark; starts much faster than Claude Code
  • Deployable: Supports local environments, docker/podman, singularity/apptainer, bublewrap, contree, and more
  • Compatible: Supports all models via litellm, openrouter, portkey, and more. Support for /completion and /response endpoints, interleaved thinking etc.
  • Built by the Princeton & Stanford team behind SWE-bench, SWE-agent, and more
  • Tested:

More motivation (for research)

SWE-agent jump-started the development of AI agents in 2024. Back then, we placed a lot of emphasis on tools and special interfaces for the agent.
However, one year later, as LMs have become more capable, a lot of this is not needed at all to build a useful agent!
In fact, the mini agent

  • Does not have any tools other than bash — it doesn't even need to use the tool-calling interface of the LMs.
    This means that you can run it with literally any model. When running in sandboxed environments you also don't need to take care
    of installing a single package — all it needs is bash.
  • Has a completely linear history — every step of the agent just appends to the messages and that's it.
    So there's no difference between the trajectory and the messages that you pass on to the LM.
    Great for debugging & fine-tuning.
  • Executes actions with subprocess.run — every action is completely independent (as opposed to keeping a stateful shell session running).
    This makes it trivial to execute the actions in sandboxes (literally just switch out subprocess.run with docker exec) and to
    scale up effortlessly. Seriously, this is a big deal, trust me.

This makes it perfect as a baseline system and for a system that puts the language model (rather than
the agent scaffold) in the middle of our attention.
You can see the result on the SWE-bench (bash only) leaderboard, that evaluates the performance of different LMs with mini.

More motivation (as a tool)

Some agents are overfitted research artifacts. Others are UI-heavy frontend monsters.

The mini agent wants to be a hackable tool, not a black box.

  • Simple enough to understand at a glance
  • Convenient enough to use in daily workflows
  • Flexible to extend

Unlike other agents (including our own swe-agent), it is radically simpler, because it:

  • Does not have any tools other than bash — it doesn't even need to use the tool-calling interface of the LMs.
    Instead of implementing custom tools for every specific thing the agent might want to do, the focus is fully on the LM utilizing the shell to its full potential.
    Want it to do something specific like opening a PR?
    Just tell the LM to figure it out rather than spending time to implement it in the agent.
  • Executes actions with subprocess.run — every action is completely independent (as opposed to keeping a stateful shell session running).
    This is a big deal for the stability of the agent, trust me.
  • Has a completely linear history — every step of the agent just appends to the messages that are passed to the LM in the next step and that's it.
    This is great for debugging and understanding what the LM is prompted with.

Should I use SWE-agent or mini-SWE-agent?

You should consider mini-swe-agent your default choice.
In particular, you should use mini-swe-agent if

  • You want a quick command line tool that works locally
  • You want an agent with a very simple control flow
  • You want even faster, simpler & more stable sandboxing & benchmark evaluations
  • You are doing FT or RL and don't want to overfit to a specific agent scaffold

You should use swe-agent if

  • You want to experiment with different sets of tools, each with their own interface
  • You want to experiment with different history processors

What you get with both

  • Excellent performance on SWE-Bench
  • A trajectory browser
CLI (mini) Batch inference
Trajectory browser Python bindings
```python
agent = DefaultAgent(
text
LitellmModel(model_name=...),
LocalEnvironment(),

)
agent.run("Write a sudoku game")

|
## Let's get started!

**Option 1:** If you just want to try out the CLI (package installed in anonymous virtual environment)

```bash
pip install uv && uvx mini-swe-agent
# or
pip install pipx && pipx ensurepath && pipx run mini-swe-agent

Option 2: Install CLI & python bindings in current environment

bash
pip install mini-swe-agent
mini  # run the CLI

Option 3: Install from source (developer setup)

bash
git clone https://github.com/SWE-agent/mini-swe-agent.git
cd mini-swe-agent && pip install -e .
mini  # run the CLI

Read more in our documentation:

Attribution

If you found this work helpful, please consider citing the SWE-agent paper in your work:

bibtex
@inproceedings{yang2024sweagent,
  title={{SWE}-agent: Agent-Computer Interfaces Enable Automated Software Engineering},
  author={John Yang and Carlos E Jimenez and Alexander Wettig and Kilian Lieret and Shunyu Yao and Karthik R Narasimhan and Ofir Press},
  booktitle={The Thirty-eighth Annual Conference on Neural Information Processing Systems},
  year={2024},
  url={https://arxiv.org/abs/2405.15793}
}

Our other projects:


File: docs/advanced/control_flow.md

Agent control flow

!!! note "Understanding AI agent basics"

text
We also recently created a long tutorial on understanding the basics of building an AI agent: [View it here](https://minimal-agent.com).

!!! abstract "Understanding the default agent"

text
* This guide shows the control flow of the default agent.
* After this, you're ready to [remix & extend mini](cookbook.md)

The following diagram shows the control flow of the mini agent:

mermaid
flowchart TD
    subgraph run["**`Agent.run(task)`**"]
        direction TB
        A["**`Initialize messages`**"] --> B
        B["**`Agent.step`**"] --> C{"**`Exception?`**"}
        C -->|Yes| D["**`Agent.add_messages`**(also re-raises exceptions that don't inherit from InterruptAgentFlow)"]
        C -->|No| E{"**`messages[-1].role == exit?`**"}
        D --> E
        E -->|No| B
        E -->|Yes| F["**`Return result`**"]
    end

    subgraph step["**`Agent.step()`**Single iteration"]
        direction TB
        S1["**`Agent.query`**"] --> S2["**`Agent.execute_actions`**"]
    end

    subgraph query["**`Agent.query()`**Also checks for cost limits"]
        direction TB
        Q3["**`Model.query`**"] --> Q4["**`Agent.add_messages`**"]
    end

    subgraph execute_actions["**`Agent.execute_actions(message)`**"]
        direction TB
        E2["**`Environment.execute`**Also raises the Submitted exception if we're done"] --> E3["**`Model.format_observation_messages`**"]
        E3 --> E4["**`Agent.add_messages`**"]
    end

    B -.-> step
    S1 -.-> query
    S2 -.-> execute_actions

And here is the code that implements it:

??? note "Default agent class"

text
- [Read on GitHub](https://github.com/swe-agent/mini-swe-agent/blob/main/src/minisweagent/agents/default.py)
- [API reference](../reference/agents/default.md)

```python
--8<-- "src/minisweagent/agents/default.py"
```

Essentially, DefaultAgent.run calls DefaultAgent.step in a loop until the agent has finished its task.

The step method is the core of the agent:

python
def step(self) -> list[dict]:
    return self.execute_actions(self.query())

It does the following:

  1. Queries the model for a response based on the current messages (DefaultAgent.query, calling Model.query)
  2. Executes all actions in the response (DefaultAgent.execute_actions, calling Environment.execute for each action)
  3. Formats the observation messages via Model.format_observation_messages
  4. Adds the observations to the messages

Here's query:

python
def query(self) -> dict:
    # ... limit checks ...
    message = self.model.query(self.messages)
    self.add_messages(message)
    return message

And execute_actions:

python
def execute_actions(self, message: dict) -> list[dict]:
    outputs = [self.env.execute(action) for action in message.get...
    return self.add_messages(*self.model.format_observation_messages(...))

The interesting bit is how we handle error conditions and the finish condition:
This uses exceptions that inherit from InterruptAgentFlow. All these exceptions carry messages that get added to the trajectory.

  • Submitted is raised when the agent has finished its task. For example, the environment checks if the command output starts with a magic string:

    python
    # In Environment.execute
    def _check_finished(self, output: dict):
        lines = output.get("output", "").lstrip().splitlines(keepends=True)
        if lines and lines[0].strip() == "COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT":
            raise Submitted({"role": "exit", "content": ..., "extra": {...}})
  • LimitsExceeded is raised when we hit a cost or step limit

  • FormatError is raised when the output from the LM is not in the expected format

  • TimeoutError is raised when the action took too long to execute

  • UserInterruption is raised when the user interrupts the agent

The DefaultAgent.run method catches these exceptions and handles them by adding the corresponding messages to the messages list. The loop continues until a message with role="exit" is added.

python
while True:
    try:
        self.step()
    except InterruptAgentFlow as e:
        self.add_messages(*e.messages)
    if self.messages[-1].get("role") == "exit":
        break

Using exceptions for the control flow is a lot easier than passing around flags and states, especially when extending or subclassing the agent.

{% include-markdown "_footer.md" %}


File: docs/advanced/cookbook.md

Cookbook

!!! abstract "Remixing & extending mini"

text
* This guide shows how to mix the different components of the `mini` agent to create your own custom version.
* You might want to first take a look at the [control flow of the default agent](control_flow.md) first

!!! note "Development setup"

text
Make sure to follow the dev setup instructions in [quickstart.md](../quickstart.md).

We provide several different entry points to the agent,
for example hello world,
or the default when calling mini.

Want to cook up your custom version and the config is not enough?
Just follow the recipe below:

  1. What's the control flow you need? Pick an agent class (e.g., simplest example, with human in the loop)
  2. How should actions be executed? Pick an environment class (e.g., local, or docker)
  3. How is the LM queried? Pick a model class (e.g., litellm)
  4. How to invoke the agent? Bind them all together in a run script, possibly reading from a config (e.g., hello world, or mini entry point)

We aim to keep all of these components very simple, but offer lots of choice between them -- enough to cover a broad range of
things that you might want to do.

You can override the default entry point by setting the MSWEA_DEFAULT_RUN environment variable to the import path of your run script.

Hello world

See Python bindings for the most basic example.

Mix & match

Models

=== "Hello world (use automatic model selection)"

text
```python
from minisweagent.agents.default import DefaultAgent
from minisweagent.models import get_model
from minisweagent.environments.local import LocalEnvironment

model_name = "anthropic/claude-sonnet-4-5-20250929"

agent = DefaultAgent(
    get_model(input_model_name=model_name),
    LocalEnvironment(),
)
agent.run(task)
```

=== "Hello world (Litellm)"

text
```python
from minisweagent.agents.default import DefaultAgent
from minisweagent.models.litellm_model import LitellmModel
from minisweagent.environments.local import LocalEnvironment

model_name = "gpt-4o"

agent = DefaultAgent(
    LitellmModel(model_name=model_name),
    LocalEnvironment(),
)
agent.run(task)
```

Environments

=== "Hello world with local execution"

text
```python
from minisweagent.environments.local import LocalEnvironment

agent = DefaultAgent(
    LitellmModel(model_name=model_name),
    LocalEnvironment(),
)
```

=== "Hello world with docker execution"

text
```python
from minisweagent.environments.docker import DockerEnvironment

agent = DefaultAgent(
    LitellmModel(model_name=model_name),
    DockerEnvironment(),
)
```

Agents

=== "Default agent"

text
```python
from minisweagent.agents.default import DefaultAgent
from minisweagent.models import get_model
from minisweagent.environments.local import LocalEnvironment

agent = DefaultAgent(
    get_model(input_model_name=model_name),
    LocalEnvironment(),
)
```

=== "Human in the loop"

text
```python
from minisweagent.agents.interactive import InteractiveAgent
from minisweagent.models import get_model
from minisweagent.environments.local import LocalEnvironment

agent = InteractiveAgent(
    get_model(input_model_name=model_name),
    LocalEnvironment(),
)
```

Advanced

Customizing execution

An agent that uses python function for some actions:

=== "Subclassing the agent"

text
```python
from minisweagent.agents.default import DefaultAgent
import shlex

def python_function(*args) -> dict:
    ...
    return {"output": "..."}

class AgentWithPythonFunctions(DefaultAgent):
    def execute_actions(self, message: dict) -> list[dict]:
        for action in message.get("extra", {}).get("actions", []):
            command = action.get("command", "")
            if command.startswith("python_function"):
                args = shlex.split(command.removeprefix("python_function").strip())
                return self.add_messages(self.model.format_observation_messages(
                    message, [python_function(*args)], self.get_template_vars()
                ))
        # everything else works as usual
        return super().execute_actions(message)
```

=== "Subclassing the environment"

text
```python
from minisweagent.agents.default import DefaultAgent
from minisweagent.environments.local import LocalEnvironment
import shlex

def python_function(*args) -> dict:
    ...
    return {"output": "..."}

class EnvironmentWithPythonFunctions(LocalEnvironment):
    def execute(self, action: dict, cwd: str = "") -> dict:
        command = action.get("command", "")
        if command.startswith("python_function"):
            args = shlex.split(command.removeprefix("python_function").strip())
            return python_function(*args)
        # all other commands are executed as usual
        return super().execute(action, cwd)

agent = DefaultAgent(
    LitellmModel(model_name=model_name),
    EnvironmentWithPythonFunctions(),
)
```

An agent that exits when the submit command is issued:

=== "Subclassing the agent"

text
```python
from minisweagent.agents.default import DefaultAgent
from minisweagent.exceptions import Submitted

class AgentQuitsOnSubmit(DefaultAgent):
    def execute_actions(self, message: dict) -> list[dict]:
        for action in message.get("extra", {}).get("actions", []):
            if action.get("command", "") == "submit":
                # The `Submitted` exception will be caught by the agent and
                # the final output will be printed.
                raise Submitted({
                    "role": "exit",
                    "content": "The agent has finished its task.",
                    "extra": {"exit_status": "Submitted", "submission": ""},
                })
        return super().execute_actions(message)
```

=== "Subclassing the environment"

text
```python
from minisweagent.agents.default import DefaultAgent
from minisweagent.environments.local import LocalEnvironment
from minisweagent.exceptions import Submitted

class EnvironmentQuitsOnSubmit(LocalEnvironment):
    def execute(self, action: dict, cwd: str = "") -> dict:
        if action.get("command", "") == "submit":
            raise Submitted({
                "role": "exit",
                "content": "The agent has finished its task.",
                "extra": {"exit_status": "Submitted", "submission": ""},
            })
        return super().execute(action, cwd)

agent = DefaultAgent(
    LitellmModel(model_name=model_name),
    EnvironmentQuitsOnSubmit(),
)
```

An agent that validates actions before execution (also an example of how to use an extended config class):

=== "Subclassing the agent"

text
```python
import re
from minisweagent.agents.default import DefaultAgent, AgentConfig
from minisweagent.exceptions import FormatError
from pydantic import BaseModel

class ValidatingAgentConfig(AgentConfig):
    forbidden_patterns: list[str] = [
        r"rm -rf /",
        r"sudo.*passwd",
        r"mkfs\.",
    ]

class ValidatingAgent(DefaultAgent):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs, config_class=ValidatingAgentConfig)

    def execute_actions(self, message: dict) -> list[dict]:
        for action in message.get("extra", {}).get("actions", []):
            command = action.get("command", "")
            for pattern in self.config.forbidden_patterns:
                if re.search(pattern, command, re.IGNORECASE):
                    raise FormatError(self.model.format_message(
                        role="user", content="Action blocked: forbidden pattern detected"
                    ))
        return super().execute_actions(message)
```

=== "Subclassing the environment"

text
```python
import re
from minisweagent.agents.default import DefaultAgent
from minisweagent.environments.local import LocalEnvironment, LocalEnvironmentConfig
from minisweagent.models.litellm_model import LitellmModel

class EnvironmentWithForbiddenPatternsConfig(LocalEnvironmentConfig):
    forbidden_patterns: list[str] = [
        r"rm -rf /",
        r"sudo.*passwd",
        r"mkfs\.",
    ]

class EnvironmentWithForbiddenPatterns(LocalEnvironment):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs, config_class=EnvironmentWithForbiddenPatternsConfig)

    def execute(self, action: dict, cwd: str = "") -> dict:
        command = action.get("command", "")
        for pattern in self.config.forbidden_patterns:
            if re.search(pattern, command, re.IGNORECASE):
                return {"output": "Action blocked: forbidden pattern detected", "returncode": 1}
        return super().execute(action, cwd)

agent = DefaultAgent(
    LitellmModel(model_name=model_name),
    EnvironmentWithForbiddenPatterns(),
)
```

Running mini-swe-agent on Ray

This blog post
describes how to parallelize mini-swe-agent runs with Ray.

{% include-markdown "_footer.md" %}


File: docs/advanced/environments.md

Environment classes

!!! abstract "Environment classes"

text
* Environments are what is executing the code generated by the LM/agent.
* We offer different classes for either executing code directly on the host machine, or in a container (e.g., Docker, Singularity, etc.).

We support various environments for executing code through different backends.

If you run the mini CLI, you will run in the local environment by default.

However, particularly for evaluating on SWE-bench, you want to run in isolated environments, so we offer multiple "backends" that you can use.

You can specify the environment class with the --environment-class flag or the
environment.environment_class key in the agent config file.

  • local (LocalEnvironment). Executes commands directly on the host machine using subprocess.run. No isolation. Directly works in your current python environment.

  • docker (DockerEnvironment). Executes commands with docker exec.

  • singularity (SingularityEnvironment) - Executes commands in Singularity/Apptainer containers. Good alternative to Docker in HPC environments where Docker is not available.

On top, there are a few more specialized environment classes that you can use:


File: docs/advanced/global_configuration.md

Global configuration

!!! abstract "Configuring mini"

text
* This guide shows how to configure the `mini` agent's global settings (API keys, default model, etc.).
  Basically anything that is set as environment variables or similar.
* You should already be familiar with the [quickstart guide](../quickstart.md).
* For more agent specific settings, see the [yaml configuration file guide](yaml_configuration.md).

!!! tip "Setting up models"

text
Setting up models is also covered in the [quickstart guide](../quickstart.md).

Setting global configuration

All global configuration can be either set as environment variables, or in the .env file (the exact location is printed when you run mini).
Environment variables take precedence over variables set in the .env file.

We provide several helper functions to update the global configuration.

For example, to set the default model and API keys, you can run:

bash
mini-extra config setup

or to update specific settings:

text
mini-extra config set KEY VALUE
# e.g.,
mini-extra config set MSWEA_MODEL_NAME "anthropic/claude-sonnet-4-5-20250929"
mini-extra config set ANTHROPIC_API_KEY "sk-..."

or to unset a key:

bash
mini-extra config unset KEY
# e.g.,
mini-extra config unset ANTHROPIC_API_KEY

You can also edit the .env file directly and we provide a helper function for that:

bash
mini-extra config edit

To set environment variables (recommended for temporary experimentation or API keys):

bash
export KEY="value"
# windows:
setx KEY "value"

Models, keys, costs

!!! tip "See also"

text
Read the [quickstart guide](../quickstart.md) first—it already covers most of this.
bash
# Default model name
# (default: not set)
MSWEA_MODEL_NAME="anthropic/claude-sonnet-4-5-20250929"

To ignore errors from cost tracking checks (for example for free models), set:

bash
# CAREFUL: This can lead to unmanaged spending!
MSWEA_COST_TRACKING="ignore_errors"

To register extra models to litellm (see local models for more details), you can either specify the path in the agent file, or set

bash
LITELLM_MODEL_REGISTRY_PATH="/path/to/your/model/registry.json"

Global cost limits:

bash
# Global limit on number of model calls (0 = no limit)
# (default: 0)
MSWEA_GLOBAL_CALL_LIMIT="100"

# Global cost limit in dollars (0 = no limit)
# (default: 0)
MSWEA_GLOBAL_COST_LIMIT="10.00"

# Number of retry attempts for model API calls
# (default: 10)
MSWEA_MODEL_RETRY_STOP_AFTER_ATTEMPT="10"

Default config files

bash
# Set a custom directory for agent config files in addition to the builtin ones
# This allows to specify them by names
MSWEA_CONFIG_DIR="/path/to/your/own/config/dir"

# Config path for mini run script
# (default: package_dir / "config" / "mini.yaml")
MSWEA_MINI_CONFIG_PATH="/path/to/your/own/config"

# Custom style path for trajectory inspector
# (default: package_dir / "config" / "inspector.tcss")
MSWEA_INSPECTOR_STYLE_PATH="/path/to/your/inspector/style.tcss"

Settings for environments

bash
# Path/name to the singularity/apptainer executable
# (default: "singularity")
MSWEA_SINGULARITY_EXECUTABLE="singularity"

# Path/name to the docker executable
# (default: "docker")
MSWEA_DOCKER_EXECUTABLE="docker"

# Path/name to the bubblewrap executable
# (default: "bwrap")
MSWEA_BUBBLEWRAP_EXECUTABLE="bwrap"

Default run files

bash
# Default run script entry point for the main CLI
# (default: "minisweagent.run.mini")
MSWEA_DEFAULT_RUN="minisweagent.run.mini"

{% include-markdown "_footer.md" %}


File: docs/advanced/v2_migration.md

v2.0 Migration Guide

!!! danger "Breaking Changes"

text
**mini-swe-agent v2.0** brings major improvements but requires migration.
To stay with v1.x, pin your dependency: `mini-swe-agent~=1.0`.
See the [v1 documentation](https://mini-swe-agent.com/v1/) or the [v1 branch on GitHub](https://github.com/SWE-agent/mini-swe-agent/tree/v1).

What's new

  • Tool calls: Native tool calling API support (now the default)
  • Multimodal input: Support for images and other content types

What do I need to change?

I only use the mini CLI with default configs

No changes needed.

I use custom configs

You might need to move some config keys. See Config changes.

I parse/analyze trajectories

Some metadata fields moved to extra. See Trajectory format.

I use the python bindings or built custom subclasses

You will need to refactor. An agent can refactor your code based on the instructions below.

Config changes

If you only changed system_template and instance_template, no changes needed.

Move from agent to model:

  • observation_template (renamed from action_observation_template)
  • format_error_template
  • action_regex (only for text-based parsing)

Removed:

  • timeout_template

Code block format changed:

Default action regex changed from ```bash to ```mswea_bash_command to avoid conflicts with bash examples in prompts.

Completion signal changed:

From echo MINI_SWE_AGENT_FINAL_OUTPUT to echo COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT.

New structure:

yaml
agent:
  system_template: "..."
  instance_template: "..."
  step_limit: 0
  cost_limit: 3.
environment:
  cwd: "..."
  timeout: 30
model:
  model_name: "..."
  observation_template: "..."
  format_error_template: "..."

CLI now supports multiple configs and key-value overrides:

bash
mini -c mini.yaml -c model.model_kwargs.temperature=0.5
mini -c swebench.yaml -c agent.step_limit=100
mini -c mini.yaml -c /path/to/model.yaml

!!! warning
If you use -c, you will not load the full default config, so make sure to always specify your config file in addition to any overrides/updates.

Tool calling

v2.0 uses native tool calling by default (instead of regex-based text parsing).

What's the difference?

  • Tool calling (default): Model uses native tool calling API to invoke a "bash" tool
  • Text-based (legacy): Model outputs commands in markdown code blocks (or similar), regex extracts them

How to use it:

Tool calling is the default. The CLI uses mini.yaml and swebench.yaml which are configured for tool calling.

bash
# Default (tool calling)
mini
python -m minisweagent.run.benchmarks.swebench
mini-extra swebench

# Text-based parsing
mini-extra swebench -c swebench_backticks.yaml
mini -c mini_textbased.yaml

For custom configs:

yaml
model:
  model_class: litellm  # tool calling (default)
  model_name: anthropic/claude-sonnet-4-5-20250929

# or for text-based:
model:
  model_class: litellm_textbased
  action_regex: "```mswea_bash_command\\s*\\n(.*?)\\n```"

Trajectory format

  • In v1, all messages in the trajectory's messages field were "hand-formatted", i.e., had a content: str and role: str field.
  • In v2, we use the model's native output as the basis for the message and only add the extra field to it.

If you use a model that uses the standard /completion endpoint, then you will still always have a content: str and role: str field.
However, if you use the /response endpoint, then things might look different.

In other words: the exact message structure depends on the model you use.

  • Advantage: Any model message structure is supported
  • Disadvantage: If you parse trajectories, you might need to adapt to the message structure of the model you use.

Removed & renamed

Removed features:

  • "Visual" UI: The -v flag for the alternate, textual based mini -v CLI is no longer supported. This was a tough decision to make, but in the end the visual mode didn't see the adoption we wanted and is significantly more complex to maintain than the default interface.
  • Rotating API keys: ANTHROPIC_API_KEYS with :: separator no longer supported. Use single ANTHROPIC_API_KEY.
  • github_issue run script: The dedicated github_issue.py run script was removed. Use the mini CLI instead.
  • MSWEA_MODEL_API_KEY environment variable: No longer used to override API keys.

Removed model classes:

  • anthropic model class: Removed. Use litellm model class for Anthropic models (make sure that cache control is enabled).

Renamed model classes:

v1 name v2 name
litellm_response_api litellm_response
portkey_response_api portkey_response

New model classes:

Name Description
litellm_textbased Text-based parsing (regex) instead of tool calls
openrouter_textbased Text-based parsing for OpenRouter
openrouter_response OpenRouter with response API

New environment:

  • swerex_modal: Run environments on Modal (requires pip install mini-swe-agent[modal])

Architecture changes

  1. Responsibility shift: Models now parse actions and format observations. This enables switching between tool calls and text parsing by changing model classes. The Agent class is now a simpler coordinator.

  2. Stateless models: Cost tracking moved to Agent. The cost and n_calls attributes were removed from the Model protocol.

  3. Pydantic configs: AgentConfig (and other configs) changed from dataclass to Pydantic BaseModel. This requires pydantic >= 2.0.

  4. New protocol methods: All classes implement get_template_vars() and serialize() instead of requiring specific attributes.

Protocol changes

If you want to write a custom Model, Environment or Agent compatible with mini-swe-agent, you don't need to subclass anything.
Rather, mini-swe-agent fully uses duck typing with protocols
(tl;dr: as long as you implement the required methods, you can use any class as a Model, Environment or Agent).
Config options like --config-class also take full import classes, so you can put your classes wherever you want.

Model protocol:

python
# Removed attributes
cost: float      # moved to Agent
n_calls: int     # moved to Agent

# New methods
def format_message(self, **kwargs) -> dict: ...
def format_observation_messages(self, message: dict, outputs: list[dict], template_vars: dict | None = None) -> list[dict]: ...
def serialize(self) -> dict: ...

Environment protocol:

python
# Changed signature
def execute(self, action: dict, cwd: str = "") -> dict[str, Any]: ...  # was: (command: str) -> dict[str, str]

# New method
def serialize(self) -> dict: ...

Agent protocol:

python
# Removed attributes (you don't need to implement these anymore, but you can)
model: Model
env: Environment
messages: list[dict]

# Changed return type
def run(self, task: str, **kwargs) -> dict: ...  # was: tuple[str, str]

# New method
def save(self, path: Path | None, *extra_dicts) -> dict: ...

Exception changes

All flow control exceptions now inherit from InterruptAgentFlow and moved to minisweagent.exceptions:

python
InterruptAgentFlow (base)
├── Submitted (task completed)
├── LimitsExceeded (cost/step limit)
├── FormatError (invalid model output)
└── UserInterruption (user cancelled)  # new

Removed exception classes:

  • NonTerminatingException - use InterruptAgentFlow base class
  • TerminatingException - use InterruptAgentFlow base class
  • ExecutionTimeoutError - removed (no longer used)
python
# Old
from minisweagent.agents.default import Submitted, FormatError

# New
from minisweagent.exceptions import Submitted, FormatError

Agent.run() return value

python
# Old (v1)
submission, exit_status = agent.run(task)  # tuple[str, str]

# New (v2)
result = agent.run(task)  # dict
submission = result["submission"]
exit_status = result["exit_status"]

The run() method returns the extra dict from the final exit message. For full trajectory data, use agent.save(path) or agent.serialize().


File: docs/advanced/yaml_configuration.md

Yaml config files

!!! abstract "Agent configuration files"

text
* You can configure the agent's behavior using YAML configuration files. This guide shows how to do that.
* You should already be familiar with the [quickstart guide](../quickstart.md).
* For global environment settings (API keys, default model, etc., basically anything that can be set as environment variables), see [global configuration](global_configuration.md).
* Want more? See [python bindings](cookbook.md) for subclassing & developing your own agent.

Overall structure

Configuration files look like this:

??? note "Configuration file"

text
```yaml
--8<-- "src/minisweagent/config/mini.yaml"
```

We use the following top-level keys:

  • agent: Agent configuration (prompt templates, cost limits etc.)
  • environment: Environment configuration (if you want to run in a docker container, etc.)
  • model: Model configuration (model name, reasoning strength, etc.)
  • run: Run configuration (output file, etc.)

Agent configuration

Different agent classes might have slightly different configuration options.
You can find the full list of options in the API reference.

To use a different agent class, you can set the agent_class key to the name of the agent class you want to use
or even to an import path (to use your own custom agent class even if it is not yet part of the mini-SWE-agent package).

Prompt templates

We use Jinja2 to render templates (e.g., the instance template).

TL;DR: You include variables with double (!) curly braces, e.g. {{task}} to include the task that was given to the agent.

However, you can also do fairly complicated logic like this directly from your template:

??? note "Example: Dealing with long observations"

text
The following snippets shortens long observations and displays a warning if the output is too long.

```jinja
<returncode>{{output.returncode}}</returncode>
{% if output.output | length < 10000 -%}
    <output>
        {{ output.output -}}
    </output>
{%- else -%}
    <warning>
        The output of your last command was too long.
        Please try a different command that produces less output.
        If you're looking at a file you can try use head, tail or sed to view a smaller number of lines selectively.
        If you're using grep or find and it produced too much output, you can use a more selective search pattern.
        If you really need to see something from the full command's output, you can redirect output to a file and then search in that file.
    </warning>

    {%- set elided_chars = output.output | length - 10000 -%}

    <output_head>
        {{ output.output[:5000] }}
    </output_head>

    <elided_chars>
        {{ elided_chars }} characters elided
    </elided_chars>

    <output_tail>
        {{ output.output[-5000:] }}
    </output_tail>
{%- endif -%}
```

In all builtin agents, you can use the following variables:

  • Environment variables (LocalEnvironment only, see discussion here)
  • Agent config variables (i.e., anything that was set in the agent section of the config file, e.g., step_limit, cost_limit, etc.)
  • Environment config variables (i.e., anything that was set in the environment section of the config file, e.g., cwd, timeout, etc.)
  • Variables passed to the run method of the agent (by default that's only task, but you can pass other variables if you want to)
  • Output of the last action execution (i.e., output from the execute_action method)

Using tool calls

Make sure to use the appropriate model class and matching configuration.

Custom Action Parsing from Text

mini-SWE-agent can parse actions from markdown code blocks (```mswea_bash_command ... ```) or from tool calls.
You can customize this behavior by setting the action_regex field to support different formats like XML.

!!! warning "Important"

text
If you set a custom action_regex (e.g. `<action>(.*?)</action>`), you must use the same output format across all prompt templates (system_template, instance_template, format_error_template, etc.), ensuring the LLM wraps commands accordingly. See the example below for a complete configuration.

??? example "Using XML format instead of markdown"

text
This example uses the same structure as the default mini.yaml config, but with `<action>` tags instead of markdown code blocks:

```yaml
--8<-- "src/minisweagent/config/benchmarks/swebench_xml.yaml"
```

You can also directly load this config by specifying `--config swebench_xml`.

??? example "Default markdown format"

text
This is the default configuration (already the default, you don't need to specify this):


```yaml
model:
  action_regex: ```mswea_bash_command\s*\n(.*?)\n```
agent:
  system_template: |
    Your response must contain exactly ONE bash code block.

    ```mswea_bash_command
    your_command_here
    ```
```

!!! warning "Linebreaks & escaping"

text
When specifying `action_regex` from the `yaml` config file, make sure you understand how escaping in yaml files works.
For example, when you use the `|` primitive, your regex might have a linbreak at the end which is probably not what you want.
The best way is to keep your regex on a single line and NOT use any quotation marks around it. You do NOT need to escape any characters in the regex. Example: `action_regex: (.*?)`

Model configuration

See this guide for more details on model configuration.

Environment configuration

See this guide for more details on environment configuration.

Run configuration

See the information in "Usage".

{% include-markdown "_footer.md" %}


File: docs/models/local_models.md

!!! abstract "Local models"

text
* This guide shows how to set up local models.
* You should already be familiar with the [quickstart guide](../quickstart.md).
* You should also quickly skim the [global configuration guide](../advanced/global_configuration.md) to understand
  the global configuration and [yaml configuration files guide](../advanced/yaml_configuration.md).

!!! tip "Examples"

text
* [Issue #303](https://github.com/SWE-agent/mini-swe-agent/issues/303) has several examples of how to use local models.
* We also welcome concrete examples of how to use local models per pull request into this guide.

Using litellm

Currently, models are supported via litellm by default.

There are typically two steps to using local models:

  1. Editing the agent config file to add settings like custom_llm_provider and api_base.
  2. Either ignoring errors from cost tracking or updating the model registry to include your local model.

Setting API base/provider

If you use local models, you most likely need to add some extra keywords to the litellm call.
This is done with the model_kwargs dictionary which is directly passed to litellm.completion.

In other words, this is how we invoke litellm:

python
litellm.completion(
    model=model_name,
    messages=messages,
    **model_kwargs
)

You can set model_kwargs in an agent config file like the following one:

??? note "Default configuration file"

text
```yaml
--8<-- "src/minisweagent/config/mini.yaml"
```

In the last section, you can add

yaml
model:
  model_name: "my-local-model"
  model_kwargs:
    custom_llm_provider: "openai"
    api_base: "https://..."
    ...
  ...

!!! tip "Updating the default mini configuration file"

text
You can set the `MSWEA_MINI_CONFIG_PATH` setting to set path to the default `mini` configuration file.
This will allow you to override the default configuration file with your own.
See the [global configuration guide](../advanced/global_configuration.md) for more details.

If this is not enough, our model class should be simple to modify:

??? note "Complete model class"

text
- [Read on GitHub](https://github.com/swe-agent/mini-swe-agent/blob/main/src/minisweagent/models/litellm_model.py)
- [API reference](../reference/models/litellm.md)

```python
--8<-- "src/minisweagent/models/litellm_model.py"
```

The other part that you most likely need to figure out are costs.
There are two ways to do this with litellm:

  1. You set up a litellm proxy server (which gives you a lot of control over all the LM calls)
  2. You update the model registry (next section)

Cost tracking

If you run with the above, you will most likely get an error about missing cost information.

If you do not need cost tracking, you can ignore these errors, ideally by editing your agent config file to add:

yaml
model:
  cost_tracking: "ignore_errors"
  ...
...

Alternatively, you can set the global setting:

bash
export MSWEA_COST_TRACKING="ignore_errors"

However, note that this is a global setting, and will affect all models!

However, the best way to handle the cost issue is to add a model registry to litellm to include your local model.

LiteLLM gets its cost and model metadata from this file. You can override or add data from this file if it's outdated or missing your desired model by including a custom registry file.

The model registry JSON file should follow LiteLLM's format:

json
{
  "my-custom-model": {
    "max_tokens": 4096,
    "input_cost_per_token": 0.0001,
    "output_cost_per_token": 0.0002,
    "litellm_provider": "openai",
    "mode": "chat"
  },
  "my-local-model": {
    "max_tokens": 8192,
    "input_cost_per_token": 0.0,
    "output_cost_per_token": 0.0,
    "litellm_provider": "ollama",
    "mode": "chat"
  }
}

!!! warning "Model names"

text
Model names are case sensitive. Please make sure you have an exact match.

!!! warning "Model provider"

text
If you use the `custom_llm_provider` or have a provider prefixed to the model name (e.g., `openai/...`),
then this must also match `litellm_provider` in the config!

There are two ways of setting the path to the model registry:

  1. Set LITELLM_MODEL_REGISTRY_PATH (e.g., mini-extra config set LITELLM_MODEL_REGISTRY_PATH /path/to/model_registry.json)
  2. Set litellm_model_registry in the agent config file
yaml
model:
  litellm_model_registry: "/path/to/model_registry.json"
  ...
...

Concrete examples

Generating SWE-bench trajectories with vLLM

This example shows how to generate SWE-bench trajectories using vLLM as the local inference engine.

First, launch a vLLM server with your chosen model. For example:

bash
vllm serve ricdomolm/mini-coder-1.7b &

By default, the server will be available at http://localhost:8000.

Second, edit the mini-swe-agent SWE-bench config file located in src/minisweagent/config/benchmarks/swebench.yaml to include your local vLLM model:

yaml
model:
  model_name: "hosted_vllm/ricdomolm/mini-coder-1.7b"  # or hosted_vllm/path/to/local/model
  model_kwargs:
    api_base: "http://localhost:8000/v1"  # adjust if using a non-default port/address

If you need a custom registry, as detailed above, create a registry.json file:

bash
cat > registry.json <<'EOF'
{
  "ricdomolm/mini-coder-1.7b": {
    "max_tokens": 40960,
    "input_cost_per_token": 0.0,
    "output_cost_per_token": 0.0,
    "litellm_provider": "hosted_vllm",
    "mode": "chat"
  }
}
EOF

Now you’re ready to generate trajectories! Let's solve the django__django-11099 instance of SWE-bench Verified:

bash
LITELLM_MODEL_REGISTRY_PATH=registry.json mini-extra swebench \
    --output test/ --subset verified --split test --filter '^(django__django-11099)$'

You should now see the generated trajectory in the test/ directory.

--8<-- "docs/_footer.md"


File: docs/models/quickstart.md

Model setup quickstart

!!! tip "Setup"

text
* In most cases, you can simply run `mini-extra config setup` to set up your default model and API keys.
  This should be run the first time you run `mini`.
* By default we support all models using [`litellm`](https://github.com/BerriAI/litellm).
* We also offer support for models via [Openrouter](https://openrouter.ai/) and [Portkey](https://portkey.ai/).

Setting API keys

There are several ways to set your API keys:

  • Recommended: Run our setup script: mini-extra config setup. This should also run automatically the first time you run mini.
  • Use mini-extra config set ANTHROPIC_API_KEY <your-api-key> to put the key in the mini config file.
  • Export your key as an environment variable: export ANTHROPIC_API_KEY=<your-api-key> (this is not persistent if you restart your shell, unless you add it to your shell config, like ~/.bashrc or ~/.zshrc).
  • If you run several agents in parallel, see our note about rotating anthropic keys here.

??? note "All the API key names"

text
We use [`litellm`](https://github.com/BerriAI/litellm) to support most models.
Here's a list of all the API key names available in `litellm`:

```
ALEPH_ALPHA_API_KEY
ALEPHALPHA_API_KEY
ANTHROPIC_API_KEY
ANYSCALE_API_KEY
AZURE_AI_API_KEY
AZURE_API_KEY
AZURE_OPENAI_API_KEY
BASETEN_API_KEY
CEREBRAS_API_KEY
CLARIFAI_API_KEY
CLOUDFLARE_API_KEY
CO_API_KEY
CODESTRAL_API_KEY
COHERE_API_KEY
DATABRICKS_API_KEY
DEEPINFRA_API_KEY
DEEPSEEK_API_KEY
FEATHERLESS_AI_API_KEY
FIREWORKS_AI_API_KEY
FIREWORKS_API_KEY
FIREWORKSAI_API_KEY
GEMINI_API_KEY
GROQ_API_KEY
HUGGINGFACE_API_KEY
INFINITY_API_KEY
MARITALK_API_KEY
MISTRAL_API_KEY
NEBIUS_API_KEY
NLP_CLOUD_API_KEY
NOVITA_API_KEY
NVIDIA_NIM_API_KEY
OLLAMA_API_KEY
OPENAI_API_KEY
OPENAI_LIKE_API_KEY
OPENROUTER_API_KEY
OR_API_KEY
PALM_API_KEY
PERPLEXITYAI_API_KEY
PREDIBASE_API_KEY
PROVIDER_API_KEY
REPLICATE_API_KEY
TOGETHERAI_API_KEY
VOLCENGINE_API_KEY
VOYAGE_API_KEY
WATSONX_API_KEY
WX_API_KEY
XAI_API_KEY
XINFERENCE_API_KEY
```

In addition, Portkey models use the `PORTKEY_API_KEY` environment variable.

Selecting a model

!!! note "Model names and providers."

text
We support most models using [`litellm`](https://github.com/BerriAI/litellm).
You can find a list of their supported models [here](https://docs.litellm.ai/docs/providers).
Please always include the provider in the model name, e.g., `anthropic/claude-...`.
  • Recommended: mini-extra config setup (should be run the first time you run mini) can set the default model for you
  • All command line interfaces allow you to set the model name with -m or --model.
  • In addition, you can set the default model with mini-extra config set MSWEA_MODEL_NAME <model-name>, by editing the global config file (shortcut: mini-extra config edit), or by setting the MSWEA_MODEL_NAME environment variable.
  • You can also set your model in a config file (key model_name under model).
  • If you want to use local models, please check this guide.

!!! note "Popular models"

text
Here's a few examples of popular models:

```
anthropic/claude-opus-4-6-20260205
openai/gpt-5.4
openai/gpt-5.4-mini
gemini/gemini-2.5-pro
deepseek/deepseek-chat
```

??? note "List of all supported models"

    Here's a list of all model names supported by `litellm` as of Aug 29th 2025.
    For even more recent models, check the [`model_prices_and_context_window.json` file from litellm](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json).

    ```
    --8<-- "docs/data/all_models.txt"
    ```

To find the corresponding API key, check the previous section.

Extra model settings

To configure reasoning efforts or similar settings, you need to edit the agent config file.
In newer versions, the location of the config file is printed when you run mini ("agent config" in the output).

Here's a few general examples:

=== "Temperature"

text
`litellm` allows to set model-specific settings with the `model_kwargs` key:

```yaml
model:
  model_name: "anthropic/claude-sonnet-4-5-20250929"
    model_kwargs:
      temperature: 0.0
```

Note that temperature isn't supported by all models.

=== "GPT-5 reasoning effort (Chat Completions API)"

text
`litellm` allows to set model-specific settings with the `model_kwargs` key:

```yaml
model:
  model_name: "openai/gpt-5-mini"
  model_kwargs:
    drop_params: true
    reasoning_effort: "high"
    verbosity: "medium"
```

Here, `drop_params` is used to drop any parameters that are not supported by the model.

=== "GPT-5 with Responses API"

text
For OpenAI models that support the Responses API, you can use the `litellm_response_toolcall` model class:

```yaml
model:
  model_class: "litellm_response_toolcall"
  model_name: "openai/gpt-5-mini"
  model_kwargs:
    drop_params: true
    reasoning:
      effort: "high"
```

=== "OpenRouter"

text
This example explicitly sets the model class to `openrouter` (see the next section for more details).
It also explicitly sets the providers to disable switching between them (this is useful if you need
very consistent cost behavior, e.g., for benchmarking, but it's not recommended if you're just interested
in getting low latency and good prices).

```yaml
model:
    model_name: "moonshotai/kimi-k2-0905"
    model_class: "openrouter"
    model_kwargs:
        temperature: 0.0
        provider:
          allow_fallbacks: false
          only: ["Moonshot AI"]
```

=== "Local models"

text
Using `litellm` with local models:

```yaml
model:
  model_name: "my-local-model"
  model_kwargs:
    custom_llm_provider: "openai"
    api_base: "https://..."
    ...
```

See [this guide](local_models.md) for more details on local models.
In particular, you need to configure token costs for local models.

Here are more examples of how to configure specific models:

=== "Gemini 3 (Openrouter)"

text
```yaml
model:
    model_name: "google/gemini-3-pro-preview"
    model_class: openrouter
    model_kwargs:
        temperature: 0.0
```

=== "GPT 5.1 medium (Portkey)"

text
```yaml
model:
    model_name: "@openai/gpt-5.1"
    model_class: portkey
    model_kwargs:
        reasoning_effort: "medium"
        verbosity: "medium"
```

=== "Claude Haiku 4.5"

text
```yaml
model:
    model_name: "anthropic/claude-haiku-4-5-20251001"
    model_kwargs:
        temperature: 0.0
```

=== "GPT 5 mini (Portkey)"

text
```yaml
model:
    model_name: "@openai/gpt-5-mini"
    model_class: portkey
```

=== "Deepseek"

text
```yaml
model:
    model_name: "deepseek/deepseek-reasoner"
    model_kwargs:
        temperature: 0.0
```

=== "Minimax (Openrouter)"

text
```yaml
model:
    model_name: "minimax/minimax-m2"
    model_class: openrouter
    model_kwargs:
        temperature: 0.0
```

Model classes

We support the various models through different backends.
By default (if you only specify the model name), we pick the best backend for you.
This will almost always default to litellm (with Anthropic models being a special case as they need to have explicit cache breakpoint handling).

However, there are a few other backends that you can use and specify with the --model-class flag or the
model.model_class key in the agent config file (see previous section).

For example:

=== "Openrouter model"

text
```bash
mini -m "moonshotai/kimi-k2-0905" --model-class openrouter
```

**Alternatively:** In the agent config file:

```yaml
model:
    model_name: "moonshotai/kimi-k2-0905"
    model_class: openrouter
```

=== "Portkey model"

text
```bash
mini -m "claude-sonnet-4-5-20250929" --model-class portkey
```

**Alternatively:** In the agent config file:
```yaml
model:
    model_name: "claude-sonnet-4-5-20250929"
    model_class: portkey
```
  • litellm (LitellmModel) - Default and recommended. Supports most models through litellm. Works with OpenAI, Anthropic, Google, and many other providers. Anthropic models automatically get cache control settings when the model name contains "anthropic", "claude", "sonnet", or "opus".

  • litellm_response (LitellmResponseModel) - Specialized version of LitellmModel that uses OpenAI's Responses API with native tool calling. Useful for models like GPT-5 and required for models like GPT-5-codex. Maintains conversation state across turns.

  • openrouter (OpenRouterModel) - Direct integration with OpenRouter API for accessing various models through a single endpoint.

  • portkey (PortkeyModel) - Integration with Portkey for accessing various models with enhanced observability, caching, and routing features. Note that this still uses litellm to calculate costs.

On top, there's a few more exotic model classes that you can use:

  • deterministic (DeterministicModel) - Returns predefined responses for testing and development purposes.
  • minisweagent.models.extra.roulette.RouletteModel and minisweagent.models.extra.roulette.InterleavingModel (RouletteModel and InterleavingModel) - Randomly selects or interleaves multiple configured models for each query. See this blog post for more details.

As with the last two, you can also specify any import path to your own custom model class (even if it is not yet part of the mini-SWE-agent package).

--8<-- "docs/_footer.md"


File: docs/models/troubleshooting.md

Model trouble shooting

This section has examples of common error messages and how to fix them.

Litellm

litellm is the default model class and is used to support most models.

Invalid API key

json
AuthenticationError: litellm.AuthenticationError: geminiException - {
  "error": {
    "code": 400,
    "message": "API key not valid. Please pass a valid API key.",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "API_KEY_INVALID",
        "domain": "googleapis.com",
        "metadata": {
          "service": "generativelanguage.googleapis.com"
        }
      },
      {
        "@type": "type.googleapis.com/google.rpc.LocalizedMessage",
        "locale": "en-US",
        "message": "API key not valid. Please pass a valid API key."
      }
    ]
  }
}
 You can permanently set your API key with `mini-extra config set KEY VALUE`.

Double check your API key and make sure it is correct.
You can take a look at all your API keys with mini-extra config edit.

"Weird" authentication error

If you fail to authenticate but don't see the previous error message,
it might be that you forgot to include the provider in the model name.

For example, this:

text
File "/Users/.../.virtualenvs/openai/lib/python3.12/site-packages/google/auth/_default.py", line 685, in default
    raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see
https://cloud.google.com/docs/authentication/external/set-up-adc for more information.

happens if you forgot to prefix your gemini model with gemini/.

Error during cost calculation

text
Exception: This model isn't mapped yet. model=together_ai/qwen/qwen3-coder-480b-a35b-instruct-fp8, custom_llm_provider=together_ai.
Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json.

litellm doesn't know about the cost of your model.
Take a look at the model registry section of the local models guide to add it.

Another common mistake is to not include any or the correct provider in the model name (e.g., gemini-2.0-flash instead of gemini/gemini-2.0-flash).

Temperature not supported

Some models (like o1, o3, GPT-5 etc.) do not support temperature. The default config no longer specifies a temperature value, so this should work out of the box now.

Portkey

Error during cost calculation

We use litellm to calculate costs for Portkey models because Portkey doesn't seem to provide per-request cost information without
very inconvenient APIs.

This can lead to errors likethis:

text
File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/minisweagent/models/portkey_model.py", line 85, in query
    cost = litellm.cost_calculator.completion_cost(response)
  File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/litellm/cost_calculator.py", line 973, in completion_cost
    raise e
  File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/litellm/cost_calculator.py", line 966, in completion_cost
    raise e
  File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/litellm/cost_calculator.py", line 928, in completion_cost
    ) = cost_per_token(
  File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/litellm/cost_calculator.py", line 218, in cost_per_token
    _, custom_llm_provider, _, _ = litellm.get_llm_provider(model=model)
  File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/litellm/litellm_core_utils/get_llm_provider_logic.py", line 395, in get_llm_provider
    raise e
  File "/opt/miniconda3/envs/clash/lib/python3.10/site-packages/litellm/litellm_core_utils/get_llm_provider_logic.py", line 372, in get_llm_provider
    raise litellm.exceptions.BadRequestError(  # type: ignore
litellm.exceptions.BadRequestError: litellm.BadRequestError: LLM Provider NOT provided. Pass in the LLM provider you are trying to call. You passed model=grok-code-fast-1
 Pass model as E.g. For 'Huggingface' inference endpoints pass in `completion(model='huggingface/starcoder',..)` Learn more: https://docs.litellm.ai/docs/providers

In this case, the issue is simply that the portkey model name doesn't match the litellm model name (and very specifically here
doesn't include the provider).

To fix this, you can manually set the litellm model name to the portkey model name with the litellm_model_name_override key.
For example:

yaml
model:
  model_name: "grok-code-fast-1"  # the portkey model name
  model_class: "portkey"  # make sure to use the portkey model class
  litellm_model_name_override: "xai/grok-code-fast-1"  # the litellm model name for cost information
  ...

--8<-- "docs/_footer.md"