Skip to content
v0.1.0agentling is now on PyPI

The agent framework you can read in one sitting

agentling is a tiny async framework for reliable, observable, tool-using agents: a clean ReAct loop, typed memory, streaming events, recoverable failures, and progressive-disclosure skills, in around 800 lines of Python.

Get started

~800

lines of source

2

runtime dependencies

100%

typed, mypy checked

1

loop for everything

Why agentling

Everything is a thin layer on one readable loop

An agent is a loop that turns a model, some tools, and a memory of what happened into more actions, until it has an answer. agentling keeps that loop legible and layers everything else on top.

Async first

The loop, tools, and model calls are all async. Tool calls in a single step run concurrently by default.

One code path

Blocking and streaming share the exact same loop. There is a single async generator; blocking mode just drains it.

Typed memory

A run is a list of typed steps that serialize to JSON, so persistence, replay, and multi-turn continuation come for free.

Streaming events

Five frozen event types narrate every run: text deltas, tool calls, results, recorded steps, and the final answer.

Self-healing

A tool that raises becomes an observation the model can recover from, not a crash. Stuck loops get a nudge.

Progressive skills

Drop a SKILL.md folder in and the model sees only its name until it decides to load it. Big skill libraries stay cheap.

The loop

One iteration, one step

Each step streams a model turn, runs the tools it asked for, records the outcome, and checks whether the run is done. Blocking and streaming, persistence and resume, skills and self-healing all hang off this one generator.

  1. 1Render the promptTyped memory becomes model messages.
  2. 2Stream the model turnText deltas surface as they arrive.
  3. 3Run the tool callsConcurrently, with schema validation.
  4. 4Record the stepUsage, duration, and results, all typed.
  5. 5Check for an answerfinal_answer, plain text, or step limit.
import asyncio
 
from agentling import Agent, OpenAIModel, tool
 
 
@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city.
 
    Args:
        city: The city to look up.
    """
    return f"It is 22C and sunny in {city}."
 
 
async def main() -> None:
    agent = Agent(model=OpenAIModel("gpt-4o-mini"), tools=[get_weather])
    print(await agent.run("What's the weather in Paris?"))
 
 
asyncio.run(main())

Observability

Every run narrates itself

Five frozen event types describe everything an agent does. Feed them to a terminal, a UI, a logger, or a metrics store; the stream and the durable memory can never disagree.

TextDeltaa chunk of streamed textToolCallEventa tool is about to runToolResultEventa tool finishedStepEventa step hit memoryFinalEventthe run is done

Read the source. All of it. Tonight.

No metaclasses, no plugin registry, no DSL. Install it, read the loop, and know exactly what your agent will do.