integrating-llm

Guides implementing vendor-neutral LLM port adapters with structured output validation and error mapping.

Updated Sep 15, 2026
One-click install
npx skills add https://github.com/tomada1114/quick-reply-drill --skill integrating-llm-tomada1114
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: integrating-llm
Source: https://github.com/tomada1114/quick-reply-drill/tree/main/.agents/skills/integrating-llm
Command: npx skills add https://github.com/tomada1114/quick-reply-drill --skill integrating-llm-tomada1114

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve? Integrating a language model into an application without leaking vendor SDK details everywhere is hard: timeouts hang, errors arrive unclassified, and structured outputs pass schema checks while being useless. This Skill defines how to build and maintain a vendor-neutral LlmPort layer under src/ai/ so providers can be swapped with a bounded edit. ## Core Features & Use Cases - Port vs. adapter boundaries: Defines what belongs on the vendor-neutral LlmPort interface versus construction-time adapter configuration, with ESLint and module-graph gates keeping SDK imports inside src/ai/adapters/. - Two-layer structured output validation: Sends a JSON Schema derived from the caller's Zod schema to the provider, then re-validates the answer with safeParseAsync so refinements the conversion dropped still fail as ERR_LLM_INVALID_OUTPUT. - Deadline and error mapping: Composes per-attempt timeouts, a total adapter deadline via AbortSignal.any, and caller signals, and maps every provider failure onto the ERR_LLM_* union by caller remedy. - Use Case: When adding a second provider adapter, follow references/adding-an-adapter.md to implement the port, wire the contract suite in tests/ai-port.test.ts, and update the gate files without touching application code. ## Quick Start Ask the AI to add a new LLM provider adapter under src/ai/adapters/ following the integrating-llm guidelines and its contract test harness.

Frequently Asked Questions about integrating-llm

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I add a new LLM provider adapter to a TypeScript app?▼

Create a directory under src/ai/adapters/<vendor>/ implementing the existing LlmPort interface, taking construction-time options including a fetch override. Then add one describeLlmPortContract call in tests/ai-port.test.ts and update the gate files like eslint.config.mjs and src/server/composition.ts.

How do I validate LLM structured output with Zod?▼

Convert the caller's Zod schema to the provider's JSON Schema format and send it, then validate the returned answer again with safeParseAsync. The second pass catches refinements and brands that JSON Schema conversion silently drops, surfacing failures as ERR_LLM_INVALID_OUTPUT.

Why does my LLM request hang instead of timing out?▼

An SDK per-attempt timeout often clears when response headers arrive, leaving a slow body unbounded. Compose a total deadline into the request signal with AbortSignal.any so firing it cancels the transport, and never rely on a Promise.race timer that leaves the socket open.

Can I import the Vercel AI SDK outside the adapter layer?▼

No. The SDK, including the vendor-neutral ai core package, is importable only under src/ai/adapters/. ESLint boundaries rules and tests/boundaries.test.ts enforce this so the port remains an interface a second vendor could implement.

How do I test an LLM adapter without network access?▼

Substitute the transport, not the adapter: pass a fetch override that answers hand-written fixture bodies for the provider URL and throws for any other. This keeps the real adapter under test while guaranteeing CI never reaches the network or needs a credential.

When should a failure map to ERR_LLM_UNAVAILABLE versus other codes?▼

Map errors by what the caller can do, not by provider or HTTP status. Unrecognized failures fall to ERR_LLM_UNAVAILABLE (retry later), aborts become ERR_LLM_TIMEOUT, and rejected prompts or invalid outputs become ERR_LLM_INVALID_OUTPUT since they are re-prompted, not retried.