361 lines
14 KiB
Markdown
361 lines
14 KiB
Markdown
---
|
|
order: 5
|
|
title: Lab 5 - API & Harnesses
|
|
description: Generate an Open WebUI API key, connect one of three coding harnesses, and build a small Zork-style game.
|
|
---
|
|
|
|
<!-- breakout-style: instruction-rails -->
|
|
<!-- step-style: underline -->
|
|
<!-- objective-style: divider -->
|
|
|
|
# Lab 5 - API & Harnesses
|
|
|
|
In this lab, we will:
|
|
|
|
- Generate a personal API key inside Open WebUI
|
|
- Install one of three coding harnesses
|
|
- Configure that harness to talk to Open WebUI as the backend
|
|
- Use the harness to build a small Zork-style game
|
|
|
|
<div class="lab-callout lab-callout--info">
|
|
<strong>Lab Flow Guide</strong><br />
|
|
This lab stays on a single high-level track, but Objectives 2 and 3 branch into three harness paths.<br />
|
|
Pick one harness, complete its branch, then rejoin the common Zork objective at the end.
|
|
</div>
|
|
|
|
To start this lab, one web service has been preconfigured:
|
|
|
|
- Open WebUI - {{service-url:open-webui}}
|
|
|
|
## Objective 1 Execute: Generate an Open WebUI API Key
|
|
|
|
Before we install any harness, we need a key that lets the harness call the same model backend exposed through Open WebUI.
|
|
|
|
### Execute: Sign in to Open WebUI
|
|
|
|
1. Navigate to `{{service-url:open-webui}}`.
|
|
2. Sign in with the same account you used in Lab 4, or the credentials supplied by your instructor.
|
|
3. Confirm that you can reach the normal chat screen before continuing.
|
|
|
|
### Execute: Create a personal access token
|
|
|
|
According to the Open WebUI reference docs, API keys are created from **Settings -> Account** and authenticate with the same permissions as the user who created them.
|
|
|
|
1. Click your avatar in the lower-left corner.
|
|
|
|
<figure style="text-align: center;">
|
|
<a href="https://i.imgur.com/oZuZwWQ.png" target="_blank">
|
|
<img
|
|
src="https://i.imgur.com/oZuZwWQ.png"
|
|
style="width: 50%; display: block; margin-left: auto; margin-right: auto; border: 5px solid black;">
|
|
</a>
|
|
<figcaption style="margin-top: 8px; font-size: 1.1em;">
|
|
User Settings
|
|
</figcaption>
|
|
</figure>
|
|
<br>
|
|
|
|
2. Open **Settings**.
|
|
3. Open **Account**.
|
|
4. Locate the **API Keys** section.
|
|
|
|
<figure style="text-align: center;">
|
|
<a href="https://i.imgur.com/oDe6cpE.png" target="_blank">
|
|
<img
|
|
src="https://i.imgur.com/oDe6cpE.png"
|
|
style="width: 50%; display: block; margin-left: auto; margin-right: auto; border: 5px solid black;">
|
|
</a>
|
|
<figcaption style="margin-top: 8px; font-size: 1.1em;">
|
|
API Key
|
|
</figcaption>
|
|
</figure>
|
|
<br>
|
|
|
|
6. Copy the key immediately and store it somewhere safe for the duration of the lab.
|
|
|
|
<div class="lab-callout lab-callout--warning">
|
|
<strong>If you do not see API Keys:</strong> Open WebUI requires the feature to be enabled globally, and your user account needs permission to generate keys. Ask your instructor for help before continuing.
|
|
</div>
|
|
|
|
### Execute: Sanity-check the key from the terminal
|
|
|
|
Run a quick authenticated request against the Open WebUI model list endpoint. You should receive JSON back instead of an authentication error.
|
|
|
|
```bash
|
|
curl {{service-url:open-webui:/api}}/models \
|
|
-H "Authorization: Bearer YOUR_OPENWEBUI_API_KEY"
|
|
```
|
|
|
|
If this request works, your harness will use the same key for later steps.
|
|
|
|
---
|
|
|
|
## Objective 2 Execute: Choose and Install a Harness
|
|
|
|
All three branches ultimately talk to the same Open WebUI backend. The difference is the user interface and configuration style for each harness.
|
|
|
|
<div class="lab-harness-chooser" role="group" aria-label="Harness installation paths">
|
|
<button type="button" class="lab-harness-card" data-harness-choice="opencode" aria-pressed="false">
|
|
<span class="lab-harness-card__tag">Path A</span>
|
|
<strong>OpenCode</strong>
|
|
<span>Terminal-first coding agent</span>
|
|
</button>
|
|
<button type="button" class="lab-harness-card" data-harness-choice="kilocode" aria-pressed="false">
|
|
<span class="lab-harness-card__tag">Path B</span>
|
|
<strong>Kilo Code VS Code</strong>
|
|
<span>Editor-driven coding assistant</span>
|
|
</button>
|
|
<button type="button" class="lab-harness-card" data-harness-choice="droid" aria-pressed="false">
|
|
<span class="lab-harness-card__tag">Path C</span>
|
|
<strong>Factory Droid</strong>
|
|
<span>Advanced CLI harness with powerful Spec Driven Development (Missions)</span>
|
|
</button>
|
|
</div>
|
|
|
|
<p>Select a path to reveal that harness's instructions throughout the rest of the lab. Select the same card again if you want to hide the harness-specific instructions and return to the shared overview.</p>
|
|
|
|
### Execute: Install the harness you want to use
|
|
|
|
<section class="lab-harness-branch" id="opencode-install" data-harness-branch="opencode">
|
|
<p class="lab-harness-branch__eyebrow">Path A</p>
|
|
<h3>Install OpenCode</h3>
|
|
<p>OpenCode is a terminal-native coding agent. Its official docs recommend either the install script or the npm package.</p>
|
|
<pre><code class="language-bash">curl -fsSL https://opencode.ai/install | bash
|
|
opencode --version</code></pre>
|
|
<p>If you prefer npm and already have Node.js installed:</p>
|
|
<pre><code class="language-bash">npm install -g opencode-ai
|
|
opencode --version</code></pre>
|
|
<p>Once installed, stay in the terminal. We will configure OpenCode in Objective 3.</p>
|
|
</section>
|
|
|
|
<section class="lab-harness-branch" id="kilocode-install" data-harness-branch="kilocode">
|
|
<p class="lab-harness-branch__eyebrow">Path B</p>
|
|
<h3>Install Kilo Code for VS Code</h3>
|
|
<p>Kilo Code is primarily used through the editor UI. For this Linux-first lab flow, use VS Code on the student workstation and install the extension from the marketplace.</p>
|
|
<ol>
|
|
<li>Open <strong>VS Code</strong>.</li>
|
|
<li>Open the <strong>Extensions</strong> view.</li>
|
|
<li>Search for <strong>Kilo Code</strong>.</li>
|
|
<li>Click <strong>Install</strong>.</li>
|
|
<li>Reload VS Code if prompted.</li>
|
|
<li>Open the project folder you want to work in before moving to Objective 3.</li>
|
|
</ol>
|
|
<div class="lab-callout lab-callout--info">
|
|
<strong>Tip:</strong> Kilo Code supports several providers and local-model options. In this lab, we will use its <strong>OpenAI Compatible</strong> provider flow so it can target Open WebUI.
|
|
</div>
|
|
</section>
|
|
|
|
<section class="lab-harness-branch" id="droid-install" data-harness-branch="droid">
|
|
<p class="lab-harness-branch__eyebrow">Path C</p>
|
|
<h3>Install Factory Droid</h3>
|
|
<p>Factory's Droid harness runs in the terminal and supports BYOK custom models through Factory configuration files.</p>
|
|
<pre><code class="language-bash">curl -fsSL https://app.factory.ai/cli | sh
|
|
droid --version</code></pre>
|
|
<p>If the shell needs to be reloaded after install, open a fresh terminal and rerun <code>droid --version</code>.</p>
|
|
</section>
|
|
|
|
---
|
|
|
|
## Objective 3 Execute: Configure Your Harness for Open WebUI
|
|
|
|
For all three harnesses, the common backend values are:
|
|
|
|
- `Base URL` - `{{service-url:open-webui:/api}}`
|
|
- `API Key` - `YOUR_OPENWEBUI_API_KEY`
|
|
- `Model ID` - Any model ID returned by Open WebUI, such as `qwen3.5:4b`
|
|
|
|
The shared idea is simple: your harness sends requests to Open WebUI's authenticated API endpoints instead of directly to a cloud provider.
|
|
|
|
### Execute: Apply the configuration for your chosen harness
|
|
|
|
<section class="lab-harness-branch" id="opencode-config" data-harness-branch="opencode">
|
|
<p class="lab-harness-branch__eyebrow">Path A</p>
|
|
<h3>Configure OpenCode</h3>
|
|
<p>OpenCode supports OpenAI-compatible providers through its JSON config. Create either a project-local <code>opencode.json</code> file or a global config under <code>~/.config/opencode/opencode.json</code>.</p>
|
|
|
|
<p>It can also be easier to start opencode once, and exit with /exit. Use the following example to help structure your opencode.json file.
|
|
<pre><code class="language-json">{
|
|
"$schema": "https://opencode.ai/config.json",
|
|
"provider": {
|
|
"openwebui": {
|
|
"name": "Open WebUI",
|
|
"options": {
|
|
"baseURL": "{{service-url:open-webui:/api}}",
|
|
},
|
|
"models": {
|
|
"qwen3.5:4b": {
|
|
"name": "Qwen 3.5 4B"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"model": "openwebui/qwen3.5:4b"
|
|
}</code></pre>
|
|
<p>After saving the config, you can login with <code>opencode auth login: </code></p>
|
|
<figure style="text-align: center;">
|
|
<a href="https://i.imgur.com/wLPJOpz.png" target="_blank">
|
|
<img
|
|
src="https://i.imgur.com/wLPJOpz.png"
|
|
style="width: 50%; display: block; margin-left: auto; margin-right: auto; border: 5px solid black;">
|
|
</a>
|
|
<figcaption style="margin-top: 8px; font-size: 1.1em;">
|
|
opencode auth login
|
|
</figcaption>
|
|
</figure>
|
|
<p>After logging in, start OpenCode from your project directory:</p>
|
|
<pre><code class="language-bash">cd /path/to/your/project
|
|
opencode</code></pre>
|
|
</section>
|
|
|
|
<section class="lab-harness-branch" id="kilocode-config" data-harness-branch="kilocode">
|
|
<p class="lab-harness-branch__eyebrow">Path B</p>
|
|
<h3>Configure Kilo Code in VS Code</h3>
|
|
<p>Kilo Code's documented workflow is provider-driven through the extension settings UI. Use the following values when creating or editing your provider profile.</p>
|
|
<ul>
|
|
<li><code>API Provider</code> - <code>OpenAI Compatible</code></li>
|
|
<li><code>OpenAI Base URL</code> - <code>{{service-url:open-webui:/api}}</code></li>
|
|
<li><code>API Key</code> - <code>YOUR_OPENWEBUI_API_KEY</code></li>
|
|
<li><code>Model ID</code> - <code>qwen3.5:4b</code> or another model exposed by Open WebUI</li>
|
|
<li><code>Approval Mode</code> - Leave the safer default enabled for your first run</li>
|
|
</ul>
|
|
<br>
|
|
<ol>
|
|
<li>Open the Kilo Code panel in VS Code.</li>
|
|
<li>Open its provider or API settings.</li>
|
|
<li>Select <strong>OpenAI Compatible</strong> as the provider.</li>
|
|
<li>Paste in the base URL and API key values above.</li>
|
|
<li>Pick a model ID that exists in Open WebUI.</li>
|
|
<li>Start a new task to verify Kilo Code can connect successfully.</li>
|
|
</ol>
|
|
|
|
<figure style="text-align: center;">
|
|
<a href="https://i.imgur.com/Q61IK03.png" target="_blank">
|
|
<img
|
|
src="https://i.imgur.com/Q61IK03.png"
|
|
style="width: 50%; display: block; margin-left: auto; margin-right: auto; border: 5px solid black;">
|
|
</a>
|
|
<figcaption style="margin-top: 8px; font-size: 1.1em;">
|
|
Kilo Code Settings
|
|
</figcaption>
|
|
</figure>
|
|
<br>
|
|
|
|
<figure style="text-align: center;">
|
|
<a href="https://i.imgur.com/vZV9qWW.png" target="_blank">
|
|
<img
|
|
src="https://i.imgur.com/vZV9qWW.png"
|
|
style="width: 50%; display: block; margin-left: auto; margin-right: auto; border: 5px solid black;">
|
|
</a>
|
|
<figcaption style="margin-top: 8px; font-size: 1.1em;">
|
|
Provider Settings
|
|
</figcaption>
|
|
</figure>
|
|
<br>
|
|
|
|
<div class="lab-callout lab-callout--info">
|
|
<strong>Tip:</strong> If model discovery fails, go back to your terminal and rerun the <code>curl /api/models</code> check from Objective 1. The harness and the curl command use the same authentication path.
|
|
</div>
|
|
</section>
|
|
|
|
<section class="lab-harness-branch" id="droid-config" data-harness-branch="droid">
|
|
<p class="lab-harness-branch__eyebrow">Path C</p>
|
|
<h3>Configure Factory Droid</h3>
|
|
<p>Factory's BYOK documentation supports custom model entries in <code>~/.factory/config.json</code>. Because Open WebUI exposes a chat-completions-compatible API, use the <code>generic-chat-completion-api</code> provider type.</p>
|
|
<pre><code class="language-json">{
|
|
"custom_models": [
|
|
{
|
|
"model_display_name": "Open WebUI - Qwen 3.5 4B",
|
|
"model": "qwen3.5:4b",
|
|
"base_url": "{{service-url:open-webui:/api}}",
|
|
"api_key": "YOUR_OPENWEBUI_API_KEY",
|
|
"provider": "generic-chat-completion-api",
|
|
"max_tokens": 4096
|
|
}
|
|
]
|
|
}</code></pre>
|
|
<p>After saving the config:</p>
|
|
<ol>
|
|
<li>Launch <code>droid</code>.</li>
|
|
<li>Open the model selector with <code>/model</code>.</li>
|
|
<li>Choose your new custom Open WebUI model entry.</li>
|
|
<li>Start a new session in the target project directory.</li>
|
|
</ol>
|
|
</section>
|
|
|
|
---
|
|
|
|
## Objective 4 Execute: Build a Tiny Zork Clone
|
|
|
|
At this point, all three branches reconnect. The rest of the lab is the same no matter which harness you chose.
|
|
|
|
### Execute: Start your harness session
|
|
|
|
<div class="lab-harness-chooser" aria-label="Harness launch reminders">
|
|
<div class="lab-harness-card" data-harness-branch="opencode">
|
|
<span class="lab-harness-card__tag">OpenCode</span>
|
|
<strong>Terminal Session</strong>
|
|
<span>Run <code>opencode</code> inside the project directory.</span>
|
|
</div>
|
|
<div class="lab-harness-card" data-harness-branch="kilocode">
|
|
<span class="lab-harness-card__tag">Kilo Code</span>
|
|
<strong>VS Code Task</strong>
|
|
<span>Open the repo folder and start a new Kilo Code task from the side panel.</span>
|
|
</div>
|
|
<div class="lab-harness-card" data-harness-branch="droid">
|
|
<span class="lab-harness-card__tag">Factory Droid</span>
|
|
<strong>CLI Session</strong>
|
|
<span>Run <code>droid</code>, type "/mission", and ensure you've selected your custom model for each phase.</span>
|
|
</div>
|
|
</div>
|
|
|
|
### Execute: Give the harness a shared prompt
|
|
|
|
Use the following prompt as your starting task. Ensure you are in **Plan** mode (or a Droid Mission):
|
|
|
|
```text
|
|
You are helping me build a tiny terminal adventure game in Python.
|
|
|
|
Create a Zork-style prototype with:
|
|
- at least 5 connected rooms
|
|
- movement commands like north, south, east, and west
|
|
- a simple inventory system
|
|
- one collectible key
|
|
- one locked room or door
|
|
- a short win condition
|
|
|
|
Use clean, readable Python and keep everything runnable from the terminal.
|
|
After writing the code, explain how to launch the game and what commands the player can use.
|
|
```
|
|
|
|
### Explore: Execute the result
|
|
|
|
Once your harness produces the first version, keep pushing it with follow-up prompts:
|
|
|
|
1. Ask it to add a help command.
|
|
2. Ask it to improve room descriptions.
|
|
3. Ask it to prevent impossible movement.
|
|
4. Ask it to add one extra puzzle or hidden interaction.
|
|
|
|
Alternatively, reflect if you'd instead focused on using a Spec Driven development flow. How might the AI model perform more accurately as the requirements become more complicated?
|
|
|
|
### Checkpoint: What success can look like
|
|
|
|
Before finishing the lab, confirm that your game can:
|
|
|
|
1. Start from the terminal without errors.
|
|
2. Accept basic movement commands.
|
|
3. Let the player pick up at least one item.
|
|
4. Use that item to unlock progress.
|
|
5. Reach a clear win state.
|
|
|
|
## Conclusion
|
|
|
|
In this lab, we:
|
|
|
|
1. Generated an Open WebUI API key.
|
|
2. Installed a harness of our choice.
|
|
3. Connected that harness back to Open WebUI.
|
|
4. Used the harness to build a small but complete coding exercise.
|
|
|
|
You should now have a repeatable pattern for testing other harnesses against the same Open WebUI deployment. We've also shown how a full local stack can work, from model selection, inference, harness installation, to real coding work.
|