Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mortemlabs.com/llms.txt

Use this file to discover all available pages before exploring further.

Events are the individual observations that make up a trace. Each time your agent calls an LLM, invokes a tool, submits a Solana transaction, or reaches a decision point, Mortem records that moment as an event with a type, payload, timing, and status. The dashboard assembles these events into a chronological decision sequence you can replay and inspect.

How events work

Every event belongs to a session and is recorded through an EventBuilder. When you use the SDK wrappers (wrapOpenAI, wrapAnthropic, wrapConnection, and so on), events are captured automatically. For steps that wrappers do not cover, call session.beginEvent() directly.
// Begin an event — returns an EventBuilder
const event = session.beginEvent("custom", { step: "market-analysis" })

// ... do work ...

// Complete it with a result payload
event.complete({ payload: { decision: "buy", confidence: 0.87 } })
You can also use event.run() to wrap an async function and have the SDK complete or fail the event automatically:
const result = await event.run(async () => {
  return fetchMarketData(token)
})

Event statuses

Every completed event has a status:
StatusMeaning
"ok"The event completed successfully.
"error"The event failed. The errorMessage field is populated.
Call event.complete() to record status "ok", or event.fail(error) to record status "error".

Parent and child events

Nest events under a parent to represent hierarchical work — for example, a planning step that triggers several tool calls. Use options.parentEventId when calling session.beginEvent():
const planning = session.beginEvent("custom", { step: "planning" })

const lookup = session.beginEvent(
  "tool_call",
  { toolName: "fetchPrice" },
  { parentEventId: planning.id },
)
lookup.complete({ payload: { price: 142.5 } })

planning.complete({ payload: { decision: "proceed" } })
When you wrap LLM clients and tools with Mortem’s wrappers and call them inside session.run(), parent-child linking is handled automatically through async context. Manual parentEventId is only needed when you manage the nesting yourself.

Auto-captured event types

These event types are recorded automatically when you use the corresponding SDK wrapper. You do not need to call session.beginEvent() for them.

llm_call

Recorded whenever your agent calls a wrapped LLM — OpenAI, Anthropic, Ollama, or a Vercel AI SDK model. Captures the model name, token usage, and estimated cost. Captured by: mortem.wrapOpenAI(), mortem.wrapAnthropic(), mortem.wrapOllama(), mortem.wrapLanguageModel() Payload shape:
{
  model: string          // e.g. "gpt-4o", "claude-sonnet-4-20250514"
  usage: {
    promptTokens: number
    completionTokens: number
    totalTokens: number
  }
  costUsd: number        // estimated cost in USD
}
Example setup:
const openai = mortem.wrapOpenAI(new OpenAI())

// All completions made through this client are now traced automatically
const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: [{ role: "user", content: "Should I buy JUP?" }],
})

tool_call

Recorded whenever a wrapped tool is invoked by the LLM. Captures the tool name, the input the model sent, and the output your function returned. Captured by: mortem.wrapTools(), mortem.langchainHandler() Payload shape:
{
  toolName: string
  input: unknown    // arguments passed to the tool
  output: unknown   // value returned by the tool
}
Example setup:
import { generateText, tool } from "ai"

const tools = mortem.wrapTools({
  fetchPrice: tool({
    description: "Get the current token price",
    parameters: z.object({ token: z.string() }),
    execute: async ({ token }) => getPriceFor(token),
  }),
})

await session.run(() =>
  generateText({ model: tracedModel, tools, prompt: "What is the SOL price?" })
)

solana_tx

Recorded whenever a Solana transaction is sent through a wrapped connection. Captures the transaction signature and the lamports transferred. Captured by: mortem.wrapConnection() Payload shape:
{
  signature: string   // base-58 transaction signature
  lamports: string    // lamport amount as a numeric string (bigint-safe)
}
Example setup:
import { Connection } from "@solana/web3.js"

const connection = mortem.wrapConnection(
  new Connection("https://api.devnet.solana.com")
)

// Transactions sent through this connection are traced automatically
const signature = await connection.sendRawTransaction(rawTx)

Manual event types

These event types are not captured by wrappers. Record them yourself with session.beginEvent().

x402_payment

Record an x402 payment event — an HTTP 402-based micropayment made by your agent.
const payment = session.beginEvent("x402_payment", {
  amount: 5000,
  currency: "USDC",
  recipient: "merchant.sol",
})

// ... execute payment ...

payment.complete({
  payload: { txSignature: "5Kd3NBUAdUnhyzenEwVLy9pBKGKdVUXmH..." },
})

mcp_call

Record a Model Context Protocol tool call made by your agent.
const mcp = session.beginEvent("mcp_call", {
  tool: "read_resource",
  server: "market-data-mcp",
})

const result = await mcpClient.callTool("read_resource", { uri: "price://SOL" })

mcp.complete({ payload: { result } })

custom

Record any arbitrary step in your agent’s reasoning process. Use custom events to mark decisions, checkpoints, strategy evaluations, or any other named step that is meaningful for post-trade debugging.
const event = session.beginEvent("custom", { step: "market-analysis" })

// ... do work ...

event.complete({ payload: { decision: "buy", confidence: 0.87 } })
Give each custom event a descriptive step value in the initial payload. That label appears in the dashboard’s event timeline and makes it easy to identify exactly where an agent’s reasoning diverged from the expected path.

BeginEventOptions

Pass these as the third argument to session.beginEvent() to control timing, identity, and nesting.
id
string
Override the auto-generated event ID. Useful when you need to correlate this event with an external system identifier.
parentEventId
string | null
Nest this event under a parent event. Set to the parent EventBuilder.id. Pass null explicitly to make the event a root event even when called inside a parent context.
startedAt
Date
Backfill the event start time. Use this if the work already began before you called beginEvent.

CompleteEventOptions

Pass these to event.complete() to attach a result payload and override timing.
payload
JsonValue
The result or output of this event. Any JSON-serializable value is accepted. If omitted, the payload passed to beginEvent is used as-is.
status
string
default:"ok"
Override the completion status. Defaults to "ok". Pass "error" if the event represents a failure you want to mark explicitly without calling event.fail().
endedAt
Date
Override the event end time. Defaults to the moment complete() is called.