Framework integrations
How Solwyn fits under OpenAI Agents, LangChain and LangGraph, and CrewAI — what each recipe enforces, what it attributes, and what it deliberately does not cover
import os
from openai import AsyncOpenAI
from agents import set_default_openai_api, set_default_openai_client
from solwyn import AsyncSolwyn
client = AsyncSolwyn(AsyncOpenAI(), api_key=os.environ["SOLWYN_API_KEY"])
set_default_openai_client(client) # every Agents model call now crosses Solwyn
set_default_openai_api("chat_completions")SDK v0.6.0+. Solwyn separates framework attribution from provider enforcement, and the two never blur:
- Enforcement — budget checks, leases, failover, settlement — happens only where a framework's provider call crosses a
Solwyn(...)orAsyncSolwyn(...)wrapper. The SDK's type-transparent wrapper passes a framework'sisinstancegate, so in the simplest case you hand the wrapped client to the framework where it expected the provider's own client. - Attribution — which agent, chain node, or task a call belongs to — comes from the shipped integration modules. They consume structural lifecycle data only (run ids, names, ordering), are enforced content-free by a privacy firewall test, and make no provider calls, budget checks, or settlement events themselves. They are built on detached run handles.
Each page below is a tested recipe, not a general promise that every framework surface which accepts a provider-looking object is budget-enforced. Keep the wrapped client, the callback or listener, the compatibility shim, and the call shape together exactly as shown.
Support matrix
| Framework | Enforcement | Attribution | Admitted and tested calls |
|---|---|---|---|
| OpenAI Agents SDK | Yes — the wrapped AsyncSolwyn default client on the pinned Chat Completions path | Workflow tags plus a stable detached RunHandle per active agent, reactivated by recipe-local Model and ModelProvider adapters | Runner.run and Runner.run_streamed, including runner-managed retries, handoffs, function-tool turns, streaming cleanup, and budget denial |
| LangChain and LangGraph | Yes — only through the recipe's wrapped sync and async clients and its exact content-blind raw-response leaf shim | SolwynRunScopeHandler maps structural chain, graph-node, and model callback ids; a one-shot nomination activates the matching identity only for the provider call | Basic non-streaming Chat Completions: chain invoke, chain ainvoke, and a two-node LangGraph invoke |
| CrewAI | Native LiteLLM path: none. The narrow enforcement recipe routes a sync, plain-text Chat Completions call through a wrapped Solwyn client from a custom BaseLLM | SolwynEventListener observes only structural crew and task lifecycle events; never model, stream-chunk, or tool events | Native LiteLLM with zero Solwyn budget checks; one sync, non-streaming, plain-text custom-BaseLLM call; sequential Crew reuse |
Hierarchy
| Framework | Run tree |
|---|---|
| OpenAI Agents | Agent runs are children of the enclosing workflow run; handoff agents are siblings; repeated tool turns reuse the same agent run |
| LangChain / LangGraph | LangChain's explicit parent_run_id edges become Solwyn parent ids; missing or inconsistent hierarchy and ambiguous nominations fail closed |
| CrewAI | crew:<name> with task:<index> children, preserved across CrewAI's thread-pool callbacks; each sequential kickoff gets a fresh generation, and overlapping reuse with a live prior task fails closed |
Installation
| Framework | Install | Ships in the SDK |
|---|---|---|
| OpenAI Agents | pip install "solwyn[openai]" openai-agents | Nothing — no solwyn.integrations.agents module and no extra; the adapter classes live in the recipe |
| LangChain / LangGraph | pip install "solwyn[langchain,openai]" langchain-openai langgraph | solwyn.integrations.langchain.SolwynRunScopeHandler (solwyn[langchain] declares langchain-core>=0.3) |
| CrewAI | pip install "solwyn[crewai]" (add openai for the enforcement recipe) | solwyn.integrations.crewai.SolwynEventListener (solwyn[crewai] declares crewai>=0.157.0) |
The Solwyn core never imports any of these frameworks; each integration module imports its framework lazily and raises an ImportError naming the extra to install. CrewAI and LiteLLM resolve in their own dependency lane because they conflict with the current Agents stack.
Keeping up with framework churn
The pinned recipes are exercised offline against locked versions — openai-agents==0.20.0, langchain-core==1.5.5, langchain-openai==1.5.1, langgraph==1.2.11, crewai==1.15.16 — and a scheduled weekly smoke re-resolves the current release of each framework so API drift fails visibly. The version-sensitive pieces (the LangChain raw-response shim, the Agents Model adapter) are deliberately kept in the recipes rather than the package so that a framework change breaks a documented snippet, not a hidden import.
What the integrations never see
Every shipped integration binds a framework callback's content parameters — inputs, outputs, prompts, messages, responses, errors — and never loads them. That rule is enforced by an AST-level test over every module in solwyn.integrations: loading a content-bearing name, importing httpx, or constructing a MetadataEvent fails the SDK's own suite. The only log lines the integrations emit are three structural WARNINGs carrying nothing but a run id (see each page). Framework tracing — OpenAI Agents tracing in particular — is a separate export channel that you disable yourself if prompts must not leave your process.
Related
- Agent runs —
solwyn.run,create_run,start_run, andRunHandle - Run control — stopping a framework-driven run from the dashboard
- How it works — why the wrapper passes
isinstancechecks - Privacy — the content-free contract the integrations are held to
Troubleshooting
Symptom-first index for common Solwyn SDK problems in production
OpenAI Agents SDK
Install AsyncSolwyn as the OpenAI Agents SDK's default client, attribute every model turn to a stable agent run under the workflow, and keep runner retries, handoffs, streaming, and budget denials on the metered path