SOLWYN

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/node imported. Constructing SolwynAgents without the Node entry throws ConfigurationError.
  • @solwyn/sdk, the umbrella @openai/agents package (optional peer range >=0.20.0 <1), openai >=7.2.0 <8 so npm installs a single OpenAI copy, and zod 4. Applications on openai 6 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.0 and openai@7.36.0. For strict declaration checking with this Agents version, use @types/node 22.15.30 or 24, include DOM types, and keep Agents' optional @modelcontextprotocol/client dependency 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.

ExportPurpose
SolwynAgentsConstructed with client, OpenAIProvider, and optional api ("chat_completions" by default, or "responses"). Exposes modelProvider, attach(runner), run(...), and runStreamed(...).
SolwynAgentsOptionsConstructor options type: client, OpenAIProvider, and optional api.
SolwynAgentsRunOptionsPer-invocation options: required workflow, optional tags, and native non-streaming runOptions.
solwynToolErrorFunctionTool 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.run and runStreamed over 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.

On this page