A Configurable Testbed for Human–AI TeamingIEEE SMC 2026 · Bellevue, WAgithub.com/iHuman-Lab/mosaic
October 4, 2026
We study how people and intelligent systems work together.

Hemanth Manjunatha Principal Investigator

Elahe Oveisi PhD Candidate

Bennett Kwaku Dogbey PhD Student
Our work spans brain–computer interfaces, human–robot interaction, human-AI interaction, and cognitive augmentation.
When an AI teammate advises people in dynamic, high-stakes tasks, researchers ask questions like these:
Trust and reliance
When do people follow AI advice, and when is that reliance appropriate?
Decisions under pressure
How do uncertainty and time constraints affect reliance?
Situation awareness
What happens when the person and AI have access to different information?
Cognitive state
How does AI advice affect attention and workload?
AI teammate design
Which teammate behaviors and communication strategies improve team performance?
Adaptive assistance
When should assistance change with task demands or human performance?
Answering these questions requires observing the interaction as it unfolds over time.
That takes four capabilities in one experiment. Existing tools rarely offer all four together.
01
Interactive decision making
People make a sequence of decisions, and each outcome changes what happens next.
03
Configurable task conditions
Researchers need to vary information access, uncertainty, time pressure, and the consequences of mistakes.
02
A customizable AI teammate
Researchers need to vary what the AI knows, how reliable it is, and when and how it communicates.
04
Synchronized data
Task events, human actions, AI advice, physiological signals, and sensor measurements must share a common timeline.
MOSAIC is a modular testbed for human–AI teaming research. Configure its components for each study.

01
Interactive task
Search and rescue, one decision at a time

03
Configurable conditions
Map, view, timing, and scoring per study
MOSAIC
modular · configurable

02
Customizable AI teammate
Scripted or LLM, with behavior you set
04
Synchronized data
Actions, advice, and signals on one clock
MOSAIC lets researchers vary the task and AI teammate, then record the interaction.
Each part is a separate module: the participant acts on the task, the AI teammate advises from task context, and LSL aligns every stream into one session record.
Human participant
Observes, decides, and acts.
actions
observations
MOSAIC task
Runs the task and the human-facing interface.
task context
advice
AI teammate
Interprets task context and provides advice.
physiological signals
task and interaction stream
Study sensors
Physiological data: EEG, eye tracking, pupil diameter
Time-stamped stream
Lab Streaming Layer (LSL)
Aligns streams on a shared clock
Synchronized record
Session data
Ready for analysis and replay

Mission
Search a multiroom building and rescue the real victims.
Real victims and decoys look alike, so an AI teammate’s advice can help or mislead.
Part Three plays the mission.
Search and rescue provides a controlled but consequential setting for studying human–AI decisions.
At every decision, the participant can act alone or ask for advice.
next decision
1 Observe
Read the room and the mission state.
2 Decide
Act alone, or ask the AI teammate.
act alone
3 Act
The participant always chooses the final action.
4 Outcome
The environment updates and the score changes.
Optional advice path
ask
use or ignore
Request advice
MOSAIC sends task context to the AI teammate.
advice
Evaluate advice
Compare it with what the participant can see.
Recorded throughout Task state · advice request · AI response · participant action · outcome
The central question is when and how AI advice changes human decisions.
Part Two
Install MOSAIC
Check the system, install MOSAIC, and run the mission
Why Install Experience Configure

Companion notebook On the tutorial server: every setup command to copy, and the mission with nothing to install Sign in with your password, then open 02_mosaic_human_ai.ipynb jupyter.ihuman-lab.work
Check four things on your laptop before installing.
Python 3.10 or 3.11 check: python --version
Git Any recent version check: git --version
Terminal PowerShell, macOS Terminal, or a Linux shell
Display A local desktop: the game opens its own window
Installed for you by pip install -e .
Task
minigrid gymnasium numpy
Interface
pygame-ce pygame_gui
Study tools
pandas pyyaml python-dotenv
Nothing to install by hand: the next two slides set everything up.
No install, or prefer to copy and paste? The companion notebook is on the tutorial server: jupyter.ihuman-lab.work
Everything in the tutorial runs from one repository and one environment.
1 Download the code
Clones the MOSAIC repository
2 Enter the folder
Stay in mosaic for the whole tutorial
3 Create the environment
A private Python named mosaic_env
4 Activate it
Every later command runs inside it
Your prompt begins with (mosaic_env), and python --version reports 3.10 or 3.11.
Five commands, run from the mosaic folder with mosaic_env active.
The check prints a pygame-ce banner, then MOSAIC ready. If it says cannot import name 'DIRECTION_LTR', rerun lines 3 and 4.
1 Update pip
Avoids old-installer errors
2 Install MOSAIC
-e means your Part Four edits apply without reinstalling
3–4 Switch to pygame-ce
The interface needs it; plain pygame hides it
5 Check it
Imports the task and the interface
Window It opens fullscreen. F11 toggles a window (macOS: fn+F11, or set fullscreen: false in configs/experiment.yaml).
Move Arrow keys turn and walk the agent
Terminal Font warnings and connect_all failed lines are normal

