npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@agentloop-sdk/openai

v0.1.1

Published

Drop-in OpenAI SDK wrapper for AgentLoop. Adds memory retrieval and turn logging to every chat.completions.create call.

Downloads

252

Readme

@agentloop-sdk/openai

Drop-in wrapper that adds AgentLoop memory retrieval and turn logging to every openai.chat.completions.create call.

import OpenAI from "openai";
import { AgentLoop } from "@agentloop-sdk/core";
import { wrapOpenAI } from "@agentloop-sdk/openai";

const openai = wrapOpenAI(new OpenAI(), {
  loop: new AgentLoop({ apiKey: process.env.AGENTLOOP_API_KEY! }),
});

// Use exactly like the normal OpenAI SDK.
// Memory search fires before; logTurn fires after.
const resp = await 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, the wrapper:

  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.logTurn(question, answer) with the result

If either AgentLoop call fails, your OpenAI call still succeeds. Hooks degrade gracefully — AgentLoop sits on the critical path of your agent's response and a blip shouldn't turn into a 500.

Install

npm install @agentloop-sdk/core @agentloop-sdk/openai openai

All three are required. openai and @agentloop-sdk/core are peer deps so you pick the versions.

Per-call options

Pass an agentloop field alongside your normal OpenAI params. The wrapper strips it before forwarding (OpenAI rejects unknown top-level fields).

const resp = await openai.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [...],
  agentloop: {
    userId: "u_123",                         // scope memory search + logTurn
    sessionId: "sess_abc",                   // passed to logTurn
    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"] }
  },
});

Streaming

Streaming works — chunks yield to the caller in real time while the wrapper buffers the full answer and fires logTurn after the stream closes.

const stream = await openai.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [{ role: "user", content: question }],
  stream: true,
  agentloop: { userId: "u_123" },
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
// logTurn has already fired with the full assembled text.

Early termination (breaking out of the loop, an abort signal) still triggers logTurn with whatever was generated.

Configuration (passed at wrap time)

const openai = wrapOpenAI(new OpenAI(), {
  loop,

  // How to inject memories into messages. Default: append to system
  // prompt with a "Trusted facts from past corrections:" block.
  injectMemories: (memories, messages) => [...],

  // Auto-detect signals from the response before logTurn.
  detectSignals: (question, answer, memories) => ({
    agent_punted: /not sure|contact support/i.test(answer),
    factual_claim: /\$|%|\d+\s*(day|hour|week)/i.test(answer),
  }),

  // Max memories per call. Default 3. Backend caps at 10.
  searchLimit: 3,

  // Apply these tags to every memory search.
  searchTags: ["production"],

  // If true, logTurn fires only when at least one signal triggered.
  // Default false — log every turn so reviewers see baseline behavior.
  onlyLogWhenSignaled: false,
});

Low-level API

For callers who want explicit control (custom streaming, non-chat endpoints, conditional wrapping), askWithAgentLoop is the underlying helper:

import { askWithAgentLoop } from "@agentloop-sdk/openai";

const resp = await askWithAgentLoop(
  openai,                        // a raw, unwrapped OpenAI client
  {
    model: "gpt-4o-mini",
    messages: [{ role: "user", content: question }],
  },
  { userId: "u_123" },           // per-call options
  { loop }                       // wrap-time config
);

The Proxy wrapper is built on top of this — same semantics, more verbose call site.

Not mutated

wrapOpenAI(client) returns a distinct Proxy. Your original client stays unwrapped and usable.

const raw = new OpenAI();
const wrapped = wrapOpenAI(raw, { loop });

await raw.chat.completions.create({...});       // no AgentLoop hooks
await wrapped.chat.completions.create({...});   // with AgentLoop hooks

License

MIT