@raindrop-ai/openai-managed-agents
v0.0.2
Published
Raindrop tracing for the OpenAI Agents API
Maintainers
Keywords
Readme
Raindrop for the OpenAI Agents API
Capture the managed Agents API (openai.beta.agents.sessions) in Raindrop.
This package uses openai, the OpenAI TypeScript SDK. For the separate,
in-process @openai/agents framework, use @raindrop-ai/openai-agents.
Requires Node.js 22+ and OpenAI SDK 7.15.x–7.x.
pnpm add @raindrop-ai/openai-managed-agents openaiQuick start
import OpenAI from "openai";
import { createRaindropOpenAIManagedAgents } from "@raindrop-ai/openai-managed-agents";
const raindrop = createRaindropOpenAIManagedAgents({
writeKey: process.env.RAINDROP_WRITE_KEY,
userId: "user_123",
properties: { feature: "world_builder" },
});
const client = raindrop.wrap(new OpenAI());
try {
const events = await client.beta.agents.sessions.create({
agent: { model: "gpt-6-astra", instructions: "Help build a simulation World." },
environment: { type: "openai_hosted" },
input: "Describe the files needed for a simulation World.",
stream: true,
});
try {
for await (const event of events) {
if (event.type === "agent.session.turn.output_text.delta") process.stdout.write(event.delta);
if (event.type === "agent.session.idle") break;
}
} finally {
events.controller.abort();
}
} finally {
await raindrop.shutdown();
}Use an OpenAI application key with the Agents API permissions.
No OpenTelemetry setup is required. Missing or blank Raindrop keys disable cloud
shipping. Set localWorkshopUrl: false to disable local Workshop mirroring.
Capture
- One partial event per turn, completed when the native turn reaches a terminal state.
- Session model, user input, completed final answer, per-turn usage, and provider attribution.
- A root turn span and child command, function, MCP, search, and subagent-control tool spans.
- Session and turn IDs in properties. By default, the session ID is the conversation ID.
- Original OpenAI results, events, request options, abort controls, and response helpers.
The wrapper observes sessions.create, sessions.retrieve,
sessions.events.create, sessions.events.stream, and sessions.stream.
Use raindrop.wrap(client, { userId, convoId, eventName, properties }) for context
on sessions created or retrieved through that wrapper. Use a single wrapper for
each native client. Retrieve an existing session before following its events to
capture its model. Reading raw bodies with asResponse() bypasses capture.
Reconnecting runners and stored history
For a runner that reconnects streams, use the public typed handler with an unwrapped native client. Keep one Raindrop client for the runner's lifetime:
import type { Turn } from "openai/resources/beta/agents/sessions/turns";
raindrop.handler.onSession(session);
raindrop.handler.onInput(session.id, userInput); // after successful submission
// Snapshot turn statuses before recovering their items.
const recoveredTurns: Turn[] = [];
for await (const turn of client.beta.agents.sessions.turns.list(session.id, { order: "asc" })) {
recoveredTurns.push(turn);
}
for await (const item of client.beta.agents.sessions.items.list(session.id, { order: "asc" })) {
raindrop.handler.onItem(session.id, item);
}
for (const turn of recoveredTurns) raindrop.handler.onTurn(turn);
for await (const event of events) raindrop.handler.onEvent(event);
await raindrop.flush();
// After all streams/recovery work are stopped:
raindrop.handler.forgetSession(session.id);
await raindrop.shutdown();Open the stream before recovery so it can buffer live updates. Read and buffer turn statuses first, recover items next, then pass the buffered turns to the handler. A turn completed after the snapshot closes from its buffered live terminal event. Process callbacks serially during recovery and consumption.
onInputEvents(sessionId, events) records accepted message/tool-result submissions.
Repeated terminal turns and tool receipts are deduplicated within this client.
Turn deduplication retains the latest 10,000 completed turns. Across process
restarts, provide a stable eventId: (turnId) => ... and replay items before turns.
No session or item listing is intercepted automatically.
The wrapper closes unfinished captures when the last iterator for a session
exits, including early exit and transport failure. This marks capture interruption; it does not
cancel the backend turn. Session model and context remain available for later
streams; the previous input is cleared. Metadata retains the latest 10,000 idle
sessions plus sessions with active turns or streams. Call forgetSession when
the session is no longer needed. Use the callback path when an unfinished turn
must survive a reconnection.
Options and enrichment
Options include writeKey, endpoint, projectId, userId, convoId,
eventName, properties, appGit, debug, localWorkshopUrl,
maxTextFieldChars, eventId(turnId), and redact(text).
Text uses the shared core bounds. redact applies to captured prompts, answers,
tool payloads, and errors. Caller-supplied properties/attachments are the caller's
responsibility.
events.patch, events.finish, events.addAttachments, events.setProperties,
users.identify, and signals.track expose the shared core enrichment API.
flush() ships current buffers; shutdown() also closes unfinished captures.
Limits
The service does not expose individual inference requests. Captures represent
turns, rather than each hidden model call. Usage comes only from Turn.usage;
missing usage stays missing. Session-wide cumulative counters are never used as
turn usage. Usage is best effort and later revisions after the first terminal
receipt are not applied.
Span timing reflects observed lifecycle events, including recovery; native turn
timestamps are recorded as openai.turn.* attributes. Command duration is available
in the native item. Image contents, reasoning text, intermediate commentary,
agent-to-agent messages, and streaming text deltas are not automatically
captured. Final text is read from completed final-answer items. Subagent turns
are grouped by session and identified by subagent ID; no cross-turn parent
hierarchy is inferred. Coordinator model identity is available from the session
configuration. Subagent model and inherited coordinator input stay absent unless
their own input is recorded.
See RELEASING.md for first-publication and verification steps. See the integration docs for configuration details.