You should see this: the room on the left, the panels on the right.
Confirm
The window opened
Arrow keys move the agent
The information panel updates
It stays open for Part Three
| Symptom | Recovery |
|---|---|
cannot import name 'DIRECTION_LTR' |
Rerun install lines 3 and 4 (pygame-ce) |
No module named 'mosaic' |
Activate mosaic_env, rerun pip install -e . |
No module named 'experiment' |
Run from the repo root with PYTHONPATH=src |
python --version shows 3.9 or older, or 3.12 and newer |
Recreate mosaic_env with Python 3.10 or 3.11 |
No window, or No available video device |
Run locally, not over SSH |
Everyone with a window open is ready for Part Three. Leave it open.
Part Three
Experience the SAR Mission
Play one mission and learn to read the screen
Why Install Experience Configure
Explore, tell real victims from decoys, and rescue them before time runs out.

Explore
Move room to room. A locked door needs the key of the same color.
Identify
Both are red T shapes. A real victim’s stem is centered; a decoy’s is off-center.
Decide
A real victim earns a point, a decoy costs one, and the clock keeps running.
Every choice has a consequence you can see and score.
What each tile means, and where to read the mission.

Game viewport — the green flash is rescue feedback
Information panel — rescued, remaining, steps, inventory
Mission status and score — reward and the clock
Controls, always on screen
Chat panel — where AI teammate advice arrives
![]()
You the red triangle
![]()
Victim rescue with Tab
![]()
Decoy costs a point
![]()
Lava ends the mission
![]()
Door Space opens it
![]()
Locked door needs the key of its color
![]()
Key Tab picks it up
Real victims and decoys are both red T shapes. Only real victims have health.

REAL VICTIM DECOY
![]()
100% 60% 25% 0%
In the study runner, the white bar shows a victim’s health.
Symbols A real victim’s stem sits in the middle of the bar. A decoy’s is off-center.
Health In the lab’s study runner, health drains while a victim is in view, faster near lava, and the victim dies at zero. In today’s mission it stays full.
Rescue Stand next to a victim, face it, and press Tab. The score updates at once.
+1.0 Real victim rescued
−1.0 Decoy rescued
−2.0 Victim died · study runner
Real victims earn points and decoys cost them. Telling them apart is where advice matters.
Four actions. Each clip shows what its keys do.

Navigate
↑ Move forward one tile
←→ Turn to face a new direction

Open
Space Open the door you are facing
Locked doors open only while you carry the matching key.

Pick up or rescue
Tab Take the key, or rescue the victim, you are facing

Request advice
Alt Ask the AI teammate
The reply appears in the chat panel. Today’s placeholder teammate answers “Currently, no commands are available.” Part Four gives it a real one.
Break · 15 minutes
Take a Break
Next · Part Four: Configure MOSAIC
Part Four
Configure MOSAIC
experiment/main.py in four parts: SAR, GUI, LLM, Sensing
Why Install Experience Configure

Companion notebook On the tutorial server: every change in this part, as the edit and as a cell you can run Sign in with your password, then open 02_mosaic_human_ai.ipynb jupyter.ihuman-lab.work
Four parts you can change, built on Gymnasium and MiniGrid.
↑ ← → Space Tab Alt
Human participant
Watches the screen and presses keys.
keys
frames

4.2 GUI mosaic.gui
Game view, panels, chat, and feedback.
action
observation

4.1 SAR mosaic.sar
Rooms, victims, rules, and rewards.
physiological signals
context · advice
built on
4.4 Sensing experiment/
Gaze and EEG on the game’s clock, through LSL.

