Skip to main content

Getting Started with AI

Level: Beginner · Time: 45–60 min · Category: Guide

Tags: OpenCode · OpenWork · VS Code · Open WebUI · Agents · Prompting

Work through this once and you will have an API key, an AI assistant that can read and edit your projects, and a sense of how to work with the models we host. Every tutorial on this site starts from here.

You do not need any prior experience with AI tools. You will use a terminal for a handful of commands. Each one is written out for you to copy, and we discuss its use in Step 1.

Short on time?

Step 1 and Step 3 are enough to begin any tutorial. Come back for Step 4 to learn more about how to best use an assistant. If you are not getting desirable results, this is where to start.

The four pieces​

Four things sit between what you type and the code that comes back. It is worth learning which is which, because when something goes wrong the fix is nearly always in one specific piece.

PieceWhat it isWhere it comes from
1The toolThe program you install and talk to. It reads your files, edits code, and runs commands.You pick one in Step 2.
2Your API keyProves the request is yours. Treat it like a password.The Voyager portal.
3The gatewayDirects interactions to: https://openai.rc.asu.edu/v1. It speaks the OpenAI-compatible protocol, so standard tools work with it unchanged.Research Computing.
4The modelThe AI itself. It interprets your request and decides what should happen next.Runs on RC hardware.

The tool and the model work as a pair. The model decides what should happen, such as writing a file, or running a command. Then, the tool carries it out on your machine, with supplied guardrails. While a model alone can get you far, the tool lets the model do the work. A model that cannot call tools will discuss your code happily and never change a line. Step 1 will help you make sure your model can use what you need. The rules you provide to the tool in Step 3b strictly limit what the model can do.

Why does "OpenAI-compatible" matter?

OpenAI published the language, or request format, that most AI tools now speak. Our gateway speaks the same format, so a tool built for OpenAI works with our models once you change two settings: the gateway and the API key. That is the whole trick behind every setup on this page, and it means what you learn here transfers to other providers.

Your prompts stay on RC hardware

These models run in our data center, so prompts and code sent through the RC gateway are not passed to a commercial AI provider. Follow your unit's normal data-handling rules for regulated or sensitive data. Reach out to us here if you need to discuss the use of your data on AIR.


Step 1: Get your API key and a model ID​

Everything else needs these two values.

  1. Log into the ASU VPN.
  2. Log in to the Voyager portal with your ASURITE credentials. If you do not yet have an account, see Requesting an Account.
  3. Open the LLM Access tab.
  4. Click Create Key. Copy the key somewhere safe — treat it like a password.
  5. On the LLMs sub-tab, review the available models and copy one model ID exactly as written (for example muse-glimmer-30b). The ID is what tools want, not the friendly display name.

The LLM Access tab holds more than LLMs. There are sub-tabs for Image, Video, Embeddings, Speech, and Usage, plus the two this guide uses: opencode (a configuration file generator for the OpenCode tool) and Skills (a growing library that enables AI assistants to help you with HPC and research tasks).

Full API details, including code samples, are in the LLM API Access guide.

Read the model badges​

Each model in the list carries capability badges and a context size. They are easy to scroll past, but they determine what a model can do for you:

BadgeWhat it meansWhy it matters
ToolsThe model can call tools.Required for editing files. Without it, an assistant can discuss your code but never change it.
VisionThe model can read images.Lets you use images with the assistant. Examples include a broken layout or a whiteboard sketch.
ReasoningThe model works through a problem before answering.Better on multi-step logic. Worth the extra wait for algorithms and debugging.
ContextThe size of its context window.How much text it can hold at once. Larger is more forgiving, though quality can still drop before the limit. See Step 4 for specifics.

For coding, start with something that has Tools, Reasoning, and a large (over 100k) context. muse-glimmer-30b, qwen38-27b, and devstral2-123b all qualify.

Store your key as an environment variable​

Do this before anything else that uses the key. An environment variable is a value that your terminal gives to every program you launch. For our use, this means tools can read the key without it ever appearing in a project file, a command, or a screenshot. Remember, an API key is a password.

Where do I type this? (if you have never used a terminal)

macOS: press Cmd+Space, type "Terminal", press Enter.


Windows: press the Start key, type "PowerShell", press Enter.


Linux: press Ctrl+Alt+T.

A terminal is a place to type commands rather than click buttons. You will use it to install things and to run your projects; the tutorials always give you the exact command.

