3 Topics
Chapter•55 Minutes

2. JavaScript Setup, Providers, and Model Fundamentals

Set up a safe Node.js project, understand model APIs and messages, compare providers, and create a reusable model boundary.

Create a Safe Node.js AI Project

Use a supported Node.js LTS release, a package manager, environment variables, and a server-side module layout. Keep provider-specific code behind a small adapter so your application logic does not depend on one SDK everywhere. Separate development, test, and production configuration. Add linting, type checking if using TypeScript, tests, and a .env.example containing placeholders rather than secrets.

For JavaScript projects, JSDoc can improve editor support; for larger systems, TypeScript is especially useful for tool arguments, structured outputs, and message-state models.

Note

Do not commit .env files containing secrets. Use a secret manager or protected deployment environment for production.

Minimal project structure
src/
  app.js
  config/env.js
  ai/provider.js
  ai/prompts.js
  ai/schemas.js
  tools/
  retrieval/
  evals/
  tests/
.env.example
package.json
💡 Keep provider calls, prompt definitions, tools, retrieval, and evaluations in separate modules. This structure makes it easier to test policy and domain behavior without calling a paid model for every unit test.
Key Takeaways
  • Use server-side configuration for secrets.
  • Separate prompts, tools, retrieval, and evaluation from route handlers.
  • Test domain logic without depending on live provider calls.
Knowledge Check

Why place provider calls behind an adapter?

Messages, Roles, Tokens, and Context Windows

A model request typically contains instructions, conversation messages, optional tool definitions, generation settings, and output constraints. Provider APIs differ in terminology and semantics, so treat a provider's current API reference as authoritative. Tokenization is not the same as word count: punctuation, code, and multilingual text may use different token counts.

The context window limits how much input and output can be processed in one request. Long history increases cost and can reduce relevance. Use concise conversation summaries, retrieve only relevant documents, cap output length, and avoid sending secrets or unrelated personal data.

Diagram
Provider-neutral request shape
const request = {
  instructions: "Answer using only the supplied policy context.",
  input: [
    { role: "user", content: "Can I return an opened item?" }
  ],
  metadata: { feature: "returns-help" }
};
💡 This is an illustrative provider-neutral shape, not a direct SDK call. Map it to the current provider API you choose, and document any semantic differences in roles and instructions.
Key Takeaways
  • Token counts are not equivalent to word counts.
  • Context limits apply to input and output.
  • Use provider documentation for exact request semantics.
Knowledge Check

Why should an application avoid sending the entire conversation history on every request?

Provider Abstraction and Model Selection

A provider abstraction should standardize only what your product actually needs: text generation, streaming, structured output, tool calls, embeddings, or image input. Do not flatten meaningful differences between providers into a misleading lowest-common-denominator interface. Record model identifier, version or snapshot when available, configuration, latency, token usage, and evaluation results.

Model choice is a product decision. Compare task quality, latency, availability, context length, tool reliability, multimodal capability, data handling terms, and cost. Keep a fallback policy for temporary outages, but do not silently downgrade to a model that fails your quality or privacy requirements.

Small application adapter
export function createTextGenerator(client, model) {
  return {
    async generate({ instructions, input }) {
      const result = await client.responses.create({
        model,
        instructions,
        input
      });
      return {
        text: result.output_text,
        responseId: result.id
      };
    }
  };
}
💡 This example illustrates an adapter around a Responses-style API. Verify current SDK syntax and response fields against official documentation before shipping; provider APIs evolve.
Key Takeaways
  • Hide provider-specific response parsing behind an adapter.
  • Evaluate models on representative tasks.
  • Fallbacks must preserve safety, privacy, and minimum quality requirements.
Knowledge Check

What should be recorded when comparing model choices in production?