agentloop
Python SDK for AgentLoop — middleware that turns human corrections into searchable memory for your agent.
- Python 3.9+, sync and async
- One runtime dependency (
httpx), nothing else - Graceful by default — network blips don't break your agent
- Type hints throughout, full dataclass response shapes
Install
pip install agentloop-py
Quick start (sync)
import os
from openai import OpenAI
from agentloop import AgentLoop
loop = AgentLoop(api_key=os.environ["AGENTLOOP_API_KEY"])
openai = OpenAI()
def ask(question: str, user_id: str) -> str:
# 1. Before calling the LLM, pull relevant corrections.
memories = loop.search(question, user_id=user_id, limit=3)
# 2. Inject them into your system prompt.
facts = "\n".join(f"- {m.fact}" for m in memories) if memories else ""
system = "You are a helpful assistant."
if facts:
system += f"\n\nTrusted facts from past corrections:\n{facts}"
# 3. Call the LLM.
resp = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": question},
],
)
answer = resp.choices[0].message.content or ""
# 4. Log the turn for review.
loop.log_turn(question, answer, user_id=user_id)
return answer
That's the whole integration — one call before the LLM, one after. For
a zero-setup drop-in wrapper, install agentloop-py-openai or
agentloop-py-anthropic instead.
Quick start (async)
from agentloop.aio import AsyncAgentLoop
async def ask(question: str, user_id: str) -> str:
async with AsyncAgentLoop(api_key=...) as loop:
memories = await loop.search(question, user_id=user_id)
# ... LLM call ...
await loop.log_turn(question, answer, user_id=user_id)
Use AsyncAgentLoop from agentloop.aio in asyncio code (FastAPI,
aiohttp, etc.). Same API, all methods are coroutines except
feedback_url() which stays sync — no network call, just HMAC.
Configuration
loop = AgentLoop(
api_key="ak_...", # required
base_url="https://...", # default: https://api.getagentloop.io
timeout_s=10.0, # per-request timeout
feedback_signing_secret="...", # only needed for feedback_url()
throw_on_error=False, # see "Graceful failures"
http_client=my_httpx_client, # inject custom httpx.Client
)
Base URL resolution
The base_url argument follows this priority order:
- Explicit
base_urlpassed to the constructor (highest) AGENTLOOP_BASE_URLenvironment variable- Hardcoded hosted-backend URL (fallback)
This lets you point the SDK at a local dev server, a self-hosted
deployment, or a future gateway without code changes — just set
AGENTLOOP_BASE_URL in the environment.
export AGENTLOOP_BASE_URL=http://localhost:8080
python your_app.py # now points at a local dev backend instead of api.getagentloop.io
Four methods
search(query, *, user_id=None, limit=3, tags=None) → list[Memory]
Retrieve corrections before your LLM call. Returns [] on failure
(unless throw_on_error=True).
memories = loop.search("pix limit at night", user_id="u_123", limit=5)
for m in memories:
print(m.fact, m.score, m.tags)
log_turn(question, agent_response, *, user_id=None, session_id=None, signals=None, metadata=None) → LogTurnResponse
Queue a turn for review. Returns a default response on failure (unless
throw_on_error=True).
result = loop.log_turn(
question="What's the Pix limit?",
agent_response="R$5,000",
user_id="u_123",
signals={"thumbs_down": True},
metadata={"latency_ms": 240, "model": "gpt-4o-mini"},
)
if result.was_duplicate:
# Backend deduplicated this turn against an existing pending one.
# The returned turn_id points to the merged doc.
...
annotate(*, question, agent_response, correction, rating, ...) → AnnotateResponse
Create an annotation directly (bypass the review queue). Always throws on failure — silent degradation would hide reviewer work.
result = loop.annotate(
question="What's the Pix limit at night?",
agent_response="R$5,000",
correction="Pix limit between 8pm and 6am is R$1,000.",
rating="incorrect",
root_cause="context",
tags=["pix", "limits"],
reviewer="maria@luma.com.br",
)
feedback_url(question, agent_response, *, user_id="", session_id="") → str
Generate an HMAC-signed URL for the embedded feedback widget. Requires
feedback_signing_secret. Sync on both clients.
url = loop.feedback_url(question, answer, user_id="u_123")
Signatures are byte-identical to the JavaScript SDK, so URLs signed in Python validate on backends that also accept JS-signed URLs.
Graceful failures
By default, search() and log_turn() return empty/default values on
failure. Agent-loop calls sit on the critical path of your agent's
response; a blip shouldn't turn into a 500.
# Hard failures
from agentloop import AgentLoopError
loop = AgentLoop(api_key=..., throw_on_error=True)
try:
memories = loop.search("...")
except AgentLoopError as e:
print(e.status, e.body)
annotate() always raises regardless of this flag.
Context managers
Both clients support context management for clean resource cleanup:
with AgentLoop(api_key=...) as loop:
loop.search("...")
# httpx.Client is closed on exit
async with AsyncAgentLoop(api_key=...) as loop:
await loop.search("...")
# httpx.AsyncClient is closed on exit
License
MIT
Metadata
Release files for agentloop-py 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| agentloop_py-0.2.0.tar.gz | 12.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agentloop_py-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.4 kB
Release files / agentloop_py-0.2.0.tar.gz
| Download URL | agentloop_py-0.2.0.tar.gz |
|---|---|
| Size | 12.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
73d1ad1f599d747bc336dd6e21370be3eda852788ff199618cd45667bd6b2cba
|
|
BLAKE2b-256 checksum How to use checksums |
55fffb528fb9f69ba26cd736687384abae9bf4c10d0e727dce90f112f28942e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Release files / agentloop_py-0.2.0-py3-none-any.whl
| Download URL | agentloop_py-0.2.0-py3-none-any.whl |
|---|---|
| Size | 12.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2b6ebf1929cf0908075f75c24e1dc796f4676afa66a536d2b0d0083b055cb291
|
|
BLAKE2b-256 checksum How to use checksums |
a37888bf1b0e1d0b22dde739903442428421b50f82f2f153fc5676dd25c70df2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.7
|
Security for agentloop-py 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.