---
title: "Options"
description: "Configure prompt and output capture (with redaction and truncation), tool input capture, cost estimation per model, and error handling during AI calls."
canonical_url: "https://www.evlog.dev/use-cases/ai-sdk/options"
---
# Options

> Configure prompt and output capture (with redaction and truncation), tool input capture, cost estimation per model, and error handling during AI calls.

`createAILogger(log, options?)` accepts a single options bag. Every option is opt-in. The defaults stay quiet, and they stay safe: nothing a model was sent or returned reaches your drain until you ask for it by name.

<table>
<thead>
  <tr>
    <th>
      Option
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        toolInputs
      </code>
    </td>
    
    <td>
      <code>
        boolean | ToolInputsOptions
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Capture tool call inputs alongside their names (off by default to avoid leaking sensitive data).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        prompt
      </code>
    </td>
    
    <td>
      <code>
        boolean | CaptureOptions
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Capture the prompt sent to the first model call as <code>
        ai.prompt
      </code>
      
       (off by default to avoid leaking sensitive data).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        output
      </code>
    </td>
    
    <td>
      <code>
        boolean | CaptureOptions
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Capture the text generated by the last model call as <code>
        ai.output
      </code>
      
       (off by default to avoid leaking sensitive data).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        cost
      </code>
    </td>
    
    <td>
      <code>
        Record<string, ModelCost>
      </code>
    </td>
    
    <td>
      <code>
        undefined
      </code>
    </td>
    
    <td>
      Pricing map. Keys are model IDs, values are <code>
        { input, output }
      </code>
      
       in dollars per 1M tokens.
    </td>
  </tr>
</tbody>
</table>

## Tool Inputs

By default, `ai.toolCalls` is a `string[]` of tool names. Enable `toolInputs` to capture inputs too, which suits debugging agent behaviour or auditing what data the model reached for.

<warning>

Tool inputs get large, and they carry SQL, API keys and customer PII. Reach for `maxLength` and `transform` before raw capture in production.

</warning>

### Capture everything

```typescript
const ai = createAILogger(log, { toolInputs: true })
```

### Truncate long inputs

```typescript
const ai = createAILogger(log, { toolInputs: { maxLength: 200 } })
```

### Redact sensitive fields

```typescript
const ai = createAILogger(log, {
  toolInputs: {
    maxLength: 500,
    transform: (input, toolName) => {
      if (toolName === 'queryDB') return { sql: '***' }
      return input
    },
  },
})
```

<table>
<thead>
  <tr>
    <th>
      Sub-option
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        maxLength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      Truncate stringified inputs exceeding this character length (appends <code>
        …
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        transform
      </code>
    </td>
    
    <td>
      <code>
        (input, toolName) => unknown
      </code>
    </td>
    
    <td>
      Custom transform applied before <code>
        maxLength
      </code>
      
      . Use to redact fields or reshape data.
    </td>
  </tr>
</tbody>
</table>

When `toolInputs` is enabled, `ai.toolCalls` becomes an `Array<{ name, input }>` instead of a plain string array.

## Prompt and Output Capture

By default, nothing the model was sent or returned reaches your drain. Two independent options turn capture on, one per direction: `prompt` records what was sent, `output` records what came back. Enable one, the other, or both.

```typescript
const ai = createAILogger(log, { prompt: true, output: true })
```

The wide event then carries:

- `ai.prompt`: the formatted text of the prompt sent to the **first** model call. One block per message prefixed with its role; text parts are inlined, and other part types become `[tool-call name]`, `[tool-result name]` or `[file]` markers.
- `ai.output`: the text generated by the **last** model call, the final answer in a multi-step run. Streamed responses accumulate from the text chunks.

Capture only the direction you need:

```typescript
const ai = createAILogger(log, { prompt: true }) // ai.prompt only
const ai = createAILogger(log, { output: true }) // ai.output only
```

<warning>

Prompts and outputs can be large, and they carry whatever your users typed. Reach for `maxLength` and `transform` before raw capture in production.

</warning>

### Truncate long content

Each option takes its own `maxLength`:

```typescript
const ai = createAILogger(log, { prompt: { maxLength: 500 } })
```

### Redact or reshape

`transform` receives the captured text and runs before `maxLength`:

```typescript
const ai = createAILogger(log, {
  prompt: {
    maxLength: 500,
    transform: text => redact(text),
  },
})
```

<table>
<thead>
  <tr>
    <th>
      Sub-option
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        maxLength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      Truncate captured text exceeding this character length (appends <code>
        …
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        transform
      </code>
    </td>
    
    <td>
      <code>
        (content) => string
      </code>
    </td>
    
    <td>
      Custom transform applied before <code>
        maxLength
      </code>
      
      .
    </td>
  </tr>
</tbody>
</table>

<note>

Prompt and output capture is a middleware capability: it works with `createAILogger` and `createAIMiddleware`. The standalone `createEvlogIntegration` observes telemetry events and has no access to the model call parameters, so `ai.prompt` and `ai.output` stay absent there.

</note>

## Cost Estimation

Pass a `cost` map to compute estimated dollar cost per call. The middleware multiplies token usage by the per-million rates and sets `ai.estimatedCost` on the wide event.

```typescript
const ai = createAILogger(log, {
  cost: {
    'claude-sonnet-4.6': { input: 3, output: 15 },
    'gpt-4o': { input: 2.5, output: 10 },
  },
})
```

Read the result from your handler with [`ai.getEstimatedCost()`](https://www.evlog.dev/use-cases/ai-sdk/metadata), which suits billing dashboards or warning users before expensive calls.

<tip>

Keep your `cost` map in one file alongside model selection so renaming a model in production also updates pricing. Per-route maps drift the moment two routes disagree about which model they call, so keep one.

</tip>

## Error Handling

If a model call fails, the middleware captures the error into the wide event before re-throwing:

```json [Wide Event]
{
  "ai": {
    "calls": 1,
    "model": "claude-sonnet-4.6",
    "provider": "anthropic",
    "finishReason": "error",
    "error": "API rate limit exceeded"
  }
}
```

Stream errors (e.g. content filter) are also captured from the stream's error chunks. Your error-handling code (`try/catch`, route-level error handlers) keeps working as usual, since the middleware only observes.

---

- [Overview](https://www.evlog.dev/use-cases/ai-sdk/overview)
- [Usage Patterns](https://www.evlog.dev/use-cases/ai-sdk/usage)


## Sitemap

See the full [sitemap](https://www.evlog.dev/sitemap.md) for all pages.
