Providers
A provider adapts a model vendor to Shiro’s request/response contract. It should stay small: accept messages and options, return text / tool requests / usage, and map vendor errors into Shiro errors.
Everything else — tools, approvals, memory, Studio — stays outside the adapter.
Why providers are isolated#
Vendor APIs change. Runtime behavior should not. If tools or Studio imported OpenAI types directly, every SDK bump would ripple through the product. Providers absorb that churn.
Agent (provider: "openai")
│
▼
Engine plugin registers OpenAIProvider
│
▼
Runner calls provider.generate / provider.streamInstalling OpenAI#
import { Engine } from "@shiro-sdk/core";
import { OpenAIPlugin } from "@shiro-sdk/openai";
const engine = new Engine();
engine.use(
new OpenAIPlugin({
apiKey: process.env.OPENAI_API_KEY!,
model: "gpt-5",
})
);OpenAIPlugin registers an OpenAIProvider under the id "openai". Agents select it:
const agent = new Agent({
name: "support",
instructions: "...",
provider: "openai",
});You can also pass a provider instance instead of a string id when you need a one-off configuration.
What providers should not own#
- Memory persistence
- Approval decisions
- Tool execution
- Studio rendering
- Handoff policy
If you find those concerns inside a provider, they belong on the engine / runner instead. See Plugins for the install surface.
Streaming#
Providers may expose streaming at the adapter level (provider.stream). Application-facing
“stream the whole run” is better modeled as runtime events (tool started, approval
requested, run completed) via the engine event bus — that is what Studio
consumes. Do not assume provider token deltas are the only progress signal.
Best practices#
- Configure providers at startup through plugins
- Normalize errors at the adapter boundary
- Record usage and latency for traces
- Avoid leaking vendor-specific response objects into tools
Common mistakes#
- Calling the vendor SDK from a tool after adopting Shiro
- Installing the package but forgetting
engine.use(new OpenAIPlugin(...)) - Selecting
provider: "openai"when no plugin registered that id