Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Minimal AI agent with tool calling and zero dependencies in 60 lines of Python

Agent demo execution example

Code

importjsonimporturllib.requestfromsubprocessimportcheck_output, STDOUT, CalledProcessErrorheaders= {
#"Authorization": f"Bearer SET_YOUR_API_KEY_HERE_IF_YOU_HAVE_ONE","Content-Type": "application/json",
"User-Agent": "Minimal Agent/0.1",
}
defcall_llm(messages, url="https://opencode.ai/zen/v1/chat/completions"): # Set URL herepayload= {
"model": "big-pickle", # Set model here"messages": messages,
"tools": [{
"type": "function",
"function": {
"name": "bash",
"description": "Runs a bash command.",
"parameters": {
"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"],
},
},
}],
}
data=json.dumps(payload).encode("utf-8")
req=urllib.request.Request(url, data=data, headers=headers, method="POST")
withurllib.request.urlopen(req) asresponse:
returnjson.loads(response.read().decode("utf-8"))
defbash(command):
try:
returncheck_output(command, stderr=STDOUT, text=True)
exceptCalledProcessErrorase:
returnf"[ERROR: exit code {e.returncode} for `{command}`]\n"+e.outputmessages= [{"role": "system", "content": "You are a helpful assistant."}]
whileTrue:
prompt=input(">> ")
messages.append({"role": "user", "content": prompt})
whileTrue:
response=call_llm(messages)
msg=response["choices"][0]["message"]
messages.append(msg)
tool_calls=msg.get("tool_calls")
ifnottool_calls:
print(f"Reply:\n{msg.get('content', '')}")
breakfortool_callintool_calls:
fn=tool_call["function"]["name"]
tool_args=json.loads(tool_call["function"]["arguments"])
tool_call_id=tool_call["id"]
command= ["bash", "-c", tool_args["command"]]
print(f"[Tool: {fn}] {json.dumps(tool_args)}")
result=bash(command) iffn=="bash"elsef"Unknown tool {fn}"print(result)
messages.append({
"role": "tool",
"tool_call_id": tool_call_id,
"content": result,
})

Installation

git clone https://github.com/99991/MinimalAgent.git
cd MinimalAgent
python3 agent.py

By default, the big-pickle model (GLM-4.6) provided by OpenCode is used, which might be overloaded.

If you have your own OpenAI-compatible API that you want to use, change the API key, URL and model in the code. You can also use a self-hosted model:

Using a local model with llama.cpp's llama serve

  1. Install llama.cpp'sllama app:
curl -LsSf https://llama.app/install.sh | sh
  1. Serve a model, e.g. Qwen3.5-4B:
llama serve --no-mmproj -hf unsloth/Qwen3.5-4B-GGUF:Q5_K_M
  • This model is very small (only about 4GB of VRAM) and has only been chosen due to its accessibility. See llama.app and HuggingFace for more models. Qwen3.6-27B is pretty good if you have the (V)RAM, but might get stuck in loops if quantized too heavily (gets better with Q5 and up).
  1. Change the URL in the call_llm function to the llama-server URL:
defcall_llm(messages, url="http://127.0.0.1:8080/v1/chat/completions"):
  1. Run python agent.py

Explanation

At its core, AI agents are very simple. All they do is:

  1. Append the user's prompt to the current context
  2. Query an LLM for tool calls and text replies
  3. Run the tools (bash in our case)
  4. Append the tool outputs and text reply to the context
  5. Continue at 1.

Since LLMs are very proficient in using bash, they don't necessarily require any other tools. They can just use bash to do whatever they need, e.g. edit files using sed or make HTTP requests using curl.

About

Minimal AI agent with tool calling and zero dependencies in 60 lines of Python

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages