A tiny, provider-agnostic framework for building tool-using AI agents.
Project description
AgentForge
A tiny, provider-agnostic framework for building tool-using AI agents in Python.
No SDK lock-in, no heavy dependencies (just requests), no magic. One small
Agent class, a @tool decorator, and a clean reason-act loop you can actually
read in one sitting. Works with any OpenAI-compatible endpoint: OpenAI,
OpenRouter, Groq, Together, Mistral, or a local llama.cpp / Ollama server.
from agentforge import Agent, tool
@tool
def add(a: int, b: int) -> int:
"Add two numbers."
return a + b
agent = Agent(model="gpt-4o-mini", tools=[add])
print(agent.run("What is 21 + 21?"))
# -> "21 + 21 equals 42."
Why
Most agent frameworks are huge. If all you want is "call my Python functions from an LLM and loop until done," you shouldn't need 40 dependencies and a graph DSL. AgentForge is ~200 lines of readable code that does exactly that.
- Provider-agnostic — point
base_urlat any OpenAI-compatible API. - Zero ceremony — a function + a docstring becomes a tool. Types are inferred from annotations into JSON schema automatically.
- Transparent loop — the whole reason-act cycle lives in one method you can read and patch.
- Resilient — automatic retry with exponential backoff on 429 / 5xx / network errors.
- Streaming + async — stream the final answer token-by-token, or
awaitthe agent from async code. - Tested offline — the test suite mocks the provider, so it runs with no API key and no network.
Install
pip install agentforge-mini
Or from source:
git clone https://github.com/kangbaxso/agent-forge
cd agent-forge
pip install -e .
Usage
1. Define tools
Any function with a docstring becomes a tool. Parameter types come from annotations:
from agentforge import tool
@tool
def get_weather(city: str) -> dict:
"Get the current weather for a city."
...
2. Build an agent
from agentforge import Agent
agent = Agent(
model="gpt-4o-mini",
tools=[get_weather],
system="You are a concise assistant.",
verbose=True, # log each tool call
max_steps=8, # safety cap on the loop
)
3. Run it
answer = agent.run("What's the weather in Tokyo?")
Stream the answer
for token in agent.stream("Explain async IO in one paragraph."):
print(token, end="", flush=True)
Tool-calling rounds run first (non-streamed); once the model is ready to answer in plain text, that answer streams token-by-token.
Use it from async code
answer = await agent.arun("What's 21 + 21?")
Resilience
The provider retries automatically on 429 and 5xx responses and on network
errors, with exponential backoff. Tune it:
agent = Agent(model="gpt-4o-mini", max_retries=5)
After exhausting retries it raises agentforge.ProviderError.
Point it at any provider
Set two environment variables — that's the whole config:
# OpenAI (default)
export OPENAI_API_KEY=sk-...
# OpenRouter
export OPENAI_BASE_URL=https://openrouter.ai/api/v1
export OPENAI_API_KEY=sk-or-...
# Groq
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
export OPENAI_API_KEY=gsk_...
# Local llama.cpp / Ollama
export OPENAI_BASE_URL=http://localhost:8080/v1
export OPENAI_API_KEY=not-needed
…or pass base_url= / api_key= directly to Agent(...).
Run the example
export OPENAI_API_KEY=sk-...
python examples/quickstart.py
Run the tests
No API key needed — the provider is mocked:
python tests/test_agent.py
# or
python -m pytest tests/ -q
How the loop works
- Send the conversation + your tool schemas to the model.
- If the model asks to call tools, AgentForge runs them locally and feeds the
results back as
role: toolmessages. - Repeat until the model returns a plain answer or
max_stepsis reached.
That's it. The entire loop is in agentforge/agent.py.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentforge_mini-0.2.0.tar.gz.
File metadata
- Download URL: agentforge_mini-0.2.0.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a05333139736b4b3e510ac99a81d307c9a046830731c1b17149622d2bc1c59d0
|
|
| MD5 |
d1ccc91f19d040f3db5a988fd37720a1
|
|
| BLAKE2b-256 |
6e275fb82f872fcc348e71341dfe44ee2b6f9cf121d7dd2aea16f0f6bf57de88
|
File details
Details for the file agentforge_mini-0.2.0-py3-none-any.whl.
File metadata
- Download URL: agentforge_mini-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff46372b61bc1d866eee1317b73d89a9859464fdff1ac96581f00d356dfde791
|
|
| MD5 |
0a6a648d15200c0e5cfdcf88a3df5642
|
|
| BLAKE2b-256 |
b1439249c56e09fd7e5238d6e8f4c8f0a5d5d228b2aa27da567fd4cc7dfb6715
|