Lesson 4 of 6

Build an AI chat

Add AI to an app without API keys or billing code. VibeOS runs the model on the signed-in person's plan, so your job is a good conversation and clear messages when something gets in the way.

15 minvos.aicanUse

What you'll build

Pocket Assistant: a chat window that remembers your conversation, shows a typing indicator and explains plainly when AI isn't available.

You'll need

Lessons 1 and 2, and to be signed in to the IDE (AI runs on your plan).

You'll learn

  • How to turn on AI for your app
  • How to send a conversation and show the reply
  • How to check whether AI is available before people type
  • How to turn errors into helpful messages
Peek at the end result first, or build it step by step below.

How AI works in VibeOS

You send a list of messages; you get the reply back as text. Each message has a role: "system" sets the assistant's personality, "user" is the person and "assistant" is earlier replies. The AI doesn't remember anything between calls, so you send the conversation so far every time.

Try it before writing any code

Turn on AI in the Info tab, then type this in the IDE's Console:
javascript
await window.vos.ai.chat([{ role: "user", content: "Say hi in five words" }])

Step 1 — Turn on AI

1

Add the ai permission

In the Info tab, tick AI. Your manifest gets "ai": true. Keep file access with empty folder lists: the chat is saved in the private folder.

javascript
var FILE = "chat.json";
var SYSTEM = { role: "system", content: "You are a friendly, concise assistant inside a VibeOS app." };
var dir = null;
var messages = [];  // [{ role: "user" | "assistant", content }]
var busy = false;

Step 2 — Send a message

2

Call vos.ai.chat with the conversation

Add the person's message, show "Thinking…", then send the system prompt plus the last 20 turns. Sending only recent turns keeps long chats fast. If the call fails, the question goes back in the text box so nothing is lost.

javascript
function send(text) {
  if (busy || !text.trim()) return;
  busy = true;
  messages.push({ role: "user", content: text.trim() });
  render(true);
  // Send the system prompt plus the most recent turns.
  var history = [SYSTEM].concat(messages.slice(-20));
  window.vos.ai.chat(history).then(function (reply) {
    messages.push({ role: "assistant", content: reply });
    showNotice("");
    save();
  }).catch(function (err) {
    // Put the question back so nothing is lost, and explain what happened.
    var failed = messages.pop();
    $("input").value = failed.content;
    showNotice(friendly(err.message));
  }).then(function () {
    busy = false;
    render(false);
  });
}
Checkpoint: ask "What's a haiku?" and a reply appears under "Thinking…".

Step 3 — Handle limits kindly

3

Explain what went wrong

AI can be unavailable for ordinary reasons. Errors arrive as plain Error objects, so look at err.message and say what the person can do about it:

SituationWhat to tell people
Not signed inSign in to VibeOS to use AI.
Plan doesn't include AIAI chat isn't included in your current plan.
Out of creditsYou're out of AI credits for now.
Too many requestsWait a moment and try again.
OfflineCheck your connection.
javascript
// Turn SDK error messages into something a person can act on.
// (Errors arrive as plain Error objects: check err.message, not err.code.)
function friendly(message) {
  var m = String(message || "");
  if (/disabled/i.test(m)) return 'AI is switched off for this app. Add "ai": true to its permissions.';
  if (/sign.?in|auth/i.test(m)) return "Sign in to VibeOS to use AI.";
  if (/credit|quota/i.test(m)) return "You're out of AI credits for now. They refill with your plan.";
  if (/plan|upgrade/i.test(m)) return "AI chat isn't included in your current plan.";
  if (/rate|too many/i.test(m)) return "That's a lot of messages. Wait a moment and try again.";
  if (/network|fetch|offline/i.test(m)) return "You seem to be offline. Check your connection.";
  return "The AI couldn't answer: " + m;
}

function showNotice(text) {
  $("notice").textContent = text || "";
  $("notice").hidden = !text;
}
4

Check before they type

vos.ai.canUse("chat") answers "can this person use AI right now?" without spending anything. Call it on start so the notice shows before someone writes a long question.

javascript
function checkAccess() {
  // canUse answers "can this user chat right now?" before they type.
  return window.vos.ai.canUse("chat").then(function (res) {
    showNotice(res.ok ? "" : (res.message || friendly(res.code)));
  });
}
Checkpoint: sign out of the IDE and click Run. A yellow notice asks you to sign in.

Step 4 — Remember the chat

5

Load on start, save after each reply

The conversation is just a list, so it's saved exactly like the to-do list in Lesson 2: one JSON file in the private folder.

javascript
function start() {
  window.vos.app.getInfo().then(function (info) {
    dir = info.sandboxPath;
    return window.vos.fs.readFile(dir, FILE);
  }).then(function (text) {
    messages = text ? JSON.parse(text) : [];
    render(false);
    return checkAccess();
  }).catch(function (err) { showNotice(friendly(err.message)); });
}
Checkpoint: chat a little, then click Run. The conversation is still there, and chat.json shows in the Files tab.

Practice

Give it a personality

Change the system prompt so the assistant answers in a different style, then ask it something.
Show a solution
javascript
var SYSTEM = {
  role: "system",
  content: "You are a pirate. Answer in one or two sentences, in pirate speak."
};

Add quick-start buttons

Show three suggestion buttons (like "Summarise my day") when the chat is empty.

Each button calls send() with a ready-made question.

Summarise a note from Lesson 3

Add a button that reads a note from Documents/Notes and asks the AI for a three-bullet summary.

Add "home/Documents/Notes" to read permissions, read a file, then send its text in a user message.

Recap

  • Turn on AI with "ai": true. No API keys, and it runs on the person's plan.
  • Send the whole recent conversation each time; the AI doesn't remember.
  • Use canUse() on start and explain errors in plain words.
  • Save the conversation as JSON in the private folder.
Up next · Lesson 5Live weatherCall a web API safely and show live data.

Full details on limits and messages are in the vos.ai reference.