Cookbook
Remixing & extending mini
- This guide shows how to mix the different components of the
miniagent to create your own custom version. - You might want to first take a look at the control flow of the default agent first
Development setup
Make sure to follow the dev setup instructions in 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:
- What's the control flow you need? Pick an agent class (e.g., simplest example, with human in the loop)
- How should actions be executed? Pick an environment class (e.g., local, or docker)
- How is the LM queried? Pick a model class (e.g., litellm)
- How to invoke the agent? Bind them all together in a run script, possibly reading from a config (e.g., hello world, or
minientry 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
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)
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
from minisweagent.environments.local import LocalEnvironment
agent = DefaultAgent(
LitellmModel(model_name=model_name),
LocalEnvironment(),
)
from minisweagent.environments.docker import DockerEnvironment
agent = DefaultAgent(
LitellmModel(model_name=model_name),
DockerEnvironment(),
)
Agents
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(),
)
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:
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)
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:
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)
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):
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)
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.