Python 3.11 or newer
Looplet¶
A Python loop for agents that call tools.
Choose your model, tools, task, and limits. Looplet runs tools and yields each step to your code. It also provides context management for long runs. Hooks let you build prompts, check calls before tools run, and inspect results afterward. Add these controls when you need them. Your code still controls the loop.
Run
Use normal Python functions as tools.
Inspect
Read the call, result, and error in each step.
Stop
Stop your iteration before the next tool call.
Extend
Add only the optional features that you need.
Why use Looplet instead of a short loop?¶
A short loop is enough if it already meets your needs. Use Looplet when your agent also needs these features:
- Model choice and retries: Use OpenAI, Anthropic, or connect another model. Add retries or fallback models to synchronous model calls.
- Python tools: Use normal Python functions as tools. Describe accepted inputs. Add argument checks before a tool runs.
- Context management: Track context limits. Shorten old history with summaries or truncation. Remove large tool results from later prompts.
- Prompt and tool hooks: Add context or build a custom prompt. Check or change calls before tools run. Inspect or change results afterward.
- Run controls: Set step and tool-call limits. Detect repeated actions or cancel a run.
- Async and streaming: Run async model calls and tools. Read model text as it arrives with a streaming backend.
- Saved runs and replay: Save prompts, responses, results, and stop reasons. Reuse saved model responses to test changed tools. Tool effects can still change.
- Tests and comparisons: Check files or records that the agent produced. Compare tool changes with saved responses. Compare model changes with new runs.
- Checkpoints: Save loop state and continue a later run. Checkpoints do not undo tool effects.
- Reusable agents: Keep tools, prompts, and settings in Python or an agent directory. Share that setup across projects.
- Skills and child agents: Load extra task instructions when needed. Delegate part of a task to another agent.
- Command line: Create, run, inspect, and test agents from your shell.
- Other processes: Connect tools and hooks running in other processes. Share state and model access across process boundaries.
These features use the same loop. You can reuse them across agents instead of writing separate control code for each one. The loop still yields steps, so your code can inspect each result and stop before the next call.
Start with one loop¶
Install the fixed release for the examples and fixes in these guides. Run it inside a virtual environment:
This non-editable package needs no Git installation or local checkout.
Release 0.4.1 includes the safety fixes missing from 0.4.0.
Pin the version and artifact hashes in your dependency lockfile for deployment.
See the Quickstart for environment setup and the same agent's tests.
This example uses fixed responses and does not contact a model service.
Run the included example without creating a file:
It runs the tools and checks the resulting answer.
To own the code, use the same loop below.
validate=True checks top-level argument types, nullability, and enum choices before tools run.
Nested data and other constraints remain tool-owned.
from looplet import MockLLMBackend, minimal_preset
def lookup_owner(service: str) -> dict:
"""Find the team that owns a service."""
owners = {"payments": "fintech-platform", "search": "discovery"}
return {"service": service, "owner": owners.get(service)}
def done(service: str, owner: str, summary: str = "") -> dict:
"""Finish with the service, its owner, and an optional explanation."""
return {"service": service, "owner": owner, "summary": summary}
llm = MockLLMBackend([
'{"tool":"lookup_owner","args":{"service":"payments"}}',
'{"tool":"done","args":{"service":"payments","owner":"fintech-platform","summary":"The payments owner is fintech-platform."}}',
], cycle=False)
with minimal_preset(tools=[lookup_owner, done], max_steps=2, validate=True) as run:
run.config.use_native_tools = False
result = run.run_result(llm, task={"goal": "Find the payments owner, then finish."})
print(result.output)
print(result.completed, result.termination_reason)
result.output contains the answer, and result.steps contains each tool call and result.
The with block closes this run and its owned resources.
Create a fresh preset for each task.
Use step-by-step iteration to inspect or stop between calls.
The example selects the JSON-text protocol for its fixed responses.
Real models use native tool calls by default.
cycle=False rejects unexpected extra model calls instead of repeating the script.
The Quickstart explains each field and shows early exit.
See Install to configure a real model.
Add only what you need¶
Hooks
Build prompts, check calls before tools run, and inspect results afterward.
Saved runs
Save prompts, responses, steps, and stop reasons as files.
Tests
Read the result that the agent produced and check it independently.
Cartridges
Put tools, prompts, and configuration in a directory for review or distribution.
These features use the same loop. They are not required for the first example.
Hooks | Capture and replay | Tests and graders | Cartridges
Check a tool change¶
Run looplet-proof after installation to check the complete regression example.
The example needs no model key or network. It reuses fixed model responses with changed tool code. A collector reads the report and a grader checks it. Read the example and its limits.
Choose a guide¶
Replace a loop¶
Keep your provider and tools. Replace only the loop and check its behavior before you add other features.
Check a failure¶
Save the run and read the result that the agent produced. Choose fixed responses or new model runs for the change that you need to check.
Find an interface¶
Find commands, Python functions, saved files, and runtime controls.
Use other processes or hosts¶
Protocol adapters can connect tools, hooks, shared state, and model access across processes. Start with the Python loop. Add a process boundary when your deployment needs one.
Study portability | Inspect the cartridge format
Know what each check proves¶
| Evidence | Use it for | Do not claim |
|---|---|---|
Step objects |
Inspect results and stop between calls | Approval before a tool runs or proof that an answer is correct |
| Saved run | Read what the model saw, returned, and called | That saved prompts are safe to publish |
| Replay | Check changed tools or hooks with fixed responses | Better decisions from a prompt or model change |
| Collector and grader | Check a file, record, or service result | Protection from code that can change the grader |
| New model runs | Check prompt, model, schema, or context changes | General performance from one sample |
Completion does not prove that an answer is correct. Replay fixes model responses, not tool effects. Keep protected acceptance checks outside the code that a candidate can change. Run untrusted code in an isolated process or operating system environment.
Capture and replay | Behavioral evals | Saved artifact reference
When Looplet fits¶
Looplet is a good fit when¶
- One model calls tools until the task ends.
- Your team uses Python, Git, and pytest.
- Your code must control when tools run.
- You need saved runs and tests for agent changes.
Choose another tool when¶
- Your main task needs a durable workflow graph.
- You need a complete assistant, not a Python library.
- You need a managed dashboard as your main interface.
- A small loop that you wrote already meets your needs.
Looplet can run inside a workflow engine and export evidence to other systems. It does not replace those systems. The core package has no third-party runtime dependencies. Provider adapters are optional extras.
Read the selection guide | Check the FAQ | Operate a production loop