mini-swe-agent
1. Panorama
Mini-SWE-Agent: A Minimalist SWE Scaffold
- Mini-SWE-Agent is a minimalist, bash-centric software engineering agent scaffold that maintains core capabilities like code navigation, testing, and iterative refinement.
- It operates as a single-agent loop executing one thought and one bash command per cycle, supporting both repository repair and embodied controller generation.
- Empirical studies show MSWEA achieves competitive resolution rates with strong models while facing challenges such as context degradation and token bloat.
The main structure of MSWEA is like this:

The file structure is :
1 | src/minisweagent/ |
2. __init__.py
__init__.py mainly defines 4 files:
version, Model Protocol,
Environment Protocol and Agent Protocol.
2.1 Version
Current version is 2.4.6 (2026-09-09).
1 | __version__ = "2.4.6" |
2.2 Model Protocol
1 | class Model(Protocol): |
This part defines a LLM protocol.
2.2.1 query
Function Name:
query
Params:
self
messages: list[dict[str, str]]
**kwargs
Return:
dict
Function Description:
Send the conversation history to the LLM, receive the response, parse the bash action to be executed, and return it wrapped in a dict.
e.g
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18message = self.model.query(self.messages)
# self.message example
# [
# {"role": "system", "content": "You are a helpful assistant..."},
# {"role": "user", "content": "Please solve this issue:repair add function"},
# ]
# the returned message like this:
{
"role": "assistant",
"content": "I'll first look at the repository structure.",
"extra": {
"actions": [{"command": "ls -la", "tool_call_id": "call_abc123"}], # parsed bash action
"cost": 0.0123, # cost of this call(dollar)
"timestamp": 1730000000.0,
},
}
2.2.2 format_message
Function Name:
format_message
Params:
self
**kwargs
Return:
dict
Function Description:
Assembles the input fields into a standard message; the default implementation mainly expands multimodal content.
e.g
1
2
3
4
5
6
7
8# assemble system prompt:
self.model.format_message(role="system", content="You are a helpful assistant...")
# return:
{"role": "system", "content": "You are a helpful assistant..."}
# assemble user message:
self.model.format_message(role="user", content="Please solve this issue: ...")
{"role": "user", "content": "Please solve this issue: ..."}
2.2.3 format_observation_messages
Function Name:
format_observation_messages
Params:
self
message: dict
outputs: list[dict]
template_vars: dict | None = None
Return:
list[dict]
Function Description:
Render the command execution result into an observation message, append it back to the conversation history, and let the model see what the previous step produced.
e.g
1
2
3
4
5
6
7
8
9
10
11
12
13# assume the last command is `ls -la`
outputs = [{"output": "file1.py\nfile2.py\n", "returncode": 0, "exception_info": ""}]
# agent calls:
self.model.format_observation_messages(message, outputs, self.get_template_vars())
# return:
[{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "<returncode>0</returncode>\n<output>\nfile1.py\nfile2.py\n</output>",
"extra": {"raw_output": "file1.py\nfile2.py\n", "returncode": 0, "timestamp": 1730000001.0},
}]
2.2.4 get_template_vars
Function Name:
get_template_vars
Params:
self
**kwargs
Return:
dict[str, Any]
Function Description:
Provide the variables needed to render the Jinja2 template (e.g., model name, model_kwargs, etc.).
e.g
1
2
3
4
5
6
7
8
9def get_template_vars(self, **kwargs):
return self.config.model_dump()
# return likes:
{
"model_name": "anthropic/claude-sonnet-4-5-20250929",
"model_kwargs": {"drop_params": True},
...
}These variables will be used to render system/instance template by Agent
2.2.5 serialize
Function Name:
serialize
Params:
self
Return:
dict
Function Description:
Serialize the model config/state for writing to the trajectory file at the end, recording which model was used.
e.g
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# when agent archive, it merges model information into final data
recursive_merge(agent_data, self.model.serialize(), self.env.serialize(), *extra_dicts)
# LitellmModel.serialize() return:
{
"info": {
"config": {
"model": {"model_name": "anthropic/claude-sonnet-4-5-20250929", ...},
"model_type": "minisweagent.models.litellm_model.LitellmModel",
}
}
}
# the information will be written into last_mini_run.traj.json:
# {
# "info": { "model_stats": {...}, "config": {"agent": {...}, "model": {...}, "environment": {...}} },
# "messages": [ ...dialog history... ]
# }
2.3 Environment Protocol
2.3.1 execute
Function Name:
execute
Params:
self
action: dict
cwd: str = “”
Return:
dict[str, Any]
Description:
Actually execute a bash command and return a dict bundling stdout, the exit code, and whether it errored. There’s also a hidden key behavior: if the first line of the output is “COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT”, it raises a
Submittedexception to signal task completion.e.g
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# e.g agent parses action from response of LLM:
action = {"command": "ls -la", "tool_call_id": "call_abc123"}
# agent calls:
outputs = [self.env.execute(action) for action in actions]
# the Agent calls subprocess to run the command actually,
# the return is:
{
"output": "total 8\ndrwxr-xr-x ...\nfile1.py\nfile2.py\n",
"returncode": 0, # 0 == success
"exception_info": "", # empty == no error raised
}
# if command fails:
# 如果命令失败了(比如文件不存在):
{
"output": "ls: cannot access 'nope': No such file or directory\n",
"returncode": 2, # not-0 == failure
"exception_info": "",
}If task finished, it can be detected:
1
2
3
4
5
6
7
8
9# when task finished
echo COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT
# raise submitted
raise Submitted({
"role": "exit",
"content": "",
"extra": {"exit_status": "Submitted", "submission": ""},
})
2.3.2 get_template_vars
Function Name:
get_template_vars
Params:
self
**kwargs
Return:
dict[str, Any]
Description:
Collect environment-related template variables (working directory config, OS info, environment variables, etc.) for the agent to fill in when rendering the system/instance prompts.
e.g.
1
2
3
4
5
6
7
8
9
10
11
12
13# Impelemtation in LocalEnvironment
def get_template_vars(self, **kwargs):
return recursive_merge(self.config.model_dump(), platform.uname()._asdict(), os.environ, kwargs)
# it returns three types information
{
# ① Env Config
"cwd": "", "env": {...}, "timeout": 30,
# ② OS information(platform.uname())
"system": "Linux", "release": "6.8.0-...", "version": "...", "machine": "x86_64",
# ③ all Environment Variables(os.environ)
"PATH": "/usr/bin:...", "HOME": "/root", ...
}
2.3.1 serialize
Function Name:
serialize
Params:
self
Return:
dict
Description:
Serialize the environment config/type into a dict for writing to the trajectory file at the end, recording which environment it ran in.
e.g.
1
2
3
4
5
6
7
8
9
10
11
12# when agent archives, the information will be merged.
recursive_merge(agent_data, self.model.serialize(), self.env.serialize(), *extra_dicts)
# return of LocalEnvironment.serialize()
{
"info": {
"config": {
"environment": {"cwd": "", "env": {}, "timeout": 30},
"environment_type": "minisweagent.environments.local.LocalEnvironment",
}
}
}
2.3.1
Function Name:
Params:
Return:
Description:
e.g.