Mental Model
Shiro is easier to learn if you stop thinking in “chatbots” and start thinking in runtimes. There are only a handful of objects. Each owns a different lifetime and a different kind of state.
The short version#
| Concept | Lifetime | Owns | Does not own |
|---|---|---|---|
| Engine | Process / worker | Shared services, registries, plugins | Per-user conversation state |
| Runner | One run | Messages, tool calls, pauses, emitted events | Vendor SDKs |
| Agent | Configuration | Instructions, tools, output contract | Request-specific memory |
| Provider | Adapter | Model API translation | Approvals, Studio, handoffs |
| Tool | One call | A typed side effect | The execution loop |
| Session | Conversation / user | Durable context across runs | Agent instructions |
| Trace | Run history | Structured observability | Application business logic |
Engine vs Runner#
This is the most important distinction in Shiro.
Engine (long-lived)
providers, plugins, registries, event bus, memory services
│
│ engine.execute(agent, input)
▼
Runner (one run)
messages → provider → tools → approvals → handoffs → output → eventsCreate the engine at startup. Reuse it. Let it create a runner per execution. If you create a new engine for every HTTP request, traces fragment and plugins re-initialize for no reason.
Agent vs session#
An agent answers: what can this role do? A session answers: what do we already know about this conversation?
const agent = new Agent({
name: "support",
instructions: "Resolve billing and account questions.",
provider: "openai",
tools: [lookupInvoice],
});
await engine.execute(agent, "Where is invoice INV-8821?", {
sessionId: "customer_48",
});The same agent definition serves many users. The session carries user-specific history. Mixing those lifetimes is the fastest way to leak context across customers.
See Agents and Memory & Sessions.
Provider vs tool#
The provider talks to a model. A tool talks to your systems.
The model may request a tool. The runner executes it. That is why tool calls show up in traces, can require approval, and can time out independently of the provider.
Trace vs logs#
A log line says something happened. A trace places that event in the run: which provider call led to which tool, whether an approval paused execution, which handoff changed the active agent, and what memory was loaded before the next model call.
Studio is a consumer of traces and events. It is not a second orchestrator.
How a run moves#
input
→ load session / memory
→ provider call
→ optional tool calls (and approvals)
→ optional handoff
→ more provider calls as needed
→ validate structured output
→ persist memory
→ emit / export traceDetails live in Execution Pipeline.
Common mistakes#
- Treating the agent as a mutable per-user object
- Calling tools from application code and expecting Studio to see them
- Calling the provider outside the runner after adopting Shiro
- Using text logs instead of traces when a run goes wrong
- Creating an engine per request
Next#
Read Architecture for the system view, then Quick Start to execute your first run.