Skip to main content

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:

  1. Extracts the last user message as the query
  2. Calls loop.search(query) — pulls any relevant corrections
  3. Injects them into your system prompt (or creates one if absent)
  4. Calls OpenAI with the augmented messages
  5. 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_id to 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, set search_user_id to 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)

Source distribution for agentloop-py-openai 0.3.0
File Size Uploaded Provenance
agentloop_py_openai-0.3.0.tar.gz 17.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for agentloop-py-openai 0.3.0
File Interpreter ABI Platform
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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page