Open your shell's startup file in a text editor. You'll open ~/.zshrc on macOS, ~/.bashrc on most Linux systems (if ~/.bashrc isn't on the Linux system, try ~/.zshrc there, too.):

nano ~/.zshrc     # macOS; use ~/.bashrc on most Linux systems

Add this line at the bottom, pasting your key between the quotes and replacing the words within, then save and exit (Ctrl+O, Enter, Ctrl+X in nano):

export OPENAI_API_KEY="paste-your-key-here"

Load it into the terminal you already have open, and confirm:

source ~/.zshrc
echo $OPENAI_API_KEY # should print your key

source re-reads the startup file. This is a nice trick, as usually you would close and reopen the terminal for this.

Type the key as few times as possible

Every command you type in a terminal is saved locally, in readable text. That is why the steps above put the key in a file you edit, rather than in a command you type. For the same reason, avoid pasting it directly into curl commands, code, or anything you might commit or screenshot.

If a key does end up somewhere it should not, regenerate it on the Voyager LLM Access tab. Rotating a key takes seconds, and no one can use your old one afterwards.

Prove it works before installing anything​

This checks the key and the model ID on their own. If it fails here, nothing else can work, so we check now before moving on. The key comes from the environment variable you just set, so it stays out of the command:

The following command uses a tool called curl, which can download information from the internet, to check connectivity:

curl -sS https://openai.rc.asu.edu/v1/chat/completions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "PASTE-MODEL-ID-HERE",
"messages": [{"role": "user", "content": "Reply with exactly: RC API ok"}]
}'

A JSON response containing RC API ok means you are ready. Move to the next step if you receive this outcome.

A 401 means the key is wrong, expired, or not set in this terminal. If this occurs,
Run echo $OPENAI_API_KEY (echo $env:OPENAI_API_KEY on Windows), and see what you get back. Compare to your key directly. You have some options at that point:

  • If incorrect, go back and fix where you entered it before.
  • If empty, close and reopen your terminal. If still empty after that, read back and ensure the key is in the correct location.

A model error means the ID does not match the portal, and you must check whether you entered the above commands correctly.

On a shared machine, such as an HPC login node

Your shell replaces $OPENAI_API_KEY with the actual key before running curl, so the key sits in that command's arguments while it runs — and command arguments are visible to other users on the same machine through ps. The window is brief, but on a shared login node it is real.

To avoid it, hand the header to curl through standard input instead. printf is built into the shell, so no separate process carries the key:

printf 'header = "Authorization: Bearer %s"\n' "$OPENAI_API_KEY" | \
curl -sS --config - https://openai.rc.asu.edu/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "PASTE-MODEL-ID-HERE", "messages": [{"role": "user", "content": "Reply with exactly: RC API ok"}]}'

The assistants in this guide read the environment variable directly and never place your key on a command line, so this only applies to ad-hoc curl testing.


Step 2: Choose your tool​

All four options below reach the same RC models with the same key. The differences between them are how much they can do on their own, and whether you use a terminal or a graphical interface.

ToolSuits you ifEdits your files?InterfaceSetup
OpenCodeYou want the option our tutorials are written against.YesTerminal or desktop app10 min
OpenWorkYou would rather see an agent's plan in a window than a scrolling terminal.YesDesktop app5 min after OpenCode
VS CodeYou already work in an editor and want chat beside your code.Yes, in Agent modeEditor15 min
Open WebUIYou want to think a problem through, or you cannot install anything.NoWebsiteNone

For completing the tutorials as written, install OpenCode and move on. You can always add more later.

For general use, we suggest installing OpenCode and add OpenWork afterwards. OpenWork runs OpenCode underneath, so the second setup is mostly done once the first is.

These are not mutually exclusive, and using several is normal: Open WebUI to think a problem through, OpenCode or OpenWork to build it, VS Code to read the resulting changes. They can all share one key, so you do not have to get a new one.

Here, we will install OpenCode as our next step. If you want to explore the other tools, please refer to the appendix.


Step 3: Set up OpenCode​

OpenCode is a free, open-source AI coding assistant. You describe what you want in plain English; it reads your project, writes and edits files, and runs commands. It has a terminal interface and a desktop app that share the same configuration.

3a. Install it​

Installing directly from OpenCode's website is easiest:

curl -fsSL https://opencode.ai/install | bash

If you prefer a package manager, you can find OpenCode on several of them:

brew install anomalyco/tap/opencode   # macOS (Homebrew)
sudo pacman -S opencode # Arch Linux

Confirm the install. The following command should print a version number:

opencode --version

If you get command not found, fully quit and reopen your terminal so it picks up the new command.

3b. Generate your config in Voyager​

OpenCode needs a config file telling it where the RC gateway is, which models exist, what agents you have, and what those agents may do. You do not have to write it by hand when using AIR. Voyager builds it for you, with all fields filled in.

Go to the Voyager portal → LLM Access → opencode tab. The page has four sections, with a live preview of the resulting opencode.json on the right.

Pick a preset​

The presets across the top are ready-made teams of agents. Starting from one is easier than assembling your own:

PresetWhat you get
StarterOne primary assistant plus a reviewer. The simplest thing that works.
Full-stackA delegating tech lead with backend, frontend, API design, and two critics.
Data scienceA research lead with an ML engineer, a statistician, and leakage/figure critics.
Scientific computingAn HPC lead with CUDA/MPI implementation, numerics, Slurm, and rigor critics. Good for using with Sol.
Web designA design lead that turns mockups into UI, gated by design and accessibility critics.

