Skip to main content

Drop-in OpenAI SDK wrapper for AgentLoop — adds memory retrieval and turn logging to chat.completions.create calls. Supports streaming.

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agentloop_py_openai-0.2.2.tar.gz (17.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agentloop_py_openai-0.2.2-py3-none-any.whl (16.6 kB view details)

Uploaded Python 3

File details

Details for the file agentloop_py_openai-0.2.2.tar.gz.

File metadata

  • Download URL: agentloop_py_openai-0.2.2.tar.gz
  • Upload date:
  • Size: 17.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for agentloop_py_openai-0.2.2.tar.gz
Algorithm Hash digest
SHA256 3712a44ad6d86b2dd442967ad5d1d28cd9e8b23f51f001f47ec97e7cf57e7247
MD5 d9cd204fe39ce0598f25c56c429223a3
BLAKE2b-256 dacabdf391625fc56e28e00d6b8c5994027d8681c38ebe256d2d1614fa68dc4f

See more details on using hashes here.

File details

Details for the file agentloop_py_openai-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for agentloop_py_openai-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5966db7cf3d8898b64b994ef8d5221da6d2caeebb38f56cc234ea45bb9f68385
MD5 06d518392f8c23610f61d18f9776fd1d
BLAKE2b-256 1ca5d643857f814e7b5f595e8d1f6ad014a394fde5e876b0b449e39d686fd260

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page