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

# Event types reference: llm_call, tool_call, solana_tx

> Reference for all event types Mortem records in a trace — auto-captured events from wrappers and manual custom events you define yourself.

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.

```ts theme={null}
// 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:

```ts theme={null}
const result = await event.run(async () => {
  return fetchMarketData(token)
})
```

## Event statuses

Every completed event has a status:

| Status    | Meaning                                                  |
| --------- | -------------------------------------------------------- |
| `"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()`:

```ts theme={null}
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" } })
```

<Note>
  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.
</Note>

## 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:**

```ts theme={null}
{
  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:**

```ts theme={null}
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:**

```ts theme={null}
{
  toolName: string
  input: unknown    // arguments passed to the tool
  output: unknown   // value returned by the tool
}
```

**Example setup:**

```ts theme={null}
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:**

```ts theme={null}
{
  signature: string   // base-58 transaction signature
  lamports: string    // lamport amount as a numeric string (bigint-safe)
}
```

**Example setup:**

```ts theme={null}
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.

```ts theme={null}
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.

```ts theme={null}
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.

```ts theme={null}
const event = session.beginEvent("custom", { step: "market-analysis" })

// ... do work ...

event.complete({ payload: { decision: "buy", confidence: 0.87 } })
```

<Tip>
  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.
</Tip>

## `BeginEventOptions`

Pass these as the third argument to `session.beginEvent()` to control timing, identity, and nesting.

<ParamField path="id" type="string">
  Override the auto-generated event ID. Useful when you need to correlate this event with an external system identifier.
</ParamField>

<ParamField path="parentEventId" type="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.
</ParamField>

<ParamField path="startedAt" type="Date">
  Backfill the event start time. Use this if the work already began before you called `beginEvent`.
</ParamField>

## `CompleteEventOptions`

Pass these to `event.complete()` to attach a result payload and override timing.

<ParamField path="payload" type="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.
</ParamField>

<ParamField path="status" type="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()`.
</ParamField>

<ParamField path="endedAt" type="Date">
  Override the event end time. Defaults to the moment `complete()` is called.
</ParamField>