Starter is the right choice for the tutorials on this site. Move to a specialized preset once you need something stronger.

Set the connection​

Most of this section is already filled in. There is one decision to make.

  • Provider key asu and display name ASU Air — leave both alone. Agents refer to models as asu/model-id, so changing the key means changing every reference too.
  • Base URL https://openai.rc.asu.edu/v1 — already correct.
  • API key — choose between Paste key inline and Environment variable.
Choose "Environment variable"

Pasting inline writes your key into the generated file in plain text. This could result in your key being discovered by others. Selecting Environment variable makes the config read OPENAI_API_KEY from the environment you set in Step 1 instead, which keeps your OpenCode config safe to store in a project folder or share with a labmate.

If you do paste inline, keep that file out of Git and regenerate the key if it ever leaks.

Select your models​

Tick the models you want available. These become the provider's model list. Two or three is plenty for now. a shorter list makes the model picker quicker to use, and you can always add more later. Ensure at least one of your models has the Tools badge, or nothing will be able to edit files.

If you are using the Starter setup, it is best if all your models have the Tools badge.

Review the agents and permissions​

The Agents section lists each agent with its own model, mode (primary or subagent), and tool permissions. A primary agent is what you use most, while a subagent is for smaller tasks. The Starter setup gives you an assistant (primary, general purpose) and a reviewer (subagent, code review). Match models to roles assigns a suitable model to each role from the ones you selected. You can add roles from the dropdown and choose which agent is the default.

Global permissions below determine what an agent can always do, must ask to do, or can never do. Permissions include read, edit, write, bash, webfetch, among others. Each permission is paired with a setting: allow, ask, or deny. The defaults are adequate for most users. The one worth noticing is external_directory. By default, we set this to deny. This ensures an agent cannot leave the folder it is working on.

Consider setting bash to ask at first

The assistant then pauses for your approval before running any command. This is slower, but reviewing its actions can help you understand what it is doing.

Save the file​

Use Copy or Download in the preview panel, then paste or move the data to somewhere OpenCode can use it:

# Global — RC models and agents available in every project (recommended)
# Make the folder:
mkdir -p ~/.config/opencode
# Then, save the file in the folder you just made as ~/.config/opencode/opencode.json.

# Per-project — save it as opencode.json in the top folder of your project

Use the global path for now. Per-project configs become useful later, when one project needs different agents or tighter permissions than the others.

What the generated file looks like

Roughly this shape, with your own models, agents, and permissions:

~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "assistant",
"permission": {
"read": "allow",
"edit": "allow",
"bash": "allow",
"webfetch": "allow",
"external_directory": "deny"
},
"provider": {
"asu": {
"npm": "@ai-sdk/openai-compatible",
"name": "ASU Air",
"options": {
"baseURL": "https://openai.rc.asu.edu/v1",
"apiKey": "{env:OPENAI_API_KEY}"
},
"models": {
"muse-glimmer-30b": { "name": "muse-glimmer-30b" }
}
}
},
"agent": {
"assistant": { "mode": "primary", "model": "asu/muse-glimmer-30b" },
"reviewer": { "mode": "subagent", "model": "asu/muse-glimmer-30b" }
}
}

Each key under models must match a Voyager model ID exactly. A field-by-field walkthrough is in the OpenCode setup guide.

3c. Open it and send a test message​

mkdir opencode-test
cd opencode-test
opencode

Type /models and press Enter, then use your arrow keys and Enter to pick a model under ASU Air. You should now be in a text box where you can speak to the assistant. Try sending:

Reply with exactly: OpenCode is connected to ASU Air.

A normal reply, with no authentication or model-not-found error, means every piece of the chain is working.

Two commands are worth knowing from the start:

  • /models: switch models.
  • /agent: switch between the agents your config defines, which is how you move from assistant to reviewer and back. Step 4 covers why you would.

Now try a real prompt. Here is an example, which you can use:

Look at the files in this folder and summarize what this project does. Do not edit anything yet.

Note that this prompt asks the assistant to look before touching anything, which is useful before starting to work.

This section is the short version

The complete OpenCode walkthrough, with every troubleshooting case, is at Set Up OpenCode with the RC LLM API.


Step 4: Why prompting and agents matter​

ASU AIR models run on Research Computing hardware, which allows us to provide them at no cost to you and keep your work within ASU. We serve a range of open-weight models. These models are often smaller and more specialized than the largest commercial frontier models. This has advantages for specialized work, such as coding and research, but it also makes good prompting especially important.

For straightforward tasks, an informal prompt may work just fine. As the work becomes more complex or novel, being explicit matters more. Instead of describing your overall goal, you want to be specific: spell out your goal, constraints, and context. You'll find, regardless of model, that you get better outcomes. Larger frontier models can sometimes infer missing context or recover from a vague request. Even for them, vague prompting is risky behavior. Smaller models may be more sensitive to these risks.

