lukasa1993/tanstack-skills-extracted/tanstack-ai-core-middleware
Claude Code and agent skill by lukasa1993/tanstack-skills-extracted
- community
Checking that the SKILL.md file is still in the repository.
Chat lifecycle middleware hooks: onConfig, onStart, onChunk, onBeforeToolCall, onAfterToolCall, onUsage, onFinish, onAbort, onError. Use for analytics, event firing, tool caching (toolCacheMiddleware), logging, and tracing. Middleware array in chat() config, left-to-right execution order. NOT onEnd/onFinish callbacks on chat() — use middleware.
Install
npx vskill@latest install lukasa1993/tanstack-skills-extracted/tanstack-ai-core-middlewareSKILL.md
Middleware
Dependency note: This skill builds on ai-core. Read it first for critical rules.
Setup — Analytics Tracking Middleware
Hooks Reference
Every hook receives a ChatMiddlewareContext as its first argument, which provides requestId, streamId, phase, iteration, chunkIndex, callMetadata, model, provider, signal, abort(), defer(), and more. parentRunId names the run this one continues. subagentRunId is set only inside a subagent and names its card.
| Hook | When | Second Argument | |
|---|---|---|---|
onConfig | Once at startup (init) + once per iteration (beforeModel) + once at a separate-finalization boundary | ChatMiddlewareConfig (return partial to merge) | |
onStructuredOutputConfig | Once at the separate-finalization boundary | StructuredOutputMiddlewareConfig (return partial) | |
onStart | Once after initial onConfig | none | |
onIteration | Start of each agent loop iteration | IterationInfo | |
onShouldContinue | Whether to start another agent-loop iteration (AND with strategy; false stops) | AgentLoopState | |
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, andmaxTokensare notfirst-class fields onChatMiddlewareConfig. To adjust sampling frommiddleware, return a partial that mutatesconfig.modelOptionsusing theprovider's native key (e.g. OpenAItemperature/max_output_tokens,Anthropicmax_tokens, Ollama nestedoptions.num_predict). Returning atop-leveltemperature/maxTokenshas 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. | |
'structuredOutput' | During the separate-finalization adapter call (set for all chunks from adapter.structuredOutputStream or the synthesized fallback). Does not occur for native-combined output. |
Separate-finalization path (adapters without native-combined support):
onStructuredOutputConfigfires beforeonConfigat the structured-output boundary.onConfigre-fires at the same boundary withctx.phase === 'structuredOutput', receiving the post-onStructuredOutputConfigview of the config (minusoutputSchema).onChunkandonUsagefire for every chunk and usage event emitted by the structured-output call, withctx.phase === 'structuredOutput'.onIterationdoes not fire for finalization — it is agent-loop-only.- Terminal `info` and structured-output:
info.usage/info.finishReason/info.contentreflect the agent loop's terminal state, NOT the finalization step. Finalization state is intentionally segregated to keep agent-loop semantics clean. For a tools-lesschat({ outputSchema })run,info.usageisundefinedandinfo.finishReasonisnull(no agent-loop iteration producedRUN_FINISHED). To capture finalization tokens, useonUsage— it fires for both agent-loop iterations and the final call. For the structured-output result itself, observe thestructured-output.completeCUSTOM event inonChunk.
Native-combined output:
- The schema-constrained JSON is produced by a normal agent-loop iteration.
onStructuredOutputConfigdoes not fire,ctx.phaseremains'modelStream', andonIterationfires for that iteration. info.contentincludes the structured JSON because it is agent-loop text. Middleware observes thestructured-output.completeevent inonChunkduring the same phase.
Both paths:
- On successful completion,
onFinishfires once after the structured result completes. Terminal-hook exclusivity still holds. - By
onFinish,ctx.messagesincludes the completed terminal assistant messages. Native-combined output keeps the structured result on its terminal assistant message. The separate-finalization path can preserve the agent loop's plain-text message followed by a distinct structured-output message.
onStructuredOutputConfig
A dedicated config hook that fires only at the separate-finalization boundary. Use it to transform the JSON Schema sent to the provider (inject $defs, strip vendor-incompatible keywords) or to apply structured-output- specific config changes that should not affect the agent-loop adapter calls.
Signature:
`StructuredOutputMiddlewareConfig` shape:
Note the Omit<…, 'tools'>: there is no `config.tools` on this hook. The structured-output call is the final, tool-free call, so reading or returning tools here is a compile error, not a no-op. Transform tools in onConfig instead.
Ordering rule:
onStructuredOutputConfigfires beforeonConfigat the structured-output boundary.onConfigre-fires at the same boundary withctx.phase === 'structuredOutput', receiving the post-onStructuredOutputConfigview of the config (minusoutputSchema).- Use
onConfigfor general-purpose transforms that apply to every adapter call (agent-loop iterations and the final structured-output call). - Use
onStructuredOutputConfigwhen you need to transform the JSON Schema or apply structured-output-specific behavior.
Core Patterns
Pattern 1: Analytics and Logging Middleware
Use onStart, onFinish, onUsage, and onError for comprehensive observability. Use ctx.defer() for non-blocking async side effects that should not block the stream.
Pattern 2: Tool Interception Middleware
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/tanstack-ai-core-middleware/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/lukasa1993/tanstack-skills-extracted/tanstack-ai-core-middleware)