Minimal AI agent tutorial
Skip to content
Initializing search
swe-agent/mini-swe-agent
Let's make it more robust
mini-swe-agent
Contribute to this guide
Comments
Let's make it more robust
mini-swe-agent
Contribute to this guide
Comments
Building a minimal AI agent from scratch
for software engineering, terminal use, and more
Authors: Kilian Lieret, Carlos Jimenez, John Yang, Ofir Press.
Contributors: Cesar Garcia, piot
( Contribute to this guide )
So you want to build your own AI agent from scratch? The good news: It's super simple, especially with more recent language models.<br>We won't be using any external packages (other than to query the LM), and our initial minimal agent is only some 60 lines long.
And if you think this is too simplified and can never work in practice: Our mini agent is built exactly the same, and is used for research at Princeton, Stanford, NVIDIA, Anyscale, essentials.ai and more.<br>Using this simple guide you can score up to 74% on SWE-bench verified, only a few percent below highly optimized agents.
Our first prototype in 50 lines¶
Let's get started: From a top level view, an AI agent is just a big loop: You start with a prompt, the agent proposes an action, you execute the action, tell the LM the output, and then repeat.<br>To keep track of what have happend we continue to append to the messages list.
Pseudocode:
messages = [{"role": "user", "content": "Help me fix the ValueError in main.py"}]<br>while True:<br>lm_output = query_lm(messages)<br>print("LM output", output)<br>messages.append({"role": "assistant", "content": lm_output}) # remember what the LM said<br>action = parse_action(lm_output) # separate the action from output<br>print("Action", action)<br>if action == "exit":<br>break<br>output = execute_action(action)<br>print("Output", output)<br>messages.append({"role": "user", "content": output}) # send command output back
What's up with the role field?<br>The role field indicates who sent the message in the conversation. Common roles are:
"user" - Messages from the user/human
"assistant" - Messages from the AI model
"system" - System prompts that set context/instructions
Different LM APIs may have slightly different conventions for how to structure these messages.
So to get this to work, we only need to implement three things:
Querying the LM API (this can get annoying if you want to support all LMs, or want detailed cost information, but is very simple if you already know which model you want)
Parsing the action (parse_action). You don't need this if you use the tool calling functionality of your LM if it supports it, but this is more provider-specific, so we wo'nt cover it in this guide for now (don't worry, the performance should not be impacted by this).
Executing the action (very simple, in our case we will simply execute any action of the LM as a bash-command in the terminal).
Querying the LM¶
Let's start with the first step. Click on the tabs to find the right LM for you.<br>litellm supports most specific LMs, so this is a good default option if your LM is not explicitly mentioned.
OpenAIAnthropicOpenRouterLiteLLMGLM
Install the OpenAI package (docs):<br>pip install openai
Here's the minimal code to query the API:<br>from openai import OpenAI
client = OpenAI(<br>api_key="your-api-key-here"<br>) # or set OPENAI_API_KEY env var
def query_lm(messages):<br>response = client.responses.create(<br>model="gpt-5.1",<br>input=messages<br>return response.output_text
Install the Anthropic package (docs):<br>pip install anthropic
Here's the minimal code to query the API:<br>from anthropic import Anthropic
client = Anthropic(<br>api_key="your-api-key-here"<br>) # or set ANTHROPIC_API_KEY env var
def query_lm(messages):<br>response = client.messages.create(<br>model="claude-sonnet-4.5",<br>max_tokens=4096,<br>messages=messages<br>return response.content[0].text
Install the OpenAI package (OpenRouter docs) - OpenRouter uses OpenAI-compatible API:<br>pip install openai
Here's the minimal code to query the API:<br>from openai import OpenAI
client = OpenAI(<br>base_url="https://openrouter.ai/api/v1",<br>api_key="your-api-key-here"<br>) # or set OPENROUTER_API_KEY env var
def query_lm(messages):<br>response = client.chat.completions.create(<br>model="anthropic/claude-3.5-sonnet", # or any model on OpenRouter<br>messages=messages<br>return response.choices[0].message.content
Install the LiteLLM package (docs) - supports 100+ LLM providers:<br>pip install litellm
Here's the minimal code to query the API:<br>from litellm import completion
def query_lm(messages: list[dict[str, str]]) -> str:<br>response = completion(<br>model="openai/gpt-5.1", # can be any provider + model<br>messages=messages<br>return response.choices[0].message.content
Install the Zhipu AI package (docs):<br>pip install zhipuai
Here's the minimal code to query the API:<br>from zhipuai import ZhipuAI
client = ZhipuAI(<br>api_key="your-api-key-here"<br>) # or set ZHIPUAI_API_KEY env var
def query_lm(messages):<br>response = client.chat.completions.create(<br>model="glm-4-plus",<br>messages=messages<br>return...