In practice, this means you should tell the model clearly what you need. You'll spend less time correcting assumptions and more time getting useful results. These are good prompting habits for any AI model, and they are particularly helpful when working with the models available through Research Computing.

What you will notice, and what to do about it​

What you will noticeWhy it happensWhat to do
It takes you literally and skips the "obvious" parts.The model does not know your undeclared intents.State the obvious. Name the file. Name the function. Say what "done" means.
It loses the thread on long, multi-part requests.Consistency can be lost in multi-step processes.One task per prompt. Finish and check it, then ask for the next.
Quality degrades in long sessions, before you hit any limit.Effective context is shorter than the advertised window, for all models.Start a fresh session per task. Point at one to three specific files rather than "the project".
It drifts from your conventions.It cannot remember across sessions.Write the conventions into AGENTS.md (below) so they are supplied every time.
It gets site-specific details wrong — wrong partition, wrong module, invented #SBATCH flags.It has never seen our clusters.Install the RC skills that describe how things work here.
File edits fail or repeat while chat works fine.Tool calling is not a universal feature.Switch to a model with the Tools badge.
It states wrong things confidently.Hallucination is a risk with AI.Ask for a plan before code, run the code, and read the diff.

The prompt skeleton​

This shape suits any request beyond a one-liner. It is more than you might strictly need to get something done, but it is usually the difference between one attempt and five.

CONTEXT
You are helping me build <what> in <language/framework>. I am a beginner.

GOAL
<One sentence. One outcome.>

FILES
Work only in <exact filenames>. Do not create new files unless I ask.

CONSTRAINTS
- <library or version limits>
- <things to keep simple, e.g. "no database, use a JSON file">
- Keep it under ~150 lines.

DONE MEANS
- I can run <exact command> and see <exact result>.
- <specific behavior a test would check>

PLEASE
1. Show me your plan first, in 3-5 bullets.
2. Wait for me to say go.
3. Then write the code and explain the two lines I am most likely to want to change.
The same request, before and after

Vague:

make me a csv viewer

You will get something back, but it will be built on guesses. You could see invented column names, a database you did not ask for, a fixed file path, and no instructions for running it.

Specific:

CONTEXT
You are helping me build a small Streamlit app in Python. I am a beginner.

GOAL
Show a CSV file's contents in a web page with a filter box.

FILES
Work only in app.py.

CONSTRAINTS
- Use streamlit and pandas only.
- The user uploads the CSV through the page. Do not read from a fixed path.
- No database, no config files.
- Under 80 lines.

DONE MEANS
- I run `streamlit run app.py`, upload a CSV, and see the first 20 rows in a table.
- Typing in the filter box narrows the table to matching rows.
- If no file is uploaded, the page says so instead of crashing.

PLEASE
1. Show me your plan first in 3-5 bullets, then wait for me to say go.
2. After I approve, write app.py.
3. Tell me which line to edit to change the number of rows shown.

The second prompt is not longer for the sake of it. Each line removes a decision the model would otherwise have had to guess at.

Three places to put structure​

Prompting well is a day-to-day habit. Luckily, we can do some work up-front so you don't repeat yourself. These helper files help you avoid retyping the same context every session:

LayerWhat it holdsWhen it loads
AGENTS.mdYour project's facts and rules.Every session, automatically.
AgentsSaved assistant roles with their chosen model and permissions.When you switch to one (/agent, @name).
SkillsSpecialized know-how, such as how Slurm works here, how Streamlit works, etc.On demand, when a task calls for it.

Write an AGENTS.md​

AGENTS.md is a plain markdown file in your project root that OpenCode, as well as many other assistant tools, reads at the start of every session. Whatever is in it comes along as context every time, without you asking.

The easiest way to start one is to run /init inside OpenCode in your project. This will let it draft for you based on what you just did. Then, you need to review and edit. Keep it short and specific: a long file starts to fill up the context your assistant can handle.

Here is an example AGENTS.md, based on ongoing development of a result parser.

AGENTS.md
# Project: Lab CSV Explorer

## What this is
A single-page Streamlit app for previewing lab result CSVs. Beginner-maintained.

## Commands
- Run: `streamlit run app.py`
- Install: `pip install -r requirements.txt`

## Conventions
- All app code lives in app.py. Do not split into modules.
- Config comes from environment variables, never hardcoded.
- Standard library and the packages in requirements.txt only — ask before adding a dependency.

## Rules for you
- Show a plan before writing code.
- Change one thing at a time.
- Never commit .env or any API key.

You can also keep a personal one at ~/.config/opencode/AGENTS.md that applies across all your projects. This is where you can put behaviors you always want, like "explain things to me as a beginner" or "always show me the command to run."

Use agents instead of one big prompt​

An agent is a saved role: a system prompt, a model, and a set of permissions, stored under a name. Rather than retyping "you are a careful code reviewer, do not edit anything, focus on…", you switch to your reviewer agent with /agent.

