agentloop-py-openai
Drop-in wrapper that adds AgentLoop memory
retrieval and turn logging to every openai.chat.completions.create
call.
from openai import OpenAI
from agentloop import AgentLoop
from agentloop_openai import wrap_openai
openai = wrap_openai(
OpenAI(),
loop=AgentLoop(api_key="ak_..."),
)
# Use exactly like the normal OpenAI SDK.
# Memory search fires before; log_turn fires after.
resp = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "What's the Pix limit at night?"}],
)
That's the whole integration.
What happens under the hood
For every chat.completions.create call:
- Extracts the last user message as the query
- Calls
loop.search(query)— pulls any relevant corrections - Injects them into your system prompt (or creates one if absent)
- Calls OpenAI with the augmented messages
- Calls
loop.log_turn(question, answer)with the result
If either AgentLoop call fails, your OpenAI call still succeeds.
Install
pip install agentloop-py agentloop-py-openai openai
Per-call options
Pass an agentloop kwarg alongside your normal OpenAI params. The
wrapper strips it before forwarding (OpenAI rejects unknown kwargs).
resp = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[...],
agentloop={
"user_id": "u_123", # tag the logged turn (per-user analytics)
"search_user_id": "u_123", # OPTIONAL: scope memory retrieval to this user
"session_id": "sess_abc", # passed to log_turn
"signals": {"thumbs_down": True}, # merged with auto-detected
"metadata": {"latency_budget_ms": 500}, # stored with the turn
"skip": False, # True = bypass AgentLoop entirely
"search": False, # skip only retrieval (still logs)
# or "search": {"limit": 5, "tags": ["pix"]}
},
)
What user_id does (changed in v0.2.2)
user_id tags the logged turn for per-user dashboard filtering. It does
not filter memory retrieval — search returns the full org-wide
memory corpus by default, regardless of which user this call is for.
That's almost always what you want: any correction your team has ever
made should be available to inform the next response.
If you have a specific reason to want per-user retrieval (e.g. a
personal-assistant agent where each end-user has their own preference
history), set search_user_id explicitly:
agentloop={
"user_id": "u_123", # tag the log
"search_user_id": "u_123", # opt-in: scope retrieval too
}
Migration note: Prior to v0.2.2, the wrapper silently forwarded
user_idto search as well, which suppressed retrieval of org-wide corrections. The fix is non-breaking for the default case. If you previously relied on per-user retrieval, setsearch_user_idto preserve that behavior.
You can also pass a typed PerCallOptions instance if you prefer:
from agentloop_openai import PerCallOptions
resp = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[...],
agentloop=PerCallOptions(user_id="u_123", signals={"thumbs_down": True}),
)
Configuration (passed at wrap time)
openai = wrap_openai(
OpenAI(),
loop=loop,
# Custom memory injection. Default: append to system prompt.
inject_memories=lambda memories, messages: [...],
# Auto-detect signals from the response before log_turn.
detect_signals=lambda question, answer, memories: {
"agent_punted": "not sure" in answer.lower(),
"factual_claim": "$" in answer or "%" in answer,
},
# Max memories per call. Default 3.
search_limit=3,
# Apply these tags to every memory search.
search_tags=["production"],
# Only log turns when at least one signal fired. Default False.
only_log_when_signaled=False,
)
Low-level API
For callers who want explicit control:
from agentloop_openai import ask_with_agentloop, PerCallOptions
from agentloop_openai._ask import WrapOptions
resp = ask_with_agentloop(
openai, # raw, unwrapped OpenAI client
messages=[{"role": "user", "content": question}],
per_call=PerCallOptions(user_id="u_123"),
config=WrapOptions(loop=loop),
model="gpt-4o-mini", # forwarded to OpenAI
temperature=0.2, # forwarded to OpenAI
)
Not mutated
wrap_openai(client) returns a distinct wrapper. Your original client
stays unwrapped and usable.
raw = OpenAI()
wrapped = wrap_openai(raw, loop=loop)
raw.chat.completions.create(...) # no AgentLoop hooks
wrapped.chat.completions.create(...) # with AgentLoop hooks
Streaming
Not supported in v0.1. Streaming intercepts are planned for a later
release (requires buffering assistant text to call log_turn after the
stream closes). For now, if you pass stream=True, call AgentLoop
methods directly rather than using the wrapper.
License
MIT
Metadata
Release files for agentloop-py-openai 0.3.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_openai-0.3.0.tar.gz | 17.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| agentloop_py_openai-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 33.9 kB
Release files / agentloop_py_openai-0.3.0.tar.gz
| Download URL | agentloop_py_openai-0.3.0.tar.gz |
|---|---|
| Size | 17.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9a8b31561917c972d99a830e72966ad35dfa443f6678e598b88151d3daa7afe6
|
|
BLAKE2b-256 checksum How to use checksums |
3b3f789027cb994d290f62ceb4997de2b2135f73f1fc03474c0524cb899028d0
|
| 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_openai-0.3.0-py3-none-any.whl
| Download URL | agentloop_py_openai-0.3.0-py3-none-any.whl |
|---|---|
| Size | 16.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e068fc5689b48611d3e6af77df358343ed0f6ef44925041f6f81f621acda64ef
|
|
BLAKE2b-256 checksum How to use checksums |
7cdf2e0fbb1093c0ab80632912abf59eecdd4c38a38e4304cca194bba54308f2
|
| 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-openai 0.3.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.