Skip to main content
Handbook/Amplify/Chapter 64 · Model Calls

Talking to a Model

Share

Share this page

Pass it to someone who needs it.

Key takeaway: Call a model like any other service

Part 7 of 15 · Amplify

Build the AI into your product

Your app runs now, but most apps worth building do something ordinary code cannot: they think. This part puts real intelligence inside your product, calling a model, grounding it in your own data, and letting it act, without it going off the rails.

By the end of this part, you can:

  • Call a model from your app with cost and latency under control
  • Ground the AI in your own data with RAG, so it stops guessing
  • Add an in-app agent that uses tools, when a call is not enough
  • Make an AI feature fail safely instead of confidently
Done:Build·You are here: Amplify·Next:Debug

Until now, AI was the tool you built your app with. In this part it moves inside the app, so your product can ask a model a question in plain language and act on the answer. That is not magic; it is an API call, text in and text out, with real cost, latency, and limits. This chapter gets you making that call from your product, correctly.

7.1.1A model is a service you call

A model call is just another service call. You send a prompt, your text and instructions, over an API, and you get text back. Nothing more mysterious than that.

So treat it like any external service you already rely on. It can be slow, it can fail, and it charges you for every call. Wrap it with the same care you give any other outside dependency.

7.1.2Feed the right context, and mind the tokens

The model knows only what you put in the prompt this call. It has no memory of your app, your database, or your last request, so the context it needs has to travel with every message.

That context is not free. Text is measured in tokens, roughly chunks of a few characters, and you pay per token while the reply gets slower as the prompt grows. Send what the task needs, not everything you have. You do not have to send everything to one model, either; a common way to cut cost is model routing, sending each request to the cheapest model that can handle it (a strong model for the hard requests, a small cheap one for the simple ones).

Rule of thumb: if you would not paste it into the message by hand, do not stuff it into the prompt.

7.1.3Stream the answer so it feels fast

A model writes its reply a piece at a time, and a long answer can take many seconds. Make the user stare at a spinner for all of it and your app feels broken.

Streaming sends each piece the moment it is generated, so words appear on screen as the model writes them. The total wait is the same, but it feels fast because the user sees progress from the first word.

Without streaming the user waits for the whole reply; streaming shows words as they arrive.

7.1.4Do not lock into one model

Models change fast, and the best one for your job this month may not be the best next month. So never scatter one model's name and address across your code, or switching means a painful hunt.

Put the call behind one thin layer your app talks to, the same adapter habit you use for any external service. Point that layer at a router like OpenRouter, which reaches many models and providers behind a single call. If you already run on one of the big clouds, its own model service is a third path that hosts foundation models behind that same layer. Switching then becomes a change of settings, not code.

All three paths call a model someone else hosts, which is the right default. If you ever have a real reason, cost at scale, privacy, or an offline need, you can instead run your own open-source model: you rent a GPU server and serve the model with an inference server, and quantization shrinks a model to run on cheaper hardware. Be honest about the money, though: a GPU is expensive and sits idle unless it is busy, so self-hosting only pays off once you have enough steady traffic to justify it, and until then a hosted API is cheaper and simpler. Hand this to your agent when the reason is real, not before.

// One thin layer between your app and any model. // Swap MODEL or the URL; the rest of your app never changes. export async function askModel(prompt: string) { const res = await fetch( "https://openrouter.ai/api/v1/chat/completions", { method: "POST", headers: { Authorization: `Bearer ${process.env.OPENROUTER_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: process.env.MODEL, // switch models here messages: [{ role: "user", content: prompt }], }), }, ); const data = await res.json(); return data.choices[0].message.content; // the text back }

Your agent writes this; you read it. This is the bare shape, text in as messages and text back as content; the prompt below adds streaming and error handling.

This prompt hands the whole setup to your agent:

Ready prompt
Act as a senior AI engineer wiring my app's first model call. Put it behind one thin adapter so the rest of my app calls askModel(prompt) and nothing else knows which model or provider sits behind it. Requirements: - Route through OpenRouter so I switch models by changing one config value, never my code. - Stream the reply so the user sees words appear instead of waiting on a spinner. - Send only the context the task needs, and keep the API key in an environment variable. - Handle a slow or failed call cleanly, with a timeout and a clear message, not a crash. My app and what I want the model to do:

Do this now: paste the prompt and have your agent build the adapter, then call askModel with one real question from your app and watch the answer stream back.

Mahmoud Zalt

Mahmoud Zalt

Software engineer, 16+ yrs · built Sistava.com in 3 months, idea to production, using these methods

Resources
Contribute
Donate

Support my work

A small tip keeps the free work coming.

© 2026 Mahmoud Zalt. Free to read, not to republish.
Copyright & license