This is what makes specialized models shine. A general-purpose prompt leaves the model to work out how to approach a task; a narrow agent tells it. A smaller model given one well-defined job, with the tools it should not use switched off, tends to do better than a larger model given vague instructions.

If you used a Voyager preset in Step 3b, you already have agents. The Starter preset gives you two:

  • assistant (primary): the one you talk to. Press Tab to cycle primary agents, or use /agent.
  • reviewer (subagent): a specialist the assistant can call, or that you invoke yourself by typing @reviewer in a message.

The critic agents in the other presets follow the same idea. A separate read-only pass, by an agent whose only job is finding problems, catches things the agent that wrote the code will not. You can think of it as bringing an editor on board. Editors have a habit of noticing things the original author doesn't.

Add your own​

The quickest route to create your own agent with AIR is back in Voyager. Navigate again to the opencode tab under the AI LLMs section. Add a role, pick its model, regenerate your config, and save. If you want to create one locally instead, this command asks where to save it and writes the file for you:

opencode agent create

You can also write the file yourself. Global agents go in ~/.config/opencode/agents/, per-project agents in .opencode/agents/. Whatever you name the file in the agents folder actually names the agents in the editor:

~/.config/opencode/agents/explainer.md
---
description: Explains existing code to a beginner without changing it
mode: subagent
temperature: 0.1
permission:
edit: deny
write: deny
bash: deny
---

You explain code to a researcher who is new to programming.

For the file you are given:
1. One sentence on what it does overall.
2. A walkthrough in the order the code actually runs, not top to bottom.
3. Any line that would surprise a beginner, and why it is written that way.

Use plain language. Define jargon the first time you use it.
Never modify the file. If something looks like a bug, say so at the end and stop.

The permission block is what makes a read-only agent worth trusting. With edit: deny it cannot change your code, so you can let it run without watching it closely.

Alongside the preset's reviewer, two more agents can make things smoother: an explainer like the one above, and a test-writer that writes tests and touches nothing else.

Add skills for HPC and research work​

A skill is a reusable instruction file an agent loads on demand, only when a task calls for it. AGENTS.md is always in context and agents are roles you switch into. Skills sit on the shelf until they are needed, which is what you want when context is in short supply.

Research Computing publishes a library of these for use with RC resources, such as the use of Sol. Go to Voyager → LLM Access → Skills. They are written in OpenCode's SKILL.md format and describe how things work on our clusters, including partitions, QOS, filesystems, and the module system. This is the kind of information a general-purpose model has no way of having. The following skills are presently available, and more are in development:

SkillWhat it covers
Slurm batch scriptsCorrect #SBATCH headers, array jobs, and interactive sessions, with the site's partitions and QOS.
Diagnose stuck and failed jobsA triage path from "it's still PENDING" or "it died at 3am" to the actual cause.
GPU right-sizing and utilizationProving a GPU is actually busy before asking for more of them.
Python environments on HPCEnvironments that survive quotas, batch shells, and whoever inherits the project.
Containers on HPC (Apptainer)Portable, reproducible software stacks that run unprivileged on compute nodes.
Research data layout and quotasWhich filesystem, what layout, how to check usage — planning only, no data touched.
Parallel performance and scalingFind the real bottleneck, then optimize, with scaling studies that hold up in a paper.
Reproducible computational researchEvery number in the paper traceable to a commit, a config, and a job ID.
Publication-quality figuresFigures legible at column width, honest about uncertainty, and readable to everyone.

To install one, on Voyager, navigate to the skill, use Copy or Download, and put it where OpenCode looks (.opencode/skills) Each skill shows its exact path on the page:

# Example: the Slurm batch scripts skill, in your project
mkdir -p .opencode/skills/slurm-job-scripts
# save the file inside that folder as SKILL.md
Rename the download

Downloads are named like slurm-job-scripts.SKILL.md so several can share one downloads folder. Rename the file to exactly SKILL.md once it is inside its skill folder.

Each skill states what it does, when to use it, and where its safety boundary sits. The Slurm skill, for example, reads and writes files inside your project and runs read-only cluster queries (sinfo, squeue, sacctmgr show). It never submits or cancels jobs. Instead, it hands you the sbatch command and you decide whether to run it. Read the safety boundaries before installing any skill, the same way you would check what any new tool is allowed to touch.

If you want to see why you need skills, ask for a Slurm script without the skill installed and then with it. Without, you get generic directives that look plausible; with, you get directives that work on Sol.

Pair the Scientific computing preset with these skills

If you work on the clusters, the Scientific computing preset from Step 3b together with the Jobs & scheduling skills is a combination worth setting up once and keeping.

