Skip to main content
ClaudeWave
Skill2.8k estrellas del repoactualizado today

ai-core/middleware

The middleware skill in TanStack AI provides lifecycle hooks for intercepting and controlling chat streams at multiple points: initialization, iteration, chunk streaming, tool execution, and completion. Use it to implement analytics tracking, error handling, request logging, tool call validation, and structured output configuration across AI chat operations.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/TanStack/ai /tmp/ai-core-middleware && cp -r /tmp/ai-core-middleware/packages/ai/skills/ai-core/middleware ~/.claude/skills/ai-core-middleware
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Middleware

> **Dependency note:** This skill builds on ai-core. Read it first for critical rules.

## Setup — Analytics Tracking Middleware

```typescript
import { chat, toServerSentEventsResponse } from '@tanstack/ai'
import { openaiText } from '@tanstack/ai-openai'

const stream = chat({
  adapter: openaiText('gpt-5.2'),
  messages,
  middleware: [
    {
      onStart: (ctx) => {
        console.log('Chat started:', ctx.model)
      },
      onFinish: (ctx, info) => {
        trackAnalytics({ model: ctx.model, tokens: info.usage?.totalTokens })
      },
      onError: (ctx, info) => {
        reportError(info.error)
      },
    },
  ],
})

return toServerSentEventsResponse(stream)
```

## Hooks Reference

Every hook receives a `ChatMiddlewareContext` as its first argument, which provides
`requestId`, `streamId`, `phase`, `iteration`, `chunkIndex`, `model`, `provider`,
`signal`, `abort()`, `defer()`, and more.

| Hook                       | When                                                                                               | Second Argument                                     |
| -------------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| `onConfig`                 | Once at startup (`init`) + once per iteration (`beforeModel`) + once at structured-output boundary | `ChatMiddlewareConfig` (return partial to merge)    |
| `onStructuredOutputConfig` | Once at the structured-output boundary (only when `chat({ outputSchema })`)                        | `StructuredOutputMiddlewareConfig` (return partial) |
| `onStart`                  | Once after initial `onConfig`                                                                      | none                                                |
| `onIteration`              | Start of each agent loop iteration                                                                 | `IterationInfo`                                     |
| `onChunk`                  | Every streamed chunk                                                                               | `StreamChunk` (return void/chunk/chunk[]/null)      |
| `onBeforeToolCall`         | Before each tool executes                                                                          | `ToolCallHookContext` (return decision or void)     |
| `onAfterToolCall`          | After each tool executes                                                                           | `AfterToolCallInfo`                                 |
| `onToolPhaseComplete`      | After all tool calls in an iteration                                                               | `ToolPhaseCompleteInfo`                             |
| `onUsage`                  | When `RUN_FINISHED` includes usage data                                                            | `UsageInfo`                                         |
| `onFinish`                 | Run completed normally                                                                             | `FinishInfo`                                        |
| `onAbort`                  | Run was aborted                                                                                    | `AbortInfo`                                         |
| `onError`                  | Unhandled error occurred                                                                           | `ErrorInfo`                                         |

Terminal hooks (`onFinish`, `onAbort`, `onError`) are **mutually exclusive** -- exactly
one fires per `chat()` invocation.

> **Sampling in `onConfig`:** `temperature`, `topP`, and `maxTokens` are **not**
> first-class fields on `ChatMiddlewareConfig`. To adjust sampling from
> middleware, return a partial that mutates `config.modelOptions` using the
> provider's native key (e.g. OpenAI `temperature` / `max_output_tokens`,
> Anthropic `max_tokens`, Ollama nested `options.num_predict`). Returning a
> top-level `temperature`/`maxTokens` has no effect.

### Phase values

`ctx.phase` is one of:

| Phase                | When                                                                                                                                                                                                                                           |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `'init'`             | Initial setup (before the first `onConfig` snapshot is built).                                                                                                                                                                                 |
| `'beforeModel'`      | Right before each agent-loop adapter call (`onConfig` re-fires here).                                                                                                                                                                          |
| `'modelStream'`      | During model streaming chunks within the agent loop.                                                                                                                                                                                           |
| `'beforeTools'`      | Before tool execution phase.                                                                                                                                                                                                                   |
| `'afterTools'`       | After tool execution phase.                                                                                                                                                                                                                    |
| `