Build your first AI project with REST, CLI, TypeScript, or Python. Try eligible requests without an account or payment method while the shared free allowance is available.

You do not need to train a model to build something useful with AI. A game can ask whether a move is sensible. A website can explain a result. A Python script can turn an idea into a first draft.

OpenMates offers a REST API, a command-line interface (CLI), and SDKs for TypeScript and Python. Pick the interface that fits your project. You can try eligible guest requests without an account, API key, or payment method while the shared free allowance is available.

Text or a decision?

Use a chat for generated text: an explanation, story, or feedback in sentences. Use ai.decide when your code needs a structured judgment. Supply state with the facts your program knows and questions with the judgments you want. Each question has a type, instructions, and, where needed, criteria.

  • noul: a yes/no judgment as a probability between 0 and 1 in the answer's noul field. Near 0.5 means uncertainty.
  • choice: choose among categories you name in a criteria object. The answer includes choice and category probabilities.
  • score: evaluate against an ordered rubric in a criteria list. The answer includes score, a legend, and probabilities for the levels. Scores run from 0 to the number of levels minus 1.

Your game still owns its rules. Validate the result, handle uncertainty, and keep a simple fallback action. A probability is the model's estimate from your information, not a guarantee about the world.

TypeScript: add AI to your app

Install the package in your project:

npm install openmates
import { OpenMates, OpenMatesSignupRequiredError } from "openmates";

const om = new OpenMates();
try {
  const reply = await om.chats.send("Suggest a friendly name for a space game.");
  console.log(reply.content);
} catch (error) {
  if (error instanceof OpenMatesSignupRequiredError) {
    console.log(error.message);
  } else {
    throw error;
  }
}

new OpenMates() automatically uses guest access without a key and your account when OPENMATES_API_KEY is configured. You need no AI provider key.

Now ask for a structured decision:

const result = await om.apps.ai.decide({
  state: { energy: 2, maximumEnergy: 10, enemiesNearby: false },
  questions: {
    rest: {
      type: "noul",
      instructions: "Should the character rest before exploring?",
      criteria: {
        true: "Energy is low and resting is safe.",
        false: "Energy is sufficient or resting is unsafe."
      }
    }
  }
});
console.log(result);

The skill response wraps the decision in data; named answers are in data.answers. Inspect the answer before connecting it to game behavior. Missing facts can change the judgment.

Python: the same idea in a script

pip install openmates
from openmates import OpenMates, OpenMatesSignupRequiredError

om = OpenMates()
try:
    reply = om.chats.send("Suggest a friendly name for a space game.")
    print(reply.content)
    result = om.apps.ai.decide({
        "state": {"energy": 2, "enemiesNearby": False},
        "questions": {
            "rest": {
                "type": "noul",
                "instructions": "Should the character rest before exploring?"
            }
        }
    })
    print(result["data"]["answers"]["rest"])
except OpenMatesSignupRequiredError as error:
    print(str(error))

OpenMates() uses your account when OPENMATES_API_KEY is configured and otherwise uses guest access for eligible requests.

CLI: try it from your terminal

The npm package includes the CLI. Install it globally to use openmates directly:

npm install -g openmates
openmates chats new "Suggest a friendly name for a space game."

Run a decision with JSON input:

openmates apps ai decide --input '{"state":{"energy":2,"enemiesNearby":false},"questions":{"rest":{"type":"noul","instructions":"Should the character rest before exploring?"}}}'

On a fresh installation, eligible requests can use guest access. An existing login or configured API key can use account access instead.

REST: call it from any language

An SDK wraps HTTP requests in convenient methods. You can also call REST directly, without an API key or a custom identity header:

curl https://api.openmates.org/v1/anonymous/apps/ai/skills/decide -H 'Content-Type: application/json' -d '{"state":{"energy":2,"enemiesNearby":false},"questions":{"rest":{"type":"noul","instructions":"Should the character rest before exploring?"}}}'

No identity setup is needed. Keep account API keys on a trusted server when you later add account access.

A picture can be part of a decision

You can also prototype image decisions with Jev 1.14. For example, draw a simple game board, save it as board.png, and ask whether there is a clear path to its exit. This judges the picture; it does not generate or edit an image.

In Node.js, read the file and encode its bytes:

import { readFile } from "node:fs/promises";
import { randomUUID } from "node:crypto";
import { OpenMates } from "openmates";

const om = new OpenMates();
const ref = randomUUID();
const image = (await readFile("board.png")).toString("base64");
const result = await om.apps.ai.decide({
  state: { board: ref },
  questions: {
    clear_path: {
      type: "noul",
      instructions: "Is there a clear path to the exit on the game board?"
    }
  },
  assets: { [ref]: { type: "image", format: "png", data_base64: image } }
});
console.log(result);

In Python, the same request looks like this:

import base64
import uuid
from pathlib import Path
from openmates import OpenMates

om = OpenMates()
ref = str(uuid.uuid4())
image = base64.b64encode(Path("board.png").read_bytes()).decode("ascii")
result = om.apps.ai.decide({
    "state": {"board": ref},
    "questions": {
        "clear_path": {
            "type": "noul",
            "instructions": "Is there a clear path to the exit on the game board?"
        }
    },
    "assets": {ref: {"type": "image", "format": "png", "data_base64": image}}
})
print(result["data"]["answers"])

The assets map carries the actual image bytes. Its UUID key is a reference: put it in a string value in state, instructions, or criteria wherever the image belongs. Every image must be referenced. Use jpg or jpeg instead of png for a JPEG file. You do not need a provider key or a special header; OpenMates handles the provider call.

This is an experimental feature for prototypes. Prepare a still PNG or JPEG locally, with both sides between 280 and 1568 pixels and a file size of at most 1 MiB. A request supports at most four images and 4 MiB of decoded image data in total. State and questions must fit 16 KiB, separately from images; the full JSON request must fit 6 MiB. A small board image is a good starting point.

Image requests go directly to TypeSafe, without OpenRouter fallback, and their image tokens use the same free allowance or account credits. Handle allowance and provider errors just as in the earlier examples. This inline path does not fetch image URLs or save an upload; the separate account upload flow still needs signup. Send only pictures you are comfortable sharing with the provider. Transient processing by OpenMates does not promise zero retention by TypeSafe.

How the free allowance works

Free testing draws from a shared service allowance with daily, weekly, and monthly limits, alongside a limit for your public IP. There is no fixed number of promised free requests: requests cost different amounts, and other people use the shared pool too. People on the same school Wi-Fi can share a public-IP limit.

The daily window resets at midnight UTC. A daily reset does not remove weekly or monthly limits, and provider availability can still affect requests.

Check status with await om.anonymous.status() in TypeScript, om.anonymous.status() in Python, or REST:

curl https://api.openmates.org/v1/anonymous/free-usage/status

Status is guidance, not a reservation. A positive remaining percentage does not mean every request will fit: a request can need more headroom than its final charge. Keep requests short and handle refusals.

When a guest request cannot fit the allowance, the API returns HTTP 429, detail.signup_required: true, and a readable message explaining that an account is needed to continue. Both SDKs expose OpenMatesSignupRequiredError, as shown above. Show the message instead of endlessly retrying. A provider outage is separate and can return HTTP 503; signup does not fix it.

You do not need a payment method to try eligible free operations. Guest access supports text chats and eligible skills that return results inline without changing account data. Uploads, saved account content, and other account actions need signup. After signup, normal account credits and limits apply; an account does not promise unlimited free use.

Build one small thing

Start with a game character that asks for advice, a page that explains a result, or a script that evaluates options. Use harmless inputs and avoid private information in experiments. Print the answer, understand its shape, then connect it to your own logic.

Explore the developer documentation and the source code. You can begin with a few lines and let your project grow from there.

Questions or feedback? marco@openmates.org