The habits, in brief​

  1. One task per prompt. Run it, check it, then ask for the next.
  2. Say what "done" means, in terms you can verify yourself.
  3. Ask for a plan before code on anything touching more than one file.
  4. Name exact files. "The project" is too much context; app.py is about right.
  5. Start a fresh session for a new task rather than continuing a long one.
  6. Read the diff. You are the reviewer. Treat the output as a draft from a fast, confident colleague who has never seen your data.
  7. Run the read-only reviewer agent before you commit. It costs one command.
  8. When a reply goes wrong, fix the prompt rather than arguing with it. Rewriting your original request usually beats three rounds of "no, not like that."
  9. When you correct the same thing twice, write it down, in AGENTS.md if it is a project rule, in an agent if it is a role, in a skill if it is specialized know-how.

Step 5: Practice on something fun​

Before starting a real project, spend an hour on something with an obvious right answer. A puzzle you can watch run tells you more about how your model behaves than a form-and-database app does, and it is a lot more enjoyable to debug. If you cannot think of one, we can provide a few.

Each prompt below is ready to copy. They all produce a single self-contained index.html and install nothing at all: save the file, double-click it, and it opens in your browser. The sudoku solver is the one to start with.

Sudoku solver with a visual UI​

A good first project: the definition of done is precise, breakage is obvious on sight, and the step-by-step solving animation requires the model to write genuine algorithmic code rather than something that merely looks right.

CONTEXT
You are helping me build a browser sudoku app. I am a beginner. Everything must live in
one file, index.html, that I can open by double-clicking it. No build step, no npm,
no external libraries or CDN links.

GOAL
A 9x9 sudoku board with a button to generate a random puzzle and a button to solve it
one box at a time, visibly.

DONE MEANS
- I open index.html and see a 9x9 grid with clear 3x3 block borders.
- "New Puzzle" fills in a random solvable puzzle. Given numbers are bold and dark;
empty cells are blank.
- "Solve" fills the empty cells one at a time with a short delay so I can watch it,
in a different color from the given numbers.
- The solver is real backtracking, not a lookup table. Show me the backtracking:
when it undoes a wrong guess, briefly flash that cell red.
- A "Stop" button halts the animation mid-solve.
- A status line reads "Solved in N steps" when finished.

CONSTRAINTS
- Plain HTML, CSS, and JavaScript in one file. No frameworks.
- Comment the solver function so I can follow the algorithm.
- Under 300 lines.

PLEASE
1. Show me your plan in 4-6 bullets, then wait for me to say go.
2. Then write index.html.
3. Explain how to change the animation speed and the puzzle difficulty.

Then add more, this is where you learn the most:

Add a difficulty selector with Easy, Medium, and Hard that changes how many cells are
pre-filled. Change nothing else.
Add a "Check" button that highlights any cell that conflicts with another in its row,
column, or 3x3 block. Do not change the solver.

→ Full step-by-step tutorial: Build a Sudoku Solver with a Visual UI

Conway's Game of Life​

Four simple rules, and you can tell at a glance whether the model implemented them correctly.

Build a single self-contained index.html with Conway's Game of Life. No libraries.

DONE MEANS
- A 50x30 grid of cells rendered on a canvas.
- Start, Stop, Step, Clear, and Randomize buttons.
- Clicking a cell toggles it alive or dead, even while running.
- A speed slider from 1 to 30 generations per second.
- A generation counter and a live-cell count.
- Edges wrap around, so a glider crossing the right edge reappears on the left.

Keep it under 250 lines. Comment the rule that decides whether a cell lives or dies.
Show me your plan first, then wait for me to say go.

Maze generator and solver​

Two algorithms in one file, both of them visible while they run. A good test of how well a model handles "animate this".

Build a single self-contained index.html that generates and solves a maze. No libraries.

DONE MEANS
- "Generate" draws a random perfect maze (exactly one path between any two cells) on a
canvas, animating the generation so I can watch it carve.
- "Solve" animates a path from the top-left to the bottom-right, drawing explored dead
ends in light gray and the final path in a solid color.
- A size slider from 10x10 to 40x40.
- Both animations can be stopped mid-run.

Use recursive backtracking to generate and breadth-first search to solve. Say in a comment
why BFS gives the shortest path. Under 300 lines.
Show me your plan first, then wait for me to say go.

Lab timer with presets​

Small enough to finish in a single pass, and it touches browser APIs that come up again in tutorials later.

Build a single self-contained index.html: a countdown timer for lab work. No libraries.

DONE MEANS
- Preset buttons for 5, 15, 25, and 50 minutes, plus a custom minutes input.
- Start, Pause, and Reset. The remaining time shows as MM:SS in large text.
- The page title also shows the countdown, so I can see it in a background tab.
- A colored ring around the timer drains as time passes.
- When it hits zero, the page flashes and a short beep plays using the Web Audio API
(no audio files).
- The last preset I used is remembered in localStorage.

Under 200 lines. Show me your plan first, then wait for me to say go.

Flashcard quiz from a text file​

The first of these that works on your own content, and a natural lead-in to the note-based tutorials.

Build a single self-contained index.html flashcard quiz. No libraries.

DONE MEANS
- A textarea where I paste lines in the form "question | answer", one per line.
- "Start Quiz" hides the textarea and shows one question at a time.
- Clicking the card flips it to reveal the answer with a CSS flip animation.
- "Got it" and "Missed it" buttons; missed cards come back later in the same session.
- A progress indicator: "Card 4 of 12 - 3 missed".
- The pasted cards persist in localStorage so a refresh does not lose them.

Under 250 lines. Show me your plan first, then wait for me to say go.

Paste-a-CSV chart​

A stepping stone to the CSV Dataset Explorer, without installing anything first.

Build a single self-contained index.html that charts pasted CSV data. No libraries and
no CDN — draw the chart yourself on a canvas.

DONE MEANS
- A textarea where I paste CSV text with a header row, plus a "Plot" button.
- Dropdowns to pick which column is the X axis and which is the Y axis, populated from
the header row.
- A bar chart or line chart (my choice via a toggle) with labeled axes and gridlines.
- Hovering a point or bar shows its exact value in a tooltip.
- A clear message if a chosen column is not numeric, instead of a broken chart.

Under 300 lines. Show me your plan first, then wait for me to say go.
What to watch for

Whether it works is only half of it. Pay attention to where it needed help, because the same tendencies will show up on your real project. Did it pull in a library you said not to use? Did it skip the one-at-a-time animation? Did asking for a plan first change the outcome? Anything you find yourself correcting more than once belongs in your AGENTS.md.

Once it works, run @reviewer over the file before moving on. Getting used to a second, read-only pass on a small project is how it becomes automatic on a larger one.


Troubleshooting​

SymptomFix
401 / authentication failedThe key is wrong, expired, or not visible to the tool. Confirm with echo $OPENAI_API_KEY (macOS/Linux) or echo $env:OPENAI_API_KEY (Windows), then restart the tool. Regenerate the key in Voyager if needed.
Model not foundA model ID does not match Voyager exactly. Copy it again from the LLM Access tab.
opencode: command not foundFully quit and reopen your terminal after installing.
No RC provider or models in the pickerThe config was not loaded. Check the file path from Step 3b and fully restart the tool — config changes need a restart.
Works in curl but not in the appThe app cannot see your shell's environment variable. For OpenCode's desktop app, run opencode auth login and paste the key.
Chat replies but file edits never happenThe model likely does not support tool calling. Switch to a tool-capable model from the Voyager list.
Replies are good but then go off the railsThe session got too long. Start a fresh session and point at specific files.
It keeps ignoring an instructionMove that instruction into AGENTS.md so it is supplied every session rather than once.
A skill never seems to loadCheck the folder path and that the file is named exactly SKILL.md (downloads arrive as name.SKILL.md and must be renamed). Restart OpenCode.
/agent shows nothing, or the wrong agentsThe config with your agent block was not loaded. Confirm you saved the file Voyager generated to the right path, then restart.
429 rate limitYou are sending requests too quickly. Wait a moment and retry.

Still stuck? See Getting Help to open a ticket or join office hours.


Appendix: Other tools​

As discussed in Step 2, other tools can be greatly beneficial when using AIR. While not required for the tutorials served on this site, we include instructions here on installing and getting started with OpenWork, VS Code, and Open WebUI.


Extra Tool 1: OpenWork​

OpenWork is a free, open-source desktop app for working with AI agents on your own files, available for macOS, Windows, and Linux. It is built on OpenCode, so what you set up in Step 3 carries straight over.

It adds some additional features on top of OpenCode:

  • A visible plan. The agent's to-do list appears as a live timeline, so you can follow what it intends to do, watch the plan change, and stop it early when it heads somewhere wrong. In a terminal the same information scrolls past you.
  • A workspace. Files, chat, and results side by side rather than interleaved in one stream.
  • Skills and MCP connections configured once and reused across projects.

Install and connect​

  1. Download the app for your OS from openworklabs.com/download.
  2. Open it and point it at a project folder.
  3. Open the model picker and choose a model under ASU Air. Because OpenWork runs OpenCode underneath, it reads the same ~/.config/opencode/opencode.json you created in Step 3. This includes the agents and permissions Voyager generated for you.

If RC models do not appear, quit and reopen the app so it re-reads the config, and confirm opencode --version and echo $OPENAI_API_KEY both work in a terminal.

A good first task​

OpenWork is at its best on multi-step work where you want to see the plan. Try this on a folder that already has a few files in it:

Read every file in this folder and write a README.md that explains what this project is,
how to run it, and what each file does.

Before you write anything, show me your plan as a checklist and wait for me to say go.

The point of the exercise is the checklist. Reading it and correcting it before a single file is written costs you a sentence; correcting the finished work costs a rewrite.

Optional: use OpenWork's shared skills from other tools

OpenWork also publishes an MCP server, which lets other agents reuse the skills and connections you set up in OpenWork. Adding it to OpenCode means adding an mcp block to your opencode.json:

~/.config/opencode/opencode.json (excerpt)
{
"mcp": {
"openwork": {
"type": "remote",
"enabled": true,
"url": "https://api.openworklabs.com/mcp/agent",
"oauth": {}
}
}
}

This is a team-sharing feature and signs you in to an OpenWork account, so it is optional and separate from everything else in this guide. The desktop app works fully without it.


Extra Tool 2: VS Code​

VS Code is a free code editor. Consider installing it even if you plan to drive OpenCode from the terminal. Reading any code in an editor, with syntax highlighting and a proper diff view, is much easier than reading the scrolling assistant output. Reviewing and understanding generated code enables you to make better code, so easing the process of reading is useful.

1. Install the editor​

Download it from code.visualstudio.com and install it like any other application. On first launch, pick a theme and skip the rest of the tour.

2. Install a few extensions​

Open the Extensions panel (Ctrl/Cmd+Shift+X) and install any extensions useful for your work. Here are some highlights for the tutorials:

ExtensionWhy
Python (Microsoft)Runs and debugs Python, picks up your .venv automatically.
Jupyter (Microsoft)Notebooks inside the editor.
ESLint + PrettierJavaScript/TypeScript linting and formatting for the web tutorials.
GitHub Pull RequestsReview pull requests without leaving the editor — used by the Git collaboration tutorial.

3. Four things worth learning​

VS Code has hundreds of features and you can ignore nearly all of them. These four carry the work:

  1. Open a folder: File → Open Folder. Open an entire project folder, not a single file, because assistants read the folder around a file for context. This is also useful without an assistant, since it lets you see all your files without switching to a file manager.
  2. The integrated terminal: Ctrl plus the backtick key opens a terminal inside the editor, already in your project folder. You can even run opencode there and have the assistant and your files side by side.
  3. Source Control panel: the branch icon in the left bar shows every change made to your project, line by line, with buttons to stage and commit. This is where you can review an assistant's work before pushing to tools like Github.
  4. Command Palette: Ctrl/Cmd+Shift+P runs any command by name, which saves hunting for the button.

4. Optional: connect VS Code Chat to the RC models​

VS Code has its own chat, and it can point at the RC gateway using BYOK (Bring Your Own Key). It's worth doing if you would rather have chat inside the editor than a separate assistant.

Here's a short walkthrough: Open the Command Palette → enter Chat: Manage Language Models → choose Add Models → choose Custom Endpoint, then give it the endpoint https://openai.rc.asu.edu/v1/chat/completions, your API key, and a model ID. The full walkthrough, including the chatLanguageModels.json file VS Code may open, is in another guide, Connect VS Code to the RC API.

Editing needs a tool-capable model

VS Code's Agent mode relies on tool calling to change files. We identify agents that can use tools with the Tools badge in Voyager, as explored in Step 1. If chat answers normally but edits never appear, that is usually the cause. Switch models, or keep VS Code Chat for explanations and let OpenCode do the editing.


Extra Tool 3: Open WebUI​

ai.rc.asu.edu is our hosted Open WebUI, a ChatGPT-style interface for the same RC models. Log in with ASURITE, and you can get started. Because it is in browser and wired to our software, you do not need further work.

It is worth being precise about what it does. Open WebUI cannot read or edit your project files, so it does not replace OpenCode, OpenWork, or VS Code, and you cannot build a tutorial project in it. Think of it as you would a traditional ChatGPT-style interface. Much like ChatGPT, it is good at helping with the thinking that happens before you open an editor, and helping you get the information you need as you work through a problem. Consider the following use cases for Open WebUI, when used with the wider assistant structure:

  • Shaping a problem. "I want a tool that summarizes lab meeting notes. What are three ways to structure this, with trade-offs?"
  • Getting unstuck. Paste an error message and ask what it means.
  • Understanding code you inherited. Paste a file and ask for a walkthrough.
  • Drafting the prompt you will use elsewhere. Ask it to turn a vague idea into a precise specification, then paste that specification into your coding assistant.

That last one pairs well with the prompt skeleton in Step 7.

Sub-agents​

Open WebUI now supports sub-agents: the model can hand a self-contained piece of work to a background helper, which runs its own tool-driven conversation and reports back only its conclusion. It keeps a research-heavy chat readable instead of filling it with intermediate output.

  • Using it. Ask for work that splits naturally: "research these four approaches and compare them". Then, a capable model will delegate rather than working through everything on its own.
  • The limits. A sub-agent cannot delegate again, so work never fans out without bound. There are caps on how many run at once and how long each may iterate.

More on features and models: Using Open WebUI.


Where to go next​

You now have a key, a tool that can edit your projects, and a working sense of how to get good results from the models we host.

Pick a project from the Tutorials & Projects index. The sudoku solver installs nothing at all, and the Streamlit chatbot and CSV dataset explorer are the gentlest starting points once you are ready to install something.