TypeScript SDK OpenAI Agents
Attribute OpenAI Agents JS workflows and each agent to stable Solwyn run scopes with the TypeScript SDK's content-free integration.
@solwyn/sdk/openai-agents adds workflow and agent attribution to the OpenAI Agents SDK for
JavaScript. It reads only structural agent names, object identities, model selection, and
lifecycle signals. It never reads prompts, responses, tool arguments, or tool results, and it
creates no budget checks or settlement events itself. Budget admission, usage settlement, and
provider enforcement still happen at the wrapped Solwyn client.
Requirements
- Node.js 22 or later, with
@solwyn/sdk/nodeimported. ConstructingSolwynAgentswithout the Node entry throwsConfigurationError. @solwyn/sdk, the umbrella@openai/agentspackage (optional peer range>=0.20.0 <1),openai >=7.2.0 <8so npm installs a single OpenAI copy, andzod4. Applications onopenai6 must upgrade for this recipe. The entry loads at runtime without Agents installed, but its declarations import the native Agents types.- The recipe is checked with
@openai/agents@0.20.0andopenai@7.36.0. For strict declaration checking with this Agents version, use@types/node22.15.30 or 24, include DOM types, and keep Agents' optional@modelcontextprotocol/clientdependency installed.
The new optional peer can cause npm ERESOLVE when an application already installs an
out-of-range @openai/agents, even if it does not use this integration.
Complete example
Pass the framework's actual OpenAIProvider class and a Solwyn-wrapped OpenAI client. The
integration constructs its delegate with that client and pins HTTP transport. Its default API is
Chat Completions, even when the framework's global default is Responses.
import OpenAI from "openai";
import {
Agent,
OpenAIProvider,
Runner,
setDefaultOpenAIClient,
setOpenAIAPI,
setTracingDisabled,
tool,
} from "@openai/agents";
import { Solwyn } from "@solwyn/sdk/node";
import { SolwynAgents, solwynToolErrorFunction } from "@solwyn/sdk/openai-agents";
const client = new Solwyn(new OpenAI({ maxRetries: 0 }), { apiKey: process.env["SOLWYN_API_KEY"]! });
// The proxy preserves OpenAI at runtime; this cast accommodates OpenAI's private-field types.
setDefaultOpenAIClient(client as unknown as OpenAI);
setOpenAIAPI("chat_completions");
setTracingDisabled(true);
const agents = new SolwynAgents({ client, OpenAIProvider });
const runner = new Runner({
modelProvider: agents.modelProvider,
tracingDisabled: true,
traceIncludeSensitiveData: false,
});
agents.attach(runner);
const lookup = tool({
name: "lookup",
description: "Look up a non-sensitive support category.",
parameters: {
type: "object",
properties: {},
required: [],
additionalProperties: false,
},
errorFunction: solwynToolErrorFunction,
execute: async () => "General support.",
});
const specialist = new Agent({ name: "Specialist", model: "gpt-4.1-mini", tools: [lookup] });
const triageAgent = new Agent({ name: "Triage", model: "gpt-4.1-mini", handoffs: [specialist] });
try {
const result = await agents.run(runner, triageAgent, "Find a support category.", {
workflow: "triage-workflow",
tags: { team: "support" },
runOptions: { maxTurns: 10 },
});
// Use result.finalOutput in your application.
} finally {
await client.close();
}Your OpenAI client reads OPENAI_API_KEY; Solwyn uses SOLWYN_API_KEY for the control plane.
Provider traffic goes directly to OpenAI.
| Export | Purpose |
|---|---|
SolwynAgents | Constructed with client, OpenAIProvider, and optional api ("chat_completions" by default, or "responses"). Exposes modelProvider, attach(runner), run(...), and runStreamed(...). |
SolwynAgentsOptions | Constructor options type: client, OpenAIProvider, and optional api. |
SolwynAgentsRunOptions | Per-invocation options: required workflow, optional tags, and native non-streaming runOptions. |
solwynToolErrorFunction | Tool errorFunction that rethrows Solwyn denials and stops instead of turning them into tool-result text. |
Pass agents.modelProvider to the Runner, attach it, and invoke through agents.run or
agents.runStreamed. Calling runner.run directly with this provider fails closed at model
dispatch. attach(runner) is safe to repeat.
runStreamed returns the native StreamedRunResult. Always consume it with for await and await
result.completed, or cancel it; returning its iterator cancels the run. Abandoned background runs
retain attribution and any token lease until they settle, and client.close() releases
outstanding leases. Supply fresh input for each invocation; resuming a RunState is refused.
Hierarchy and enforcement
Each invocation creates a detached workflow run in the caller's current Solwyn frame, so a
workflow inside an outer run(...) remains its child. Each distinct agent
object gets one child run named agent:<name>. Tool turns and hand-backs reuse that ID, and handoff
targets are siblings under the workflow.
Exact-run stops, velocity history, per-run budgets, and leases target the agent leaf run IDs.
Stopping a workflow parent does not stop its children. Agent names must be non-empty, contain no
control, format, separator, or lone-surrogate characters, and fit in 255 UTF-16 units together
with the agent: prefix.
Set explicit, non-sensitive tags on the workflow; child agents inherit them. Tagged calls use per-call admission and are lease-ineligible. Untagged eligible text calls use token leases, including reuse across an agent's tool turns and hand-backs.
Keep maxRetries: 0 on the underlying OpenAI client and configure retries on the Runner. Each
Runner retry crosses the wrapped client as a separate attempt. Solwyn budget and stop errors veto
Runner retries, even under a permissive plain-boolean retry policy; an explicit unsafe-replay
approval can override that veto, but those retries still cross the wrapped client's budget gate.
Admitted and tested paths
SolwynAgents.runandrunStreamedover OpenAI Chat Completions HTTP.- Responses HTTP with
api: "responses". - Function-tool turns whose tools make no model calls, handoffs and hand-backs, concurrent
independent invocations, and nesting the workflow under a user
run(...). - Runner-managed retries, budget denial, exact-run stop, and stream cancellation and cleanup.
Refused and unsupported paths
The integration throws a typed SolwynError before model dispatch for missing workflow or agent
identity, overlapping agent starts, concurrent model attempts within one invocation, and model
calls while tools execute. Agent-as-tool calls on the inherited provider and explicitly nested
integration workflows latch the violation on the outer workflow; it surfaces from run, from
streamed iteration, and from completed.
A raw OpenAI client fails construction with ConfigurationError (field: "client"), an invalid
api with field: "api", and an absent or invalid OpenAIProvider with
field: "OpenAIProvider". Foreign runner providers, a Model instance in runner.config.model
or Agent.model, and invalid agent names are refused; keep model selection as strings or leave it
unset.
Not admitted: Responses websocket transport, Realtime, hosted multi-agent execution, sandbox agents, human-in-the-loop resume, custom providers or models, model calls inside tools, and guardrail runs on other runners that share this provider.
Tool errors and guardrails
Agents normally turns tool exceptions into a fixed tool-result message. Set
errorFunction: solwynToolErrorFunction on every function tool to preserve Solwyn denial and stop
errors. SolwynAgents.run, streamed iteration, and completed unwrap Agents' ToolCallError and
GuardrailExecutionError wrappers when they carry a Solwyn error, so you can catch
BudgetExceededError or RunStoppedError as you would around a direct wrapped-client call.
Non-Solwyn failures and guardrail tripwires keep their native Agents wrappers.
In Agents 0.20.0, when final output comes from a tool result and a sibling output guardrail trips, Agents replaces the Solwyn error with a redacted plain error before Solwyn receives it. Typed Solwyn catches are unavailable on that path, although the wrapped client still enforces the denial or stop.
Responses caveats
Responses generation is primary-only, so cross-provider failover is unavailable on this surface.
Hosted tools such as web search, file search, code interpreter, image generation, and computer use
incur non-token charges that Solwyn does not meter. background: true is refused by the wrapped
client before provider I/O.
Tracing and edge runtimes
Agents tracing can export prompts, responses, and tool content to OpenAI, outside Solwyn's privacy
boundary. Keep setTracingDisabled(true), tracingDisabled: true, and
traceIncludeSensitiveData: false as shown.
In an edge runtime, pass a wrapped client directly to
new OpenAIProvider({ openAIClient: client as unknown as OpenAI, useResponses: false }) for core
enforcement without framework attribution.