4.3 LLM mosaic.llm
Reads the task, replies in the chat.
obs, reward, terminated, truncated, info = env.step(action)
Gymnasium + MiniGrid
The step API and the grid world.
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
src/experiment/main.py · lines 31–51
env = build_sar_env(
screen_size=800,
num_rows=3,
num_cols=3,
room_size=10,
victim_placer=LavaRiskVictimPlacer(
num_real_victims=game_config.get("num_real_victims", 6),
num_fake_victims=game_config.get("num_fake_victims", 12),
),
lava_placer=SectorSpreadLavaPlacer(
lava_per_room=game_config.get("lava_per_room", 8),
),
locked_room_placer=LockedRoomPlacer(locked_room_prob=0.5),
camera_strategy=AgentFOVCamera(),
)
env.reset()
llm_client = build_llm_client(
provider=config.get("provider", "dummy"), model=config.get("model")
)
gui = SAREnvGUI(env, config=config, llm_client=llm_client)
gui.run()4.1 SAR
The building, what fills it, the camera
4.2 GUI
The participant’s window
4.3 LLM
Who answers Alt
4.4 Sensing
What every step records
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Lines 31–44 build the task. Notebook: notebooks/02_mosaic_human_ai.ipynb
src/experiment/main.py lines 31–44
env = build_sar_env(
screen_size=800,
num_rows=3,
num_cols=3,
room_size=10,
victim_placer=LavaRiskVictimPlacer(
num_real_victims=game_config.get("num_real_victims", 6),
num_fake_victims=game_config.get("num_fake_victims", 12),
),
lava_placer=SectorSpreadLavaPlacer(
lava_per_room=game_config.get("lava_per_room", 8),
),
locked_room_placer=LockedRoomPlacer(locked_room_prob=0.5),
camera_strategy=AgentFOVCamera(),Three things to change
1 The building Notebook
YAML counts · num_rows · locked_room_prob
How big, crowded, and locked
2 Camera Next
camera_strategy=
What the participant sees
3 Rewards Try it
action=RescueAction(...)
What a mistake costs
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Line 44 sets the camera. One walk through a door, three cameras:

Edge-following
EdgeFollowCamera · scrolls with the agent

Whole room
AgentFOVCamera · the default

Forward cone
AgentConeCamera · only what is ahead
Agent same tile in all three · Room the agent’s room
Same task. The camera sets what the participant can see.
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Try it Make rescuing a decoy cost 5 points instead of 1.
src/experiment/main.py an import, then inside build_sar_env
Run Relaunch and rescue a decoy.
What will the reward read?

Before · the default

After · fake_victim=-5.0
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Lines 50–51 open the participant’s window.
src/experiment/main.py lines 50–51

Three things to change
1 Feedback flash Demo · next
vignette=EdgeVignette(...)
How a mistake feels
2 Info panel Appendix
info_panel=
What progress is shown
3 Time limit Appendix
max_time: (YAML)
How much time pressure
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Presenter demo Make the red flash after a decoy stronger and longer.
src/experiment/main.py an import, then the gui = line
+from mosaic.gui.feedback import EdgeVignette, VignetteStyle
@@ further down @@
- gui = SAREnvGUI(env, config=config, llm_client=llm_client)
+ gui = SAREnvGUI(env, config=config, llm_client=llm_client,
+ vignette=EdgeVignette(800, styles={"wrong_victim":
+ VignetteStyle((200, 0, 0), 200, 1.5, "fade")}))Run Relaunch and rescue a decoy.
How will the mistake feel different?

Before · default, 0.6 s

After · stronger, 1.5 s
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Lines 47–49 pick the AI teammate. Today it is the dummy placeholder.
src/experiment/main.py lines 47–49

Today, after Alt
Three things to change
1 Keyless teammate Try it · next
llm_client=ReliableTeammate(0.7)
How reliable the advice is
2 Real LLM On your own
provider: in the YAML, key in .env
Who answers Alt
3 Prompt Appendix
prompt_builder=
What the teammate is told
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Try it Swap in a teammate that reads the map and is right 7 times in 10.
Get advisor.py into src/experiment/, from
github.com/Bkdogbey/mosaic-smc-tutorial · presentation/labs/
src/experiment/main.py imports, then the gui = line
Run Relaunch and press Alt.
Is the advice always right?

Before · the dummy placeholder

After · ReliableTeammate, grounded in the map
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
On your own With your own key: two packages, one key, two lines of YAML.
Run Relaunch and press Alt.
How it answers
1 Prompt The game state, as rules and a table
2 Model One reply, a few seconds later
3 Chat The participant decides whether to follow it
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Each step produces an observation. The study runner streams it with sensors on one clock.
obs → agent_x, agent_y, direction, grid,
saved_victims, remaining_victims,
victim_health, step_count, …
+ action, reward, llm_response
→ study runner: one JSON line per frame on LSL
Three things to change
1 Recorded fields Notebook
print(sorted(obs))
What each step holds
2 Custom fields
observation= in build_sar_env
Add or drop fields
3 Sensors Demo · next
register_sensor(...)
Gaze or EEG on the game’s clock
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
Presenter demo A Tobii eye tracker on the lab’s study runner, while a volunteer plays.
src/experiment/eye_demo.py the study runner
What lands next to the game data?
Watch for
1 Calibration Five dots
2 Play A short mission
3 Two streams, one clock TobiiEyeTracker (gaze, 60 Hz) and SARGame (game state, every frame), side by side in LabRecorder
Map 4.1 SAR 4.2 GUI 4.3 LLM 4.4 Sensing
One recorded mission gaze and game on the same clock

What to look for
Where Which part of the screen holds the gaze?
When What do the eyes do in the second after a rescue?
Advice Where does gaze go when the teammate replies?
Gaze and game share one clock, so every look lines up with what happened.
The parts you changed today, and where they live.
src/experiment/ One study built on the package. Copy this folder to start yours.
main.py
placers.py
llm.py
pacing.py
game.py
replay.py
sensors/
API build_llm_client · LavaRiskVictimPlacer · SARGameTrial
composes
src/mosaic/core/ 4.1
Level generation and cameras
level.py
placers.py
camera.py
API Placer · CameraStrategy
src/mosaic/sar/ 4.1 4.4
The search-and-rescue task
env.py
placers.py
actions.py
objects.py
observations.py
API build_sar_env · RescueAction
src/mosaic/gui/ 4.2
What the participant sees
main.py
user.py
chat.py
info.py
feedback.py
API SAREnvGUI · EdgeVignette
src/mosaic/llm/ 4.3
The teammate contract
client.py
process_prompts.py
prompts.yaml
pathfinding.py
parser.py
API LLMClient · ask
What you configured today, put to work in a study of people and an LLM teammate.
LLM-Mediated Human-AI Interaction in Search and Rescue: Impact of Expertise on Attentional Allocation Elahe Oveisi · Hemanth Manjunatha
Task The search-and-rescue mission, with victims whose health runs down.
Teammate Two LLM teammates and a no-LLM baseline, three trials per participant.
Sensing A Tobii eye tracker and the game on one clock, through LSL.
Question Does guidance change where people look, and does expertise matter?

Monday, October 5 · 14:00–14:15 Grand C · Session MoA10 Scan for the talk’s slides
Come and hear what they found: Monday at 14:00, Grand C.
Thanks!
Questions?
MOSAIC github.com/iHuman-Lab/mosaic
Appendix
More changes and reference
Each change starts from the stock files
Set the chance that a room is locked: 0.5 locks about half, 0.9 most.
Give the mission 2 minutes instead of 5.
Hide how many victims remain.
Get panel.py into src/experiment/, from
github.com/Bkdogbey/mosaic-smc-tutorial · presentation/labs/
src/experiment/main.py an import, then the gui = line
Run Relaunch and look at the mission box.
What does the participant no longer know?

Before · rescued and remaining

After · no remaining count
Before trusting its advice, look at what it is told.
Every Alt sends
1 Rules Rescue real survivors, nearest first, never through lava
2 Every real victim Even ones out of your view
3 No decoys Left out, so it never points at one
Change it SAREnvGUI(..., prompt_builder=...)
The start of one prompt
Agent: room (0,1) facing West | …
Object Direction Visible PathLength
Victim4 East Yes 9
Victim2 South Yes 0
RedKey1 East Yes 5
PurpleKey1 East Yes 6
PurpleDoor1 South Yes 34
RedDoor1 East No 10

MOSAIC Tutorial · iHuman Lab · Oklahoma State University