Documentation
Tracing, reliability, and errors
Every run has a runId. Traces, retries, timeouts, typed errors, and provider fallbacks.
Tracing
Every run has a `runId`. result.traces is an ordered list of what happened: start/end, model route and calls, tools, handoffs, memory search/add, graph read/ingest, retries, errors.
Use traces for support (“show me why this refund didn’t fire”), cost (token usage on each model.call), and SLOs (durationMs on run.end).
.tracing({
enabled: true,
onEvent: (event) => logger.debug({ runId: event.runId, type: event.type, ...event.data }),
})
result.traces;
result.usage;
result.durationMs;
result.turns;Disable with .tracing(false) in hot tests if you want.
Retries and timeouts
Provider calls use .retry({ maxAttempts, baseDelayMs }). The whole run is bounded by .timeout(ms) (default 120s) and .maxTurns(n) (default 10).
.retry({ maxAttempts: 3, baseDelayMs: 200 })
.timeout(60_000)
.maxTurns(8)
await agent.run(prompt, { abortSignal: controller.signal });AbortError if the signal fires. TimeoutError / MaxTurnsError if limits hit. Tool failures inside the loop are *not* those — they become error payloads unless you throw from a guardrail.
Error types
Catch ShirubeError or a subclass:
| Class | Meaning |
|---|---|
ConfigError | Missing name, instructions, or API key |
GuardrailTripwireError | A rail blocked the run |
MaxTurnsError | Tool loop too long |
TimeoutError | Wall clock limit |
ToolError | Bad tool definition or unknown tool |
ModelError | Provider HTTP / empty response (including after fallbacks) |
MemoryError | Memory backend |
McpError | MCP connect/serve |
OutputValidationError | JSON schema still invalid after repairs |
AbortError | Caller cancelled |
Fallbacks
If OpenAI is down, try Claude (or Gemini) with the same ChatRequest shape:
import { OpenAIProvider, AnthropicProvider, GeminiProvider } from "shirube-ai";
.provider(new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY! }))
.fallback(
new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY }),
)The first provider that returns successfully wins. All failing is ModelError. See Model providers.