Zero deps · Four hooks · One iterator
The loop is the product.¶
looplet is a for-loop you own for LLM tool-calling agents. Yield
every step, intercept every tool call, redact every prompt, eval every
trajectory. No graph DSL, no agent runtime, no hidden state. Works with
any OpenAI-compatible endpoint or Anthropic directly.
289ms
Cold import
0
Runtime deps
4
Hook protocols
1,062
Tests, ~1s

How it works¶
flowchart LR
subgraph Loop["composable_loop()"]
direction LR
P[pre_prompt] --> L[llm.generate]
L --> D[pre_dispatch]
D --> T[tool.execute]
T --> R[post_dispatch]
R --> C{check_done}
C -- no --> P
C -- yes --> Y([yield Step])
end
Y --> Caller[Your for-loop]
Caller -. "stop / log / score" .-> Loop
classDef hook fill:#EEF2FF,stroke:#4F46E5,stroke-width:1.5px,color:#1E1B4B
class P,D,R,C hook
Four hook methods on any Python object. Implement only the ones you
need. The loop uses hasattr — no base class, no registration.
Why looplet?¶
-
Fast to start, fast to run
289 ms cold import. Zero runtime dependencies.
pip installstays snappy on serverless and short-lived scripts. -
Composable by Protocol
Four
@runtime_checkablehook methods. Any object implementing one or more is a hook. No base classes, no registration. -
Observable by default
step.pretty(),ProvenanceSink, andeval_*all read the sameStepdataclass. One artifact, three uses. -
Safe by design
redact=scrubs PII before the provider sees it and before the trace is written. No wrapping-order footguns. -
Compose agents as tools
Any looplet agent is a function that returns a result. Wrap it in a
ToolSpecand plug it into the next agent. -
Debugging is evaluation
What you do while debugging (
print(step.pretty())) is a trajectory. Evals are pytest-style functions over the same data.
See the difference¶
for step in composable_loop(
llm=llm, tools=tools, task=task,
hooks=[BudgetCap(10_000), Redactor()],
):
if step.tool_call.tool == "delete":
if not approve(step): # (1)
break
log(step) # (2)
- Intercept any tool call with ordinary Python — no custom graph node needed.
- One
Stepobject is the trace, the eval context, and the checkpoint unit.
Honest benchmarks¶
All numbers regenerate in one command on a fresh Python 3.11 venv. See Benchmarks for the full methodology.
looplet 289 ms · 0 deps
strands-agents 1,885 ms · 6 deps
LangGraph 2,294 ms · 31 deps
Claude Agent SDK 2,409 ms · 13 deps
Pydantic AI 3,975 ms · 12 deps
Cold-import time, median of 9 fresh subprocess runs. Python 3.11.13, Linux x86_64, PyPI wheels from 2026-04-21.
Start here¶
-
Install. Run. Understand the loop in five minutes.
-
Build an agent with hooks, context management, crash-resume, and approval — in five steps.
-
The four extension points. Recipes for every common pattern.
-
pytest-style scoring over the same trajectory you debug with.
-
Capture every prompt and step to a diff-friendly directory.
-
Ollama, OTel, MCP, cost accounting, checkpoints.
-
Ten sharp edges worth knowing — with the "right way" for each.
-
Cold import and dependency footprint, with the harness.
Extension points at a glance¶
-
pre_promptInject context into the next prompt. Context managers, retrieval-augmented briefings, step-specific guidance.
-
pre_dispatchIntercept a tool call before it runs. Cache hits, permission gates, argument rewriting, approval flows.
-
post_dispatchReact to a tool result. Duplicate-call warnings, error remediation messages, metric collection, streaming events.
-
check_doneReject premature completion. Quality gates, minimum-evidence thresholds, required-tool checks.
Talks and writing¶
- Blog: "The loop is the product" — the design argument behind the library.
- THIRD_PARTY_USERS.md — who is building on looplet.