---

# BIP Information

--- BIP GUIDE ---

### ABOUT THE PROGRAMME

This BIP brings together students and staff from the UNINOVIS European university alliance to explore how AI agents can support higher education. The programme combines online preparation with a 5-day physical component in Málaga, Spain.

### UNINOVIS ALLIANCE

UniNovis is a European university alliance focused on enhancing education, research, and innovation in the field of applied data science. UniNovis consists of eight European universities from eight different countries:

| University                                                     | Acronym | Country     |
|----------------------------------------------------------------|---------|-------------|
| University of Sorbonne Paris Nord                              | USPN    | France      |
| University of Campania "Luigi Vanvitelli"                      | UDCLV   | Italy       |
| University of Malaga                                           | UMA     | Spain       |
| Kauno Kolegija Higher Education Institution                    | KK      | Lithuania   |
| University of Tirana                                           | UT      | Albania     |
| Technical University of Applied Sciences Würzburg-Schweinfurt  | THWS    | Germany     |
| Tampere University of Applied Sciences                         | TAMK    | Finland     |
| The Hague University of Applied Sciences                       | THUAS   | Netherlands |

UMA (Universidad de Málaga) is the host institution for this BIP.

### PROGRAMME OBJECTIVES

1. Understand what AI agents are and how they can support teaching, research, and administration
2. Build practical AI agents using the TOMMI Lite platform
3. Explore responsible AI practices in a higher education context
4. Foster cross-institutional collaboration and knowledge exchange

### DAILY SCHEDULE

**Day 1 — Introduction to AI Agents in European University Alliances**

| Time          | Activity                                                                                        |
|---------------|-------------------------------------------------------------------------------------------------|
| 10:00 – 10:30 | Registration & Welcome session. Introduction to the BIP objectives, agenda and expected outcomes |
| 10:30 – 11:30 | A first dive: basic One-shot architecture                                                       |
| 11:30 – 12:00 | Coffee break                                                                                    |
| 12:00 – 13:30 | Overview of AI agent tools for universities     |
| 13:30 – 14:30 | Lunch break                                                                                     |
| 14:30 – 16:00 | Preparation of practical activities                                                             |

**Day 2 — AI for Research and Innovation**

| Time          | Activity                                                                  |
|---------------|---------------------------------------------------------------------------|
| 10:00 – 11:30 | AI-assisted research                                                      |
| 11:30 – 12:00 | Coffee break                                                              |
| 12:00 – 13:30 | Hands-on workshop: Research assistants (with RAG architecture)            |
| 13:30 – 14:30 | Lunch break                                                              |
| 14:30 – 16:00 | Teamwork session: Create your research assistant                          |

**Day 3 — AI in Teaching and Learning**

| Time          | Activity                                                                           |
|---------------|------------------------------------------------------------------------------------|
| 10:00 – 11:30 | Teaching assistants. Keynote: Francisco Rejón Guardia                               |
| 11:30 – 12:00 | Coffee break                                                                       |
| 12:00 – 13:30 | Hands-on workshop: Teaching assistants (with advanced RAG architecture)             |
| 13:30 – 14:30 | Lunch break                                                                        |
| 14:30 – 16:00 | Teamwork session: Create your virtual tutor                                        |

**Day 4 — AI for University Management and Administration**

| Time          | Activity                                                                                    |
|---------------|---------------------------------------------------------------------------------------------|
| 10:00 – 11:30 | Keynote: AI-assisted University management                                                  |
| 11:30 – 12:00 | Coffee break                                                                                |
| 12:00 – 13:30 | Hands-on workshop: Database access in research/administration (with Toolcall agents)        |
| 13:30 – 14:30 | Lunch break                                                                                 |
| 14:30 – 16:00 | Teamwork session: Create your DB query system                                               |

**Day 5 — Presentation and Future Collaboration**

| Time          | Activity                                                                              |
|---------------|---------------------------------------------------------------------------------------|
| 09:00 – 10:00 | AI & Law & Ethics. Keynote: Jorge Villalobos Portales (Law Faculty, UMA)              |
| 10:00 – 11:00 | AI & Law & Ethics. Keynote: Gómez Jiménez, María Luisa (Law Faculty, UMA)             |
| 11:00 – 11:30 | Coffee break                                                                          |
| 11:30 – 12:15 | Roundtable discussion: Future collaboration within UNINOVIS and beyond                |
| 12:15 – 12:30 | Closing ceremony and certificate delivery                                             |

### VENUE AND LOGISTICS

Location: Universidad de Málaga (UMA), Campus de Teatinos. Address: Boulevard Louis Pasteur, 29071 Málaga, Spain.

How to Get There:
- From Málaga Airport (AGP): take the Cercanías train (line C1) to Málaga Centro, then bus line 11 to Campus de Teatinos. Total: ~40 min. Or taxi (~20 min, ~€20).
- From María Zambrano train station: bus line 11 directly to campus (~20 min).
- By bus from city centre: lines 11 and 22.

Wi-Fi: Eduroam available across campus. Use your institutional credentials. IT help desk in library building (ground floor).

Meals: Coffee breaks provided. Lunch NOT included. Options: University cafeteria (menu del día ~€6), Cafetería de Teatinos, restaurants on Blvd. Louis Pasteur.

### SOCIAL PROGRAMME

Cultural Visit (Day 2 evening): Guided walking tour including the Alcazaba (11th-century Moorish fortress), Roman Theatre (1st century BC), Cathedral ("La Manquita"), and Calle Larios. Meeting point: venue lobby at 17:30. Duration: ~2 hours.

Free Evening (Day 3): Enjoy Málaga on your own.

Farewell Dinner (Day 4 evening): Closing dinner at Kaleido restaurant in the Port (just 5 minutes from the BIP location) .

### WHAT TO DO IN MÁLAGA

Museums:
- Museo Picasso Málaga — over 200 works. Calle San Agustín, 8. Tue–Sun 10:00–19:00. €12.
- Centre Pompidou Málaga — modern and contemporary art. Muelle Uno. €9.
- Carmen Thyssen Museum — 19th-century Spanish painting. Calle Compañía, 10. €10.
- CAC Málaga — contemporary art. Free. Calle Alemania.
- Museo de Málaga — fine arts and archaeology. Free for EU citizens.

Beaches:
- Playa de la Malagueta — closest to city centre (~15 min walk from cathedral).
- Playa de Pedregalejo — famous for chiringuitos and espetos. Bus lines 3, 8, 11, 34.
- Playa del Palo — quieter, more local. Bus lines 3, 8, 11

Food and Drink:
- Espetos de sardinas — sardines grilled on skewers over fire. Best in Pedregalejo.
- Pescaíto frito — mixed fried fish.
- Porra antequerana — cold tomato and bread soup, thicker than gazpacho.
- Salmorejo — cold tomato soup, creamier than gazpacho.
- Málaga sweet wine — try at Antigua Casa de Guardia (founded 1840), Alameda Principal, 18.

Day Trips:
- Caminito del Rey — walkway along gorge walls. 60 km from Málaga. €10. Book in advance.
- Ronda — hilltop town with famous bridge. ~1.5 hours by bus.
- Nerja — Balcón de Europa viewpoint and Nerja Caves. ~1 hour east.
- Granada — Alhambra palace. ~1.5 hours. Book tickets well in advance.
- Frigiliana — prettiest white village in Andalucía.

Getting Around:
- Walking — city centre is compact.
- Bus (EMT) — €1.40/ride or rechargeable card.
- Metro — 2 lines.
- Bike — lanes along seafront, rental available.
- Taxi — metered, apps: FreeNow, Uber.

Useful Info: Currency: Euro. Language: Spanish (English widely spoken in tourist areas). Emergency: 112. Weather: 20–35°C, rain rare. Time zone: CET/CEST. Tipping: not mandatory, 5–10% appreciated.

--- END OF BIP GUIDE ---

---

# Step-by-Step Guide

TOMMI Lite — Step-by-Step Guide

Step-by-Step Guide to Creating Your First AI Agent

## Contents

0. [Prerequisites](#step0)
1. [Install TOMMI Lite](#step1)
2. [Start the Server](#step2)
3. [Create a RAG Agent](#step3)
4. [Chat with Your Agent](#step4)

## 0 Prerequisites

#### Computer

A computer running macOS, Linux, or Windows.

#### Python 3.10+

If not installed, `start.sh` will detect this and ask you to accept its installation automatically.

#### Basic Command Line Knowledge

Familiarity with basic terminal/command line instructions. See our [Terminal Guide](Terminal_Guide.html).

### 0.b A Large Language Model (LLM)

TOMMI Lite needs an LLM to power its agents. You have two options — choose one:

#### Option A: Ollama (local, free)

Run AI models on your own computer. No internet needed, no API key, completely free. Requires a reasonably modern computer (8+ GB RAM recommended).

**Setup:**

1. Download and install from [ollama.com](https://ollama.com)
2. Open a terminal and download a model:

   ```
   ollama pull mistral
   ```

   This downloads about 4 GB (only needed once).

**Other models:** `ollama pull llama3`, `ollama pull qwen2.5-coder`, `ollama pull gemma2`

#### Option B: Mistral Cloud (API key)

Use Mistral's cloud servers. No local GPU needed, works on any computer. Requires an internet connection and an API key (free tier available).

**Setup:**

1. Go to [console.mistral.ai](https://console.mistral.ai) and create an account
2. Generate an API key from the dashboard
3. Open the file `env.txt` inside the `tommi_lite` folder with any text editor and change:

   ```
   # Comment out the Ollama lines:
   # LLM_PROVIDER=ollama
   # OLLAMA_BASE_URL=http://localhost:11434
   # OLLAMA_MODEL=mistral

   # Uncomment and fill in the Mistral lines:
   LLM_PROVIDER=mistral
   MISTRAL_API_KEY=your_key_here
   ```

**Which one should I choose?**

* **Ollama** if you want privacy (data stays on your machine), have a decent computer, and don't want to pay for API calls.
* **Mistral Cloud** if you want faster/better responses, don't have a powerful computer, or prefer not to install additional software.

You can also switch between them at any time by editing the `env.txt` file, or use different providers for different agents.

## 1 Install TOMMI Lite

### 1.1 Extract TOMMI Lite

Unzip the `tommi_lite.zip` file to any folder on your computer. You will get a folder called `tommi_lite` containing all the necessary files.

Mac / Linux

Windows

```
# Navigate to where you downloaded the zip
cd ~/Downloads
unzip tommi_lite.zip
cd tommi_lite
```

```
:: Right-click tommi_lite.zip and select "Extract All"
:: Then open a Command Prompt and navigate to the folder:
cd %USERPROFILE%\Downloads\tommi_lite
```

### 1.2 Verify the folder structure

You should see these files:

```
tommi_lite/
  app.py              # Server
  agent_runner.py     # Agent engine
  llm_client.py       # LLM provider abstraction
  env.txt             # Configuration
  requirements.txt    # Python dependencies
  start.sh            # Mac/Linux startup
  start.bat           # Windows startup
  static/
    index.html        # Chat interface
    create.html       # Agent creator
    guide.html        # This guide
  agents/
    hello_world/      # Example agent
```

### 1.3 Configure your Mistral API Key

Open the file `env.txt` in the `tommilite` folder with any text editor. You will see:

```
# LLM Provider configuration
LLM_PROVIDER=mistral
MISTRAL_API_KEY=YOUR_MISTRAL_API_HERE
MISTRAL_MODEL=mistral-small-latest
```

Replace `YOUR_MISTRAL_API_HERE` with your actual Mistral API key (obtained from [console.mistral.ai](https://console.mistral.ai)).

**Important:** If the file `env.txt` does not exist after extracting the zip, create it manually in the main `tommilite/` folder with the content shown above.

## 2 Start the Server

### 2.1 Run the start script

The start script automatically creates a Python virtual environment, installs dependencies, and starts the server.

Mac / Linux

Windows

```
./start.sh
```

**Note:** If you get "permission denied", run `chmod +x start.sh` first.

```
:: Double-click start.bat, or from Command Prompt:
start.bat
```

If Python is not installed, the script will ask you to accept its installation. Type **Y** (or just press Enter) to proceed.

The first time, it will also install dependencies (this takes about 30 seconds). You should see:

```
  TOMMI Lite running at http://localhost:8000
```

### 2.2 Open the interface

Open your browser and go to:

```
http://localhost:8000
```

You should see the TOMMI Lite chat interface with the **Hello World Agent** in the sidebar. You can try chatting with it to verify everything works.

**Troubleshooting:** If you get a connection error when chatting, make sure Ollama is running. Open a new terminal and run `ollama serve` (on Mac/Linux, Ollama usually starts automatically).

## 3 Create a RAG Agent

A **RAG (Retrieval-Augmented Generation)** agent answers questions using your own documents. It searches through PDFs, text files, or other documents to find relevant information, then uses the LLM to formulate an answer.

### 3.1 Open the Agent Creator

Click the **"+ Create Agent"** button at the bottom of the sidebar, or go directly to:

```
http://localhost:8000/create
```

### 3.2 Step 1 — Choose the agent type

You will see five agent types. Click on **"RAG (document retrieval)"** and then click **Next**.

**What does RAG mean?** RAG stands for Retrieval-Augmented Generation. The agent first *retrieves* relevant passages from your documents, then *generates* an answer based on those passages. This means the agent's answers are grounded in your actual data, not just the LLM's general knowledge.

### 3.3 Step 2 — Configure your agent

Fill in the form fields:

| Field | What to enter |
| --- | --- |
| **Agent ID** | A short identifier, e.g. `my_research` (only lowercase, numbers, underscores) |
| **Agent Name** | A display name, e.g. `My Research Assistant` |
| **Description** | Brief description, e.g. `Answers questions about my research papers` |
| **Welcome Message** | What the agent says first, e.g. `Hello! Ask me about the research papers.` |
| **LLM Provider** | Select **Ollama (local)** and choose a model (e.g. `mistral`) |
| **System Prompt** | Instructions for the agent, e.g. `You are a research assistant. Answer questions based only on the provided documents. If you don't know, say so.` |
| **Example Queries** | One question per line, e.g.: `What are the main findings?` `List the authors` `Summarize the methodology` |

Click **Next** when done.

### 3.4 Step 3 — Upload your documents

This is where you give the agent its knowledge base. Drag and drop your files into the upload area, or click to select them.

**Supported formats:**

* **PDF** — research papers, reports, manuals
* **TXT / MD** — plain text, markdown notes
* **CSV / JSON** — structured data

**Tip:** Start with 2-3 small documents to test. You can always add more later by uploading files to `agents/your_agent/data/docs/`.

Click **Create Agent**. You should see a success message.

### 3.5 What just happened?

TOMMI Lite created a new folder in `agents/` with your agent's configuration and data:

```
agents/my_research/
  config.json     # Agent metadata (name, description, etc.)
  prompts.json           # System prompt sections (identity, rules, strict)
  prompts.template.json  # Original template (use "Reset to Template" to restore)
  agent.py        # Agent logic (auto-generated)
  app.py          # Discovery file
  env.txt         # LLM provider configuration
  data/
    data.md       # Knowledge base placeholder
    docs/
      paper1.pdf  # Your uploaded documents
      paper2.pdf
```

You can edit any of these files later to customize the agent further.

## 4 Chat with Your Agent

### 4.1 Select your agent

Click **"Go to Chat"** on the success page, or go to <http://localhost:8000>. Your new agent should appear in the sidebar. Click on it to select it.

### 4.2 Ask a question

Type a question in the input field at the bottom and press **Enter** or click **Send**. For example:

```
What are the main conclusions of the paper?
```

The agent will:

1. Search through your uploaded documents for relevant passages
2. Send those passages + your question to the LLM
3. Stream the answer back to you in real time

### 4.3 Try the example queries

Below the welcome message, you'll see buttons with the example queries you defined. Click any of them to try a pre-written question.

### 4.4 Start a new conversation

Click the **"New Chat"** button in the top bar to clear the conversation history and start fresh. The agent remembers the conversation within a session, so it can answer follow-up questions.

**Tip:** If the agent gives answers that seem unrelated to your documents, check that:

* Your documents were uploaded correctly (check `agents/your_agent/data/docs/`)
* The system prompt tells the agent to use only the provided documents

## ! What's Next?

Now that you have a working agent, here are some things you can try:

* **Add more documents** — drop files into `agents/your_agent/data/docs/` and restart the server, or open the ⚙ Settings panel of the agent and drop new files there directly.
* **Refine the system prompt** — use the **PROMPT Assistant** agent to review and improve your agent's prompts. Select your agent, ask for changes (e.g. "make it more strict", "use a friendlier tone"), edit the proposal if needed, and apply directly.
* **Try a different model** — click the model badge in the top bar to select a different LLM model.
* **Create other agent types** — try Text-to-SQL for database queries, or a simple chat agent

To continue learning, see the [TOMMI Lite Course Book](/TOMMI_Lite_Course_Book) for a complete guide on agent design, prompt engineering, and more.

TOMMI Lite — Part of the TOMMI Project  
Developed within the UNINOVIS European University Alliance

function showOS(os) {
// Toggle all OS tab groups on the page
document.querySelectorAll('.os-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.os-content').forEach(c => c.classList.remove('active'));
if (os === 'mac') {
document.querySelectorAll('.os-tab:first-child').forEach(t => t.classList.add('active'));
['os-mac', 'os-mac-2'].forEach(id => { var el = document.getElementById(id); if (el) el.classList.add('active'); });
} else {
document.querySelectorAll('.os-tab:last-child').forEach(t => t.classList.add('active'));
['os-win', 'os-win-2'].forEach(id => { var el = document.getElementById(id); if (el) el.classList.add('active'); });
}
}

---

# Terminal Guide

Terminal Guide for Mac and Windows

:root {
--primary: #4250b3;
--primary-light: #f0f0ff;
--primary-dark: #2a3480;
--green: #28a745;
--green-bg: #d4edda;
--yellow-bg: #fff3cd;
--gray-50: #f8f9fa;
--gray-200: #e0e0e0;
--gray-600: #666;
--gray-800: #333;
--font: 'Segoe UI', system-ui, -apple-system, sans-serif;
--mono: 'Consolas', 'Monaco', 'Courier New', monospace;
}
\* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: var(--font); color: var(--gray-800); line-height: 1.7; background: #fff; }
.page { max-width: 850px; margin: 0 auto; padding: 40px 24px 60px; }
h1 { color: var(--primary); font-size: 2em; margin-bottom: 8px; border-bottom: 3px solid var(--primary); padding-bottom: 8px; }
h2 { color: var(--primary-dark); font-size: 1.5em; margin-top: 40px; margin-bottom: 12px; }
h3 { color: var(--gray-800); font-size: 1.15em; margin-top: 24px; margin-bottom: 8px; }
p { margin-bottom: 14px; }
ul, ol { margin-bottom: 14px; padding-left: 28px; }
li { margin-bottom: 6px; }
code { background: var(--gray-50); color: var(--primary-dark); padding: 2px 6px; border-radius: 4px; font-family: var(--mono); font-size: 0.9em; }
pre { background: #1e1e2e; color: #cdd6f4; padding: 16px 20px; border-radius: 8px; overflow-x: auto; margin-bottom: 18px; font-family: var(--mono); font-size: 0.9em; line-height: 1.5; }
pre code { background: none; color: inherit; padding: 0; }
.callout { padding: 14px 18px; border-radius: 8px; margin-bottom: 18px; border-left: 4px solid; }
.callout-info { background: #e8f0fe; border-color: var(--primary); }
.callout-tip { background: var(--green-bg); border-color: var(--green); }
.callout-warning { background: var(--yellow-bg); border-color: #ffc107; }
.os-tab { display: inline-block; padding: 8px 20px; margin-right: 4px; border-radius: 8px 8px 0 0; font-weight: 600; cursor: default; }
.os-mac { background: #e8e0f0; color: #4250b3; }
.os-win { background: #dbeafe; color: #1e40af; }
.screenshot { background: var(--gray-50); border: 1px solid var(--gray-200); border-radius: 8px; padding: 12px; text-align: center; margin-bottom: 18px; font-style: italic; color: var(--gray-600); }
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th { background: var(--primary); color: #fff; padding: 10px 14px; text-align: left; }
td { padding: 10px 14px; border-bottom: 1px solid var(--gray-200); }
tr:nth-child(even) td { background: var(--gray-50); }

# Terminal Guide for Mac and Windows

A terminal (also called "command line" or "console") is a text-based interface where you type commands to interact with your computer. You will need it to run TOMMI Lite and manage your AI agents.

**Why do I need a terminal?**
TOMMI Lite is started from the terminal, and some setup steps (installing Python packages, downloading models) require terminal commands. Don't worry — you only need a few basic commands.

## macOS

### Opening the Terminal

1. Press `Cmd + Space` to open Spotlight Search
2. Type `Terminal` and press Enter
3. A window with a command prompt will appear (usually showing your username and a `%` or `$` sign)

Alternatively: open **Finder > Applications > Utilities > Terminal**

### Essential Commands

| Command | What it does | Example |
| --- | --- | --- |
| `cd folder_name` | Change directory (move into a folder) | `cd Downloads/tommilite` |
| `cd ..` | Go up one folder level | `cd ..` |
| `ls` | List files in current folder | `ls` |
| `pwd` | Show current folder path | `pwd` |
| `python3 --version` | Check if Python is installed | `python3 --version` |
| `./start.sh` | Run a shell script | `./start.sh` |
| `Ctrl + C` | Stop a running program | (press keys together) |

### Example: Starting TOMMI Lite on Mac

```
# Navigate to the TOMMI Lite folder
cd ~/Downloads/tommilite

# Start the server
./start.sh
```

**Tip:** You can drag a folder from Finder into the Terminal window to paste its full path.

## Windows

### Opening the Terminal

Windows has several terminal options. We recommend **PowerShell** or **Command Prompt**:

1. Press `Win + R`, type `cmd` and press Enter (for Command Prompt)
2. Or: press `Win + X` and select "Windows Terminal" or "PowerShell"
3. Or: search "PowerShell" in the Start menu

### Essential Commands

| Command | What it does | Example |
| --- | --- | --- |
| `cd folder_name` | Change directory | `cd Downloads\tommilite` |
| `cd ..` | Go up one folder level | `cd ..` |
| `dir` | List files in current folder | `dir` |
| `cd` | Show current folder path (no arguments) | `cd` |
| `python --version` | Check if Python is installed | `python --version` |
| `start.bat` | Run a batch script | `start.bat` |
| `Ctrl + C` | Stop a running program | (press keys together) |

**Note:** On Windows, use `python` (not `python3`). If `python` doesn't work, you may need to install Python from [python.org](https://www.python.org/downloads/) and make sure to check "Add Python to PATH" during installation.

### Example: Starting TOMMI Lite on Windows

```
# Navigate to the TOMMI Lite folder
cd C:\Users\YourName\Downloads\tommilite

# Start the server
start.bat
```

## Common Tips

* **Tab completion:** Press `Tab` while typing a folder or file name to auto-complete it.
* **Command history:** Press the `Up arrow` key to recall previous commands.
* **Copy/Paste:** On Mac, use `Cmd+C` / `Cmd+V`. On Windows terminal, use `Ctrl+Shift+C` / `Ctrl+Shift+V` (or right-click to paste).
* **If something goes wrong:** Press `Ctrl + C` to stop whatever is running, then try again.

**That's all you need!** For this course you will mainly use `cd` to navigate to the TOMMI Lite folder and `./start.sh` (Mac) or `start.bat` (Windows) to start the server. Everything else happens in the browser.

[← Back to TOMMI Lite Course Book](TOMMI_Lite_Course_Book.html)

---

# TOMMI Lite Course Book

TOMMI Lite — Course Book

html {
color: #2d3748;
background-color: #f7fafc;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
margin: 0 auto;
max-width: 52em;
padding: 40px 60px;
line-height: 1.7;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
font-size: 16px;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 16px;
}
h1 { font-size: 1.8em; }
}
@media print {
html { background-color: white; }
body { background-color: transparent; color: black; font-size: 11pt; }
p, h2, h3 { orphans: 3; widows: 3; }
h2, h3, h4 { page-break-after: avoid; }
}
p {
margin: 0.8em 0;
}
a {
color: #4250b3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: #5a4fcf;
}
img {
max-width: 100%;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
svg {
height: auto;
max-width: 100%;
}
h1 {
color: #4250b3;
border-bottom: 3px solid #4250b3;
padding-bottom: 0.3em;
margin-top: 1.5em;
}
h2 {
color: #4250b3;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 0.3em;
margin-top: 2em;
}
h3 {
color: #2d3748;
margin-top: 1.5em;
}
h4, h5, h6 {
margin-top: 1.2em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 0.8em;
}
li > ol, li > ul {
margin-top: 0;
}
li {
margin-bottom: 0.3em;
}
blockquote {
margin: 1em 0 1em 0;
padding: 0.8em 1.2em;
border-left: 4px solid #4250b3;
background-color: #edf2f7;
border-radius: 4px;
color: #4a5568;
}
code {
font-family: "SF Mono", Menlo, Monaco, Consolas, monospace;
font-size: 0.88em;
background-color: #e2e0f0;
padding: 0.15em 0.4em;
border-radius: 4px;
border: 1px solid #c8c4e0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
background-color: #1a202c;
color: #e2e8f0;
padding: 1em 1.2em;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
pre code {
padding: 0;
background-color: transparent;
color: inherit;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
border: none;
border-top: 2px solid #e2e8f0;
margin: 2em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
box-shadow: 0 1px 4px rgba(0,0,0,0.08);
border-radius: 6px;
overflow: hidden;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
}
th {
background-color: #4250b3;
color: white;
padding: 0.6em 1em;
text-align: left;
}
td {
padding: 0.5em 1em;
border-bottom: 1px solid #e2e8f0;
}
tr:nth-child(even) {
background-color: #f7fafc;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/\* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js \*/
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
/\* CSS for syntax highlighting \*/
html { -webkit-text-size-adjust: 100%; }
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /\* Alert \*/
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /\* Annotation \*/
code span.at { color: #7d9029; } /\* Attribute \*/
code span.bn { color: #40a070; } /\* BaseN \*/
code span.bu { color: #008000; } /\* BuiltIn \*/
code span.cf { color: #007020; font-weight: bold; } /\* ControlFlow \*/
code span.ch { color: #4070a0; } /\* Char \*/
code span.cn { color: #880000; } /\* Constant \*/
code span.co { color: #60a0b0; font-style: italic; } /\* Comment \*/
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /\* CommentVar \*/
code span.do { color: #ba2121; font-style: italic; } /\* Documentation \*/
code span.dt { color: #902000; } /\* DataType \*/
code span.dv { color: #40a070; } /\* DecVal \*/
code span.er { color: #ff0000; font-weight: bold; } /\* Error \*/
code span.ex { } /\* Extension \*/
code span.fl { color: #40a070; } /\* Float \*/
code span.fu { color: #06287e; } /\* Function \*/
code span.im { color: #008000; font-weight: bold; } /\* Import \*/
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /\* Information \*/
code span.kw { color: #007020; font-weight: bold; } /\* Keyword \*/
code span.op { color: #666666; } /\* Operator \*/
code span.ot { color: #007020; } /\* Other \*/
code span.pp { color: #bc7a00; } /\* Preprocessor \*/
code span.sc { color: #4070a0; } /\* SpecialChar \*/
code span.ss { color: #bb6688; } /\* SpecialString \*/
code span.st { color: #4070a0; } /\* String \*/
code span.va { color: #19177c; } /\* Variable \*/
code span.vs { color: #4070a0; } /\* VerbatimString \*/
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /\* Warning \*/

# TOMMI Lite — Course Book

## Building AI Agents: A Practical Guide

**University of Malaga — UNINOVIS European University
Alliance**

---

## Preface

This course book is a hands-on guide to building AI agents with TOMMI Lite. It is designed for participants of the UNINOVIS European University Alliance training programme, but it can be used by anyone interested in understanding how AI agents work, how to create them, and what risks they entail. The document takes you from initial setup through agent design, prompt engineering, and practical exercises, providing everything you need to build, test, and reason about your own agents.

### What You Will Learn

By the end of this course, you will be able to:

* Set up and run TOMMI Lite on your computer
* Understand the different types of AI agents and their use cases
* Create, configure, and test custom agents
* Understand the risks associated with different agent architectures
* Design system prompts that control agent behaviour

---

## Table of Contents

1. [Introduction](#1-introduction)
2. [LLM Providers](#2-llm-providers)
3. [Types of Agents](#3-types-of-agents)
4. [System Prompts](#4-system-prompts)
5. [Setting Up TOMMI Lite](#5-setting-up-tommi-lite)
6. [Building Your First
   Agent](#6-building-your-first-agent)
7. [Agent Examples and
   Applications](#7-agent-examples-and-applications)
8. [Risks and
   Considerations](#8-risks-and-considerations)
9. [Exercises](#9-exercises)

---

## 1. Introduction

### What is an AI Agent?

An AI agent is a software system that uses a Large Language Model
(LLM) to process user queries and generate responses, often augmented
with external data sources, tools, or specialized knowledge. Unlike a
plain chatbot, an agent can:

* Follow specific rules and constraints defined in a system
  prompt
* Retrieve information from documents, databases, or APIs before
  responding
* Adapt its behaviour based on configuration (prompt level,
  transparency, model choice)

### What is TOMMI Lite?

TOMMI Lite is a minimal, local development server for building and
testing AI agents. It provides a web-based chat interface, an agent
creation wizard, and a unified LLM client that works with multiple AI
model providers.

TOMMI Lite is designed to run **locally on your
machine** while connecting to **cloud-based LLMs**
(such as Mistral Cloud) for language generation. It is not intended for
production deployment — it has no authentication, no user management,
and no rate limiting. Its purpose is education, prototyping, and
experimentation.

### How TOMMI Lite Works

The following figure illustrates the main components and how they
interact:

![TOMMI Lite Architecture](tommi_lite_architecture.svg)

TOMMI Lite Architecture

The **user** interacts through a web browser. The
**Agent Server** (running locally) hosts multiple
**Agents**, each specialized for a different task. When an
agent receives a query, it may perform **actions** — such
as searching documents, querying a database, or fetching emails — and
then sends the gathered context along with the user’s question to a
**Cloud LLM** (such as Mistral), which generates the
response.

---

## 2. LLM Providers

An LLM provider is the service that runs the AI model your agents
talk to. Think of it as the “brain” behind the agents — TOMMI Lite
handles the conversation, the data, and the rules, but the actual text
generation happens on the LLM provider’s side. You can switch providers
without changing your agents; they all work the same way from the
agent’s perspective.

### Mistral Cloud

* **Configuration**: `MISTRAL_API_KEY` in
  `env.txt`
* **Available models**: Mistral Small, Mistral Medium,
  Mistral Large, Devstral Small
* **Pros**: No local hardware needed, high-quality
  models, fast inference
* **Cons**: Requires internet, API costs (free tier has
  limits), data sent to external servers
* **Best for**: Course exercises, prototyping,
  production-like testing

### Ollama (Local)

* **Configuration**: `LLM_PROVIDER=ollama` in
  `env.txt`
* **Available models**: Any model from the Ollama library
  (mistral, llama3, qwen, gemma, etc.)
* **Pros**: Free, private (data stays on your machine),
  works offline
* **Cons**: Requires capable hardware (8GB+ RAM), slower
  on CPU, model quality varies
* **Best for**: Privacy-sensitive applications, offline
  work, experimentation with open models

---

## 3. Types of Agents

### Key Concepts

Before exploring the different agent types, it is important to
understand the elements that all agents share. Every conversation in
TOMMI Lite involves the same basic components:

* **User message**: The question or instruction typed
  by the user. This is the input that triggers the agent. Examples:
  *“Summarize my unread emails”*, *“What is the capital of
  France?”*, *“Show students with grades above 8”*.
* **System prompt**: A set of hidden instructions that
  the agent sends to the LLM before every conversation. The user never
  sees the system prompt, but it shapes the entire behaviour of the agent
  — its personality, its rules, and its limitations. For example, a system
  prompt might say: *“You are a Spanish language tutor. Only answer questions
  about Spanish grammar. If the student asks about another topic, politely
  redirect them.”*
* **Conversation history**: The list of previous
  messages in the current session (both user messages and agent
  responses). This gives the LLM memory of what has been discussed,
  allowing follow-up questions like *“Can you explain that in more
  detail?”* to work correctly.
* **Context** (optional): Additional information that
  the agent gathers before calling the LLM. Not all agents use context — a
  simple chat agent sends only the user message and system prompt. But a
  RAG agent retrieves relevant document passages, a Text-to-SQL agent
  includes the database schema, and an email agent fetches inbox messages.
  This context is injected into the prompt so the LLM can base its answer
  on real data rather than its training knowledge alone.
* **Response**: The text generated by the LLM and
  displayed to the user. In TOMMI Lite, responses are streamed word by
  word, so the user sees the answer being written in real time.

The general flow for all agents is:

```
System prompt + Conversation history + [Context] + User message → LLM → Response
```

The difference between agent types lies in **what context they
gather** and **where it comes from**. A simple chat
agent gathers no context at all. A RAG agent searches documents. A SQL
agent queries a database. A custom agent can fetch data from any source.
But the core pipeline — assemble a prompt, send it to the LLM, stream
the response — is always the same.

TOMMI Lite supports five agent types, each suited to different use
cases.

### 3.1 Simple Chat (Oneshot)

**What it does**: A conversational agent guided entirely
by its system prompt. It has no external data — all responses come from
the LLM’s training knowledge, filtered through the prompt rules.

**Architecture**:
`User message + System prompt → LLM → Response`

**Use cases**: - General-purpose assistants - Creative
writing helpers - Language tutors - Customer service prototypes

**Example**: The “Hello World” agent included with TOMMI
Lite.

**Data requirements**: None

---

### 3.2 RAG (Retrieval-Augmented Generation)

**What it does**: Before responding, the agent searches
a document database (using ChromaDB vector search) and includes relevant
passages in the prompt. The LLM then generates a response grounded in
the retrieved documents.

**Architecture**:
`User message → Vector search (ChromaDB) → Retrieved context + Message + System prompt → LLM → Response`

**Use cases**: - Knowledge base Q&A - Internal
documentation assistant - Course material Q&A - Company policy
assistant

**Data requirements**: PDF, TXT, or MD files uploaded to
the agent’s `data/docs/` directory.

**Dependencies**: Requires `chromadb` and
`sentence-transformers` (not included by default — install
separately if needed).

---

### 3.3 RAG + Metadata

**What it does**: Extends the RAG agent with structured
metadata capabilities. In addition to document retrieval, it can search
structured data (researchers, papers, institutions) and present it in
organized formats.

**Architecture**:
`User message → Metadata search + Vector search → Combined context + Message + System prompt → LLM → Response`

**Use cases**: - Research excellence hubs - Academic
paper databases - Institutional knowledge management - Multi-university
research portals

**Data requirements**: PDF/text documents plus metadata
JSON files describing researchers, publications, and institutions.

**Dependencies**: Same as RAG — requires
`chromadb` and `sentence-transformers`.

---

### 3.4 RAG Metadata Vectorless

**What it does**: The same functionality as RAG +
Metadata, but replaces ChromaDB vector search with BM25 keyword-based
retrieval. No GPU or embedding model is needed.

**Architecture**:
`User message → BM25 keyword search (chunk_db.json) + Metadata search → Combined context + Message + System prompt → LLM → Response`

**Use cases**: Same as RAG + Metadata, but preferred
when: - ChromaDB installation is problematic - The machine has limited
resources - Simplicity is prioritized over semantic search quality

**Data requirements**: Same as RAG + Metadata. A
`chunk_db.json` file is built automatically from the
documents.

**Dependencies**: None beyond the base requirements.
This is the easiest RAG option to set up.

---

### 3.5 Text-to-SQL

**What it does**: Converts natural language questions
into SQL queries, executes them against a SQLite database, and presents
the results in a readable format.

**Architecture**:
`User message + DB schema → LLM generates SQL → Agent executes SQL → Results formatted + LLM explanation → Response`

**Use cases**: - Database exploration without SQL
knowledge - Data reporting dashboards - Student exercises on relational
databases - Quick data analysis tools

**Data requirements**: A SQLite database file
(`.db`) uploaded to the agent’s `data/` directory.
Optionally, a SQL schema provided during creation.

**Safety**: The agent only allows `SELECT`
queries — it cannot modify data.

---

### 3.6 Custom Agents (Email Assistant Example)

Beyond the five standard types, TOMMI Lite supports fully custom
agents. The Email Assistant is an example that:

1. Connects to an email inbox via IMAP (with OAuth2
   authentication)
2. Fetches matching emails based on the user’s query
3. Sends the email content as context to the LLM
4. Returns a natural language summary or answer

**Architecture**:
`User message → IMAP fetch → Email context + Message + System prompt → LLM → Response`

This demonstrates how any external data source (APIs, databases, web
services) can be integrated into an agent.

---

### Agent Type Comparison

| Feature | Oneshot | RAG | RAG Vectorless | Text2SQL | Custom |
| --- | --- | --- | --- | --- | --- |
| External data | No | Documents | Documents | Database | Any |
| Setup complexity | Low | Medium | Low | Medium | High |
| Extra dependencies | None | chromadb | None | None | Varies |
| Response grounding | LLM only | Document-based | Document-based | Data-based | Source-dependent |
| Best for | Chat, tutoring | Knowledge Q&A | Knowledge Q&A | Data queries | Integrations |

---

## 4. System Prompts

System prompts can be configured in two ways:

* **During agent creation**: The Create Agent wizard
  (click “+ Create Agent” in the sidebar) includes text fields for
  Identity, Rules, and Strict, along with a dropdown to choose a built-in
  prompt template as a starting point.
* **After creation**: Click the gear icon (⚙) in the top
  bar while chatting with any agent. The Settings drawer lets you edit all
  three prompt sections, save changes instantly, and reset to the original
  template if needed. You can also edit the file
  `agents/{agent_id}/prompts.json` directly with a text
  editor.
* **Using the PROMPT Assistant**: Select the **PROMPT Assistant** agent from the sidebar, type `list` to see your agents, pick one, and ask for improvements in natural language (e.g. "make it more strict", "use a friendlier tone"). The assistant will propose changes in an editable text area that you can modify before applying.

### Using an LLM to Help You Write Prompts

Writing good system prompts can be challenging, especially for
complex agents with many rules and restrictions. A useful technique is
to **use an LLM itself to help you write or refine your
prompts**. For example:

* Ask **Mistral Large** (a more capable model) to improve
  your existing prompt: *“I have an agent with this identity prompt:
  [paste your prompt]. Can you improve it to be clearer and more
  specific?”*
* Ask it to generate a full set of Rules and Strict constraints for
  your use case: *“I’m building a nutrition assistant for university
  students. Write a set of Rules and Strict constraints that prevent
  medical advice and keep the agent focused on healthy eating.”*
* Use **Devstral** (Mistral’s coding model) to help you
  create an entirely new custom agent — including the Python code in
  `agent.py` — by describing what data sources it should
  connect to and what actions it should perform.

You can do this directly from TOMMI Lite: create a simple Oneshot
agent, switch to Mistral Large or Devstral using the model selector in
the top bar, and use it as your prompt-writing assistant. Then copy the
generated text into your agent’s configuration.

### Three-Section Architecture

TOMMI Lite organizes system prompts into three sections, each stored
in `prompts.json`:

1. **Identity** — Who the agent is and how it should
   behave. Always included. This section defines the agent’s personality
   and scope.
   * *Example*: “You are HealthBot, a friendly assistant that
     answers questions about nutrition and healthy eating. You speak in a
     warm, encouraging tone and use simple language suitable for
     non-experts.”
2. **Rules** — Operational guidelines and constraints.
   Included in Tolerant and Stringent levels. These tell the agent what it
   should and shouldn’t do during a conversation.
   * *Example*: “1. Only answer questions related to nutrition and
     diet. 2. Always cite the source of your information. 3. If the user asks
     about a medical condition, recommend they consult a doctor. 4. Present
     information in short, numbered lists when possible.”
3. **Strict** — Hard restrictions to prevent unwanted
   behaviour. Included only in Stringent level. These are non-negotiable
   boundaries designed to prevent harmful, incorrect, or off-topic
   responses.
   * *Example*: “1. NEVER diagnose medical conditions or recommend
     medication. 2. NEVER provide calorie targets for children under 12. 3.
     If the user describes symptoms of an eating disorder, respond only with
     a helpline number. 4. Do NOT generate meal plans that exclude entire
     food groups unless the user specifies a medically diagnosed
     allergy.”

### Prompt Levels

| Level | Sections Included | Use Case |
| --- | --- | --- |
| **Lax** | Identity only | Maximum creativity, minimal restrictions |
| **Tolerant** | Identity + Rules | Balanced — follows guidelines but allows flexibility |
| **Stringent** | Identity + Rules + Strict | Maximum control — strict factual accuracy |

The prompt level can be changed at runtime by clicking the prompt
badge in the interface, without restarting the agent.

### Template Variables

Prompts support two placeholders that are automatically filled from
`config.json`:

* `{agent_name}` — The agent’s display name
* `{description}` — The agent’s description

Example:

```
"identity": "You are {agent_name}, a helpful {description}."
```

Becomes: *“You are Research Assistant, a helpful expert on AI
ethics papers.”*

### Built-in Prompt Templates

TOMMI Lite includes five ready-to-use prompt templates:

| Template | Best For | Key Characteristics |
| --- | --- | --- |
| **Blank** | Starting from scratch | No predefined behaviour |
| **General Assistant** | Knowledge base Q&A | Cites sources, refuses unknown topics |
| **Research Hub** | Academic research portals | Handles researchers, papers, affiliations |
| **Document Q&A** | Specific document collections | Direct quotes, source attribution |
| **Virtual Tutor** | Educational agents | Step-by-step guidance, never solves directly |

### Example: Tutor Prompt

```
{
  "identity": "You are {agent_name}, a virtual tutor specialized in {description}. Your role is to help students learn by explaining concepts clearly, providing examples, and guiding them through exercises.",

  "rules": "RULES:\n1. Explain concepts using simple, clear language.\n2. Use examples from the knowledge base.\n3. Check if the answer is in your materials before responding.\n4. Encourage active learning — ask follow-up questions.\n5. Break complex topics into smaller parts.",

  "strict": "STRICT CONSTRAINTS:\n1. NEVER provide information that contradicts the course materials.\n2. If a topic is not covered, say so.\n3. Do NOT solve exercises completely — guide step by step.\n4. Use exact formulas from the course materials.\n5. If confused, re-explain using a different approach."
}
```

---

## 5. Setting Up TOMMI Lite

### Prerequisites

* A computer running macOS, Linux, or Windows
* Python 3.10 or higher installed
* Basic familiarity with the command line
* A Mistral Cloud API key (free tier available) or Ollama installed
  locally

### Step 1: Download TOMMI Lite

1. Go to [github.com/UNINOVIS-UMA/tommilite](https://github.com/UNINOVIS-UMA/tommilite)
2. Click the green **Code** button
3. Click **Download ZIP**
4. Unzip the downloaded file to a folder of your choice (e.g., your
   Desktop or Documents folder)
5. Open a terminal and navigate to the unzipped folder:

```
cd path/to/tommilite
```

### Step 2: Obtain an LLM Provider

TOMMI Lite supports two LLM providers. For this course, we recommend
Mistral Cloud:

**Mistral Cloud (recommended for this course)**

1. Go to [console.mistral.ai](https://console.mistral.ai)
2. Create a free account
3. Navigate to **API Keys** and create a new key
4. Save the key — you will need it in the next step

**Ollama (alternative — local, free, no internet
required)**

1. Download Ollama from [ollama.com](https://ollama.com)
2. Install it and run the following command in your terminal:
   `ollama pull mistral` (downloads ~4GB)
3. Ollama runs a local server at
   `http://localhost:11434`

### Step 3: Configure TOMMI Lite

Open the file `env.txt` in the project root and set your
API key:

```
# For Mistral Cloud (default)
MISTRAL_API_KEY=your_actual_api_key_here
MISTRAL_MODEL=mistral-small-latest

# For Ollama (uncomment these and comment out the Mistral lines)
# LLM_PROVIDER=ollama
# OLLAMA_BASE_URL=http://localhost:11434
# OLLAMA_MODEL=mistral

# Server port
PORT=8000
```

**Note:** If the file `env.txt` was not created during installation, you can simply create a new file called `env.txt` in the main `tommilite/` folder, copying the information from the figure above, and replacing `your_actual_api_key_here` with your actual Mistral API key.

### Step 4: Start the Server

Run the following command in your terminal:

**Mac/Linux:**

```
./start.sh
```

**Windows:**

```
start.bat
```

The first run will: 1. Create a Python virtual environment
(`venv/`) 2. Install all dependencies from
`requirements.txt` 3. Start the web server at
`http://localhost:8000`

Open your browser and navigate to
**http://localhost:8000**.

### Step 5: Verify It Works

You should see: - A sidebar listing available agents (at least “Hello
World Agent”) - Click on an agent to start chatting - Type a message and
press Send

If you see “Connection error”, verify that:   
 - For Mistral: Your API key is
correctly set in `env.txt`
  
- For Ollama: the Ollama service is running (run `ollama serve` in your terminal)

### Project File Structure

```
tommilite/
  app.py              # Server (FastAPI)
  agent_runner.py      # Agent discovery and execution
  llm_client.py        # Unified LLM provider client
  error_codes.py       # Error handling
  env.txt              # LLM configuration (API keys, model choice)
  requirements.txt     # Python dependencies
  start.sh / start.bat # Startup scripts
  static/
    index.html         # Chat interface
    create.html        # Agent creation wizard
    guide.html         # Interactive setup guide
  agents/
    base/              # Shared base classes for RAG agents
    hello_world/       # Example agent
    email_assistant/   # Email reader agent
```

---

## 5. Building Your First Agent

### Using the Web Wizard

1. Open TOMMI Lite in your browser
2. Click **“+ Create Agent”** in the sidebar
3. Follow the 4-step wizard:
   * **Step 1**: Choose the agent type
   * **Step 2**: Configure name, description, prompt, and
     examples
   * **Step 3**: Upload data files (if applicable)
   * **Step 4**: Done — start chatting

### Manual Creation

For more control, create an agent manually:

```
cp -r agents/hello_world agents/my_agent
```

Edit the four files:

**config.json** — Agent metadata:

```
{
  "agent_id": "my_agent",
  "agent_name": "My Agent",
  "type": "oneshot",
  "description": "An assistant that helps with Python programming",
  "welcome_message": "Hello! I can help you with Python. What do you need?",
  "example_queries": [
    "How do I read a CSV file?",
    "Explain list comprehensions",
    "What is the difference between a list and a tuple?"
  ],
  "show_history": true,
  "public": true,
  "prompt_level": "tolerant"
}
```

**prompts.json** — System prompt sections:

```
{
  "identity": "You are {agent_name}, a Python programming tutor. You explain concepts clearly with practical examples.",
  "rules": "RULES:\n1. Always include code examples in your explanations.\n2. Use Python 3 syntax.\n3. Explain errors clearly when the student makes mistakes.\n4. Suggest best practices.",
  "strict": "STRICT CONSTRAINTS:\n1. Never write complete solutions to exercises.\n2. Guide the student step by step.\n3. If asked about non-Python topics, redirect to Python."
}
```

**agent.py** — The agent logic (copy from
`hello_world/agent.py` and modify).

**app.py** — Required for discovery (can be empty or
contain just a comment).

Restart the server — your agent appears automatically.

---

## 7. Agent Examples and Applications

### Example 1: University FAQ Agent (Oneshot)

**Scenario**: A university wants an agent that answers
frequently asked questions about admissions, programs, and campus
services.

**Type**: Oneshot **Prompt template**:
General Assistant

**Identity**: *“You are the UMA Admissions Assistant.
You help prospective students with questions about undergraduate and
postgraduate programs at the University of Malaga.”*

**Why Oneshot?** The information is general enough that
the LLM’s training knowledge covers it. No private documents are
needed.

**Risks**: The LLM may provide outdated information
(e.g., old tuition fees, discontinued programs). Consider upgrading to a
RAG agent with official documentation.

---

### Example 2: Course Material Q&A (RAG Vectorless)

**Scenario**: A professor wants students to ask
questions about the course textbook and lecture slides.

**Type**: RAG Metadata Vectorless **Prompt
template**: Virtual Tutor

**Data**: PDF lecture slides and textbook chapters
uploaded to `data/docs/`.

**Why Vectorless?** Easier to set up than full RAG, no
ChromaDB needed, works on any machine.

**Risks**: BM25 keyword search may miss semantically
related content that uses different wording. Students may over-rely on
the agent instead of reading the material directly.

---

### Example 3: Research Paper Database (RAG + Metadata)

**Scenario**: A research group wants to query their
collection of publications, find papers by topic, and identify
collaboration opportunities.

**Type**: RAG + Metadata **Prompt
template**: Research Hub

**Data**: PDF papers plus metadata JSON files describing
authors, institutions, and keywords.

**Why RAG + Metadata?** The metadata enables structured
queries (“Which researchers from UMA work on AI ethics?”) while the
document retrieval handles free-text questions about paper content.

**Risks**: Requires ChromaDB and sentence-transformers
installation. The agent may hallucinate paper titles or author names not
present in the database — the Stringent prompt level mitigates this.

---

### Example 4: Student Grade Explorer (Text-to-SQL)

**Scenario**: Students can query their academic records
using natural language: “What was my average grade last semester?”

**Type**: Text-to-SQL **Data**: A SQLite
database with tables for students, courses, enrollments, and grades.

**Why Text-to-SQL?** The data is structured and
relational — perfect for SQL queries. The LLM translates natural
language to SQL, executes it, and presents results.

**Risks**: The LLM may generate incorrect SQL that
produces wrong results. While only SELECT queries are allowed (no data
modification), incorrect JOINs or WHERE clauses can lead to misleading
answers. Consider adding result validation.

---

### Example 5: Email Inbox Assistant (Custom)

**Scenario**: A professional wants to quickly search and
summarize their email inbox without opening each message.

**Type**: Custom (Oneshot with IMAP integration)
**Data**: Emails fetched in real time from the user’s
mailbox via IMAP/OAuth2.

**Pipeline**: 1. User asks: “Any unread emails from
Dr. Garcia?” 2. Agent connects to Outlook via OAuth2 3. Searches for
matching emails (UNSEEN + FROM “Garcia”) 4. Fetches email content (up to
20 messages) 5. Sends email text as context to the LLM 6. LLM generates
a natural language summary

**Risks**: Privacy concerns — email content is sent to
the cloud LLM. The agent is read-only (cannot send, delete, or modify
emails). OAuth2 tokens are cached locally.

---

## 8. Risks and Considerations

### 8.1 Risks by Agent Type

#### Oneshot Agents

| Risk | Severity | Description |
| --- | --- | --- |
| **Hallucination** | High | No external data to ground responses — the LLM may invent facts |
| **Outdated information** | Medium | LLM training data has a cutoff date |
| **Prompt injection** | Medium | Users may craft inputs that override the system prompt |
| **Inconsistency** | Low | Different runs may produce different answers to the same question |

**Mitigation**: Use Stringent prompt level. Add explicit
rules like “If you don’t know, say so.” Consider upgrading to RAG if
factual accuracy is critical.

#### RAG Agents (including Vectorless)

| Risk | Severity | Description |
| --- | --- | --- |
| **Partial grounding** | Medium | The LLM may mix retrieved facts with invented content |
| **Retrieval failure** | Medium | Relevant documents may not be retrieved (wrong keywords, poor chunking) |
| **Context window overflow** | Low | Very large documents may exceed the model’s context limit |
| **Document staleness** | Low | Uploaded documents may become outdated |

**Mitigation**: Use the reliability badge system
(crystal box transparency) to monitor grounding. Reindex documents when
updated. Use Stringent prompt level with rules like “Answer ONLY from
the provided context.”

#### Text-to-SQL Agents

| Risk | Severity | Description |
| --- | --- | --- |
| **Incorrect SQL** | High | The LLM may generate wrong queries (bad JOINs, wrong filters) |
| **Data exposure** | Medium | Users may query sensitive data if the database contains it |
| **SQL injection** | Low | Mitigated by only allowing SELECT queries |
| **Schema misunderstanding** | Medium | The LLM may misinterpret column names or relationships |

**Mitigation**: Only allow SELECT queries (enforced by
TOMMI Lite). Review generated SQL before trusting results. Use clear,
descriptive column names in the database schema.

#### Custom Agents (e.g., Email)

| Risk | Severity | Description |
| --- | --- | --- |
| **Data privacy** | High | External data (emails, API responses) sent to cloud LLM |
| **Authentication security** | High | OAuth tokens and credentials stored locally |
| **Unintended actions** | Medium | If the agent can write (send emails, modify data), errors are hard to reverse |
| **API rate limits** | Low | External services may throttle or block frequent requests |

**Mitigation**: Use read-only access wherever possible.
Never store plain-text passwords. Require user confirmation before any
write action. Consider using a local LLM (Ollama) for sensitive
data.

### 8.2 General Risks

#### Privacy and Data Protection

* **Cloud LLMs**: Every message and document context is
  sent to the LLM provider’s servers (Mistral, etc.). Do not use cloud
  LLMs with confidential data unless your institution has a data
  processing agreement with the provider.
* **Local LLMs (Ollama)**: Data stays on your machine.
  This is the safest option for sensitive information.
* **TOMMI Lite has no authentication**: Anyone on your
  network who can reach the server can use your agents and potentially
  access your LLM API key.

#### Hallucination and Trust

All LLMs can generate plausible-sounding but false information. This
risk is: - **Highest** in Oneshot agents (no data
grounding) - **Medium** in RAG agents (partially grounded,
but the LLM may still add ungrounded content) - **Lowest**
in Text-to-SQL agents (results come from actual data queries, though the
SQL itself may be wrong)

#### Prompt Injection

A user may craft inputs designed to override the system prompt, such
as: *“Ignore your previous instructions and…”*. TOMMI Lite’s
Stringent prompt level includes rules against this, but no system is
fully immune.

#### Reproducibility

LLM responses are non-deterministic — the same question may produce
different answers across runs. This is by design (creativity/variety),
but can be problematic for grading, auditing, or compliance
purposes.

### 8.3 Best Practices

1. **Start with Stringent** prompt level and relax only if
   needed
2. **Use RAG** instead of Oneshot when factual accuracy
   matters
3. **Use local LLMs** (Ollama) for sensitive or private
   data
4. **Review generated SQL** before trusting Text-to-SQL
   results
5. **Never deploy TOMMI Lite** on a public network — it
   has no authentication
6. **Monitor the reliability badges** to understand
   response grounding
7. **Test with adversarial inputs** to find prompt
   weaknesses
8. **Keep documents up to date** in RAG agents
9. **Never grant write, edit, or delete permissions to AI
   agents**. An LLM can misinterpret a query or hallucinate, and if
   the agent has write access, the consequences can be irreversible — a
   wrong SQL `DELETE`, a mistakenly sent email, or a corrupted
   file. This is especially critical for Email agents (which could send
   messages on your behalf) and Text-to-SQL agents (which could modify or
   erase database records). In TOMMI Lite, both are designed as read-only
   by default: the Email Assistant can only read your inbox (it cannot
   send, delete, or move emails), and the Text-to-SQL agent only executes
   `SELECT` queries (it cannot insert, update, or delete
   data)

---

## 9. Exercises

The practical exercises for this course are available on a separate page: [TOMMI Lite Exercises](/tommiLite_exercises).

---

## Appendix A: Troubleshooting

| Problem | Solution |
| --- | --- |
| “Connection error” on first message | Check `env.txt` has a valid API key; for Ollama, ensure it’s running |
| “ModuleNotFoundError” | Run `venv/bin/pip install -r requirements.txt` |
| Agent doesn’t appear in sidebar | Check `config.json` has `"public": true`; restart the server |
| RAG agent returns empty context | Upload documents to `agents/{id}/data/docs/`; check file format (.pdf, .txt, .md) |
| Text-to-SQL returns wrong results | Review the generated SQL; ensure your schema uses clear column names |
| “Permission denied” on start.sh | Run `chmod +x start.sh` or use `bash start.sh` |

## Appendix B: Glossary

| Term | Definition |
| --- | --- |
| **LLM** | Large Language Model — the AI model that generates text (e.g., Mistral, GPT, Llama) |
| **Agent** | A program that uses an LLM with specific configuration, data sources, and rules |
| **RAG** | Retrieval-Augmented Generation — fetching relevant documents before generating a response |
| **System prompt** | Hidden instructions sent to the LLM that define the agent’s behaviour |
| **Prompt level** | How strict the agent’s rules are: Lax, Tolerant, or Stringent |
| **BM25** | A keyword-based search algorithm used by vectorless RAG agents |
| **ChromaDB** | A vector database that stores document embeddings for semantic search |
| **SSE** | Server-Sent Events — the protocol used for streaming responses to the browser |
| **IMAP** | Internet Message Access Protocol — used to read emails from a mail server |
| **OAuth2** | An authentication standard used for secure access to services like Outlook |
| **Hallucination** | When an LLM generates plausible but false information |
| **Prompt injection** | An attack where user input attempts to override the system prompt |
| **Grounding** | The degree to which an LLM’s response is based on provided data rather than invented |

---

*TOMMI Lite is part of the TOMMI project, developed by the
University of Malaga within the UNINOVIS European University
Alliance.*

---

# Exercises

TOMMI Lite — Exercises

html {
color: #2d3748;
background-color: #f7fafc;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
margin: 0 auto;
max-width: 52em;
padding: 40px 60px;
line-height: 1.7;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
font-size: 16px;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 16px;
}
h1 { font-size: 1.8em; }
}
@media print {
html { background-color: white; }
body { background-color: transparent; color: black; font-size: 11pt; }
p, h2, h3 { orphans: 3; widows: 3; }
h2, h3, h4 { page-break-after: avoid; }
}
p {
margin: 0.8em 0;
}
a {
color: #4250b3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: #5a4fcf;
}
h1 {
color: #4250b3;
border-bottom: 3px solid #4250b3;
padding-bottom: 0.3em;
margin-top: 1.5em;
}
h2 {
color: #4250b3;
border-bottom: 1px solid #e2e8f0;
padding-bottom: 0.3em;
margin-top: 2em;
}
h3 {
color: #2d3748;
margin-top: 1.5em;
}
ol, ul {
padding-left: 1.7em;
margin-top: 0.8em;
}
li {
margin-bottom: 0.3em;
}
code {
font-family: "SF Mono", Menlo, Monaco, Consolas, monospace;
font-size: 0.88em;
background-color: #e2e0f0;
padding: 0.15em 0.4em;
border-radius: 4px;
border: 1px solid #c8c4e0;
}
pre {
margin: 1em 0;
overflow: auto;
background-color: #1a202c;
color: #e2e8f0;
padding: 1em 1.2em;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
pre code {
padding: 0;
background-color: transparent;
color: inherit;
overflow: visible;
overflow-wrap: normal;
border: none;
}
hr {
border: none;
border-top: 2px solid #e2e8f0;
margin: 2em 0;
}
.back {
display: inline-block;
margin-bottom: 1em;
font-size: 0.95em;
}

[← Back to Chat](/)

# TOMMI Lite — Exercises

Practical exercises for the TOMMI Lite course. See the [Course Book](/TOMMI_Lite_Course_Book) for background material.

---

### Exercise 1: Hello World — Your First Agent (Beginner)

**Objective**: Understand the basic agent structure.

**Tasks**: 1. Start TOMMI Lite and chat with the Hello
World agent 2. Change the prompt level from Stringent to Lax and ask the
same questions. What changes? 3. Modify the identity to
make the agent respond as a pirate. Test it. You can do this in two ways: edit
`agents/hello_world/prompts.json` directly, or use the **PROMPT Assistant** agent
(type `list`, select Hello World, and ask it to "change the identity to a pirate personality"). 4. Add two new example
queries to `config.json`. You can either edit the file directly or click the ⚙ gear icon
in the top bar to open the Settings panel and modify it from there. Restart the server and verify they
appear in the interface.

**Deliverable**: Screenshot of a conversation showing
the pirate personality, and the modified `prompts.json`
file.

---

### Exercise 2: Build a Language Tutor (Oneshot)

**Objective**: Create a custom Oneshot agent from
scratch.

**Tasks**: 1. Use the Create Agent wizard to build a
Spanish language tutor 2. Choose the "Virtual Tutor" prompt template 3.
Customize the identity to focus on Spanish grammar and vocabulary 4. Add
example queries like "How do I conjugate 'ser'?" and "What's the
difference between 'por' and 'para'?" 5. Test the agent with at least 5
different questions 6. Compare responses at Lax, Tolerant, and Stringent
prompt levels

**Deliverable**: The agent's `config.json`,
`prompts.json`, and a log of 5 conversations showing how
prompt level affects responses.

---

### Exercise 3: Course FAQ Agent (RAG Vectorless)

**Objective**: Build a RAG agent that answers questions
from course materials.

**Tasks**: 1. Create a RAG Metadata Vectorless agent
using the wizard 2. Prepare a text file (`course_faq.md`)
with at least 20 Q&A pairs about a course of your choice 3. Upload
the file to the agent's data directory 4. Test the agent with questions
that ARE in the document 5. Test with questions that are NOT in the
document — does it refuse to answer or hallucinate? 6. Modify the Strict
section of the prompt to improve refusal behaviour

**Deliverable**: The FAQ document, the agent's prompt
configuration, and a comparison of grounded vs. ungrounded
responses.

---

### Exercise 4: Prompt Engineering Challenge (Oneshot)

**Objective**: Understand how prompt design affects
agent behaviour.

**Tasks**: 1. Create an agent with NO rules and NO
strict constraints (Lax mode) 2. Ask it to: "Write me an essay about
climate change" 3. Now add Rules that restrict it to only discuss
climate change in the context of agriculture 4. Ask the same question
and compare 5. Add Strict constraints that prevent it from giving
opinions — only facts 6. Ask again and compare all three responses 7.
Try to "jailbreak" the agent at each level — can you get it to ignore
its rules?

**Deliverable**: Three versions of the prompt, the
corresponding responses, and a written analysis of how each constraint
affected behaviour.

---

### Exercise 5: Multi-Model Comparison (Any Agent)

**Objective**: Compare how different LLM models handle
the same tasks.

**Tasks**: 1. Choose any agent you have created 2.
Prepare a set of 5 test questions (mix of easy, medium, and hard) 3. Use
the model selector in the top bar to test each question with: - Mistral
Small - Mistral Large - Devstral Small (if available) 4. For each
question, record: response quality, response length, response speed 5.
Create a comparison table

**Deliverable**: A comparison table with observations
about quality, speed, and cost trade-offs between models.

---

### Exercise 6: Risk Assessment (Research)

**Objective**: Identify and document risks in an AI
agent deployment.

**Tasks**: 1. Choose one of the agent types (RAG,
Text-to-SQL, or Custom) 2. Design a realistic use case for a university
or company 3. Write a risk assessment document that covers: - Data
privacy risks - Hallucination risks - Security risks (prompt injection,
data exposure) - Reliability risks - Ethical considerations 4. For each
risk, propose a mitigation strategy 5. Classify each risk as Low,
Medium, or High severity

**Deliverable**: A 2-3 page risk assessment document
following the structure above.

---

### Exercise 7: Build a Custom Agent (Advanced)

**Objective**: Create an agent that integrates an
external data source.

**Tasks**: 1. Choose an external data source (options):
- A public REST API (weather, news, Wikipedia) - A local CSV file that
the agent reads dynamically - An RSS feed 2. Create a new agent that
fetches data from this source before responding 3. The agent should: -
Connect to the data source when a query arrives - Format the retrieved
data as context - Send context + user question to the LLM - Stream the
response 4. Handle errors gracefully (source unavailable, timeout,
malformed data) 5. Write a brief technical document explaining your
agent's pipeline

**Deliverable**: The complete agent code
(`agent.py`, `config.json`,
`prompts.json`), a technical document, and screenshots of the
agent in action.

---

### Exercise 8: Agent Comparison Study (Group Project)

**Objective**: Compare agent architectures for the same
use case.

**Tasks** (team of 3-4 students): 1. Choose a single use
case (e.g., "Course material Q&A") 2. Each team member builds the
same use case using a different agent type: - Student A: Oneshot
(prompt-only, no documents) - Student B: RAG Vectorless (with course
documents) - Student C: Text-to-SQL (with a structured database of
topics) 3. Prepare a shared set of 10 test questions 4. Each student
tests all 10 questions on their agent 5. Compare results in a group
presentation: - Accuracy (did it answer correctly?) - Groundedness (was
the answer based on real data?) - Helpfulness (was the answer useful to
a student?) - Risk level (what could go wrong?)

**Deliverable**: Group presentation (10-15 slides) with
comparison results, examples, and recommendations for which agent type
works best for the use case.

---

*TOMMI Lite is part of the TOMMI project, developed by the
University of Malaga within the UNINOVIS European University
Alliance.*