Mimir.Event (Mimir v0.4.0)

Copy Markdown View Source

Domain-typed event envelope — the vocabulary root for everything that travels the llm.* / agent.* / workflow.* streams. domain/type are closed atom unions, usage/tool are the promoted commons consumers actually query, and anything provider-specific rides raw (the documented verbatim carve-out).

Build with llm/2, agent/2, or workflow/2 — each validates type against its domain's closed union and returns {:ok, t()} | {:error, {:bad_type, domain, type}}. Never construct the struct directly.

to_wire/1 / from_wire/1 are the struct-in-BEAM / JSON-at-the-boundary pair (the house DecisionRecord.to_event pattern): to_wire/1 always succeeds and produces a string-keyed map with nil ids omitted and nil usage/tool serialized as absent keys, never null. from_wire/1 is the fallible, tolerant inverse — unknown top-level keys are ignored, an unknown "type" for the domain is {:error, {:bad_event, {:bad_type, ...}}}, and anything else unparseable is {:error, {:bad_event, reason}}. It never raises and never calls String.to_atom/1 — types are resolved through fixed lookup maps built from the closed unions.

Type unions are closed per release; tolerance for unknown telemetry frames lives at collection (collectors count + debug-log + drop), never here.

Summary

Functions

Build an agent.* event. See llm/2 for attrs.

Parse a wire-form map back into a t(). Fallible and tolerant: unknown top-level keys are ignored, a non-map or a map missing "domain"/"type" is {:error, {:bad_event, {:invalid_wire, term()}}}, an unrecognized "domain" is {:error, {:bad_event, {:bad_domain, term()}}}, and an unrecognized "type" for the domain is {:error, {:bad_event, {:bad_type, domain, term()}}}. Never raises; never calls String.to_atom/1.

Build an llm.* event. type must be one of llm_type/0; attrs is a keyword list or map carrying :seq (default 0), :ts (default System.monotonic_time(:nanosecond)), the four correlation ids, :usage, :tool, and :raw (default %{}).

Render a t() to its wire form: a string-keyed map, correlation ids nested under "ids" (nils omitted, "ids" itself always present), "usage"/ "tool" present only when not nil, "raw" always present.

Build a workflow.* event. See llm/2 for attrs.

Types

agent_type()

@type agent_type() ::
  :session_open
  | :session_reattach
  | :turn_start
  | :turn_end
  | :terminal
  | :error

domain()

@type domain() :: :llm | :agent | :workflow

llm_type()

@type llm_type() ::
  :request_start
  | :request_stop
  | :reasoning
  | :tool_call
  | :usage
  | :turn_complete
  | :exception

t()

@type t() :: %Mimir.Event{
  domain: domain(),
  raw: map(),
  request_id: String.t() | nil,
  seq: non_neg_integer(),
  session_id: String.t() | nil,
  step_id: String.t() | nil,
  tool: %{id: String.t() | nil, name: String.t()} | nil,
  ts: integer(),
  type: llm_type() | agent_type() | workflow_type(),
  usage:
    %{input_tokens: non_neg_integer(), output_tokens: non_neg_integer()} | nil,
  workflow_id: String.t() | nil
}

workflow_type()

@type workflow_type() :: :step_start | :step_stop | :step_exception

Functions

agent(type, attrs)

@spec agent(agent_type(), keyword() | map()) ::
  {:ok, t()} | {:error, {:bad_type, :agent, term()}}

Build an agent.* event. See llm/2 for attrs.

from_wire(wire)

@spec from_wire(map()) :: {:ok, t()} | {:error, {:bad_event, term()}}

Parse a wire-form map back into a t(). Fallible and tolerant: unknown top-level keys are ignored, a non-map or a map missing "domain"/"type" is {:error, {:bad_event, {:invalid_wire, term()}}}, an unrecognized "domain" is {:error, {:bad_event, {:bad_domain, term()}}}, and an unrecognized "type" for the domain is {:error, {:bad_event, {:bad_type, domain, term()}}}. Never raises; never calls String.to_atom/1.

llm(type, attrs)

@spec llm(llm_type(), keyword() | map()) ::
  {:ok, t()} | {:error, {:bad_type, :llm, term()}}

Build an llm.* event. type must be one of llm_type/0; attrs is a keyword list or map carrying :seq (default 0), :ts (default System.monotonic_time(:nanosecond)), the four correlation ids, :usage, :tool, and :raw (default %{}).

to_wire(ev)

@spec to_wire(t()) :: map()

Render a t() to its wire form: a string-keyed map, correlation ids nested under "ids" (nils omitted, "ids" itself always present), "usage"/ "tool" present only when not nil, "raw" always present.

workflow(type, attrs)

@spec workflow(workflow_type(), keyword() | map()) ::
  {:ok, t()} | {:error, {:bad_type, :workflow, term()}}

Build a workflow.* event. See llm/2 for attrs.