Mental Model

The few runtime objects you need to keep straight before writing agents.

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#

ConceptLifetimeOwnsDoes not own
EngineProcess / workerShared services, registries, pluginsPer-user conversation state
RunnerOne runMessages, tool calls, pauses, emitted eventsVendor SDKs
AgentConfigurationInstructions, tools, output contractRequest-specific memory
ProviderAdapterModel API translationApprovals, Studio, handoffs
ToolOne callA typed side effectThe execution loop
SessionConversation / userDurable context across runsAgent instructions
TraceRun historyStructured observabilityApplication 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 → events

Create 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.

See Engine and Runner.

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.

See Providers and Tools.

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 trace

Details 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.