Agents
Irregular • File:
AgentsData.csv• Writer:LaboAgentDataWriter.cs• RequiresUSING_AGENTS
At a glance
Agents captures per-step state for ML-agent-driven experiences — one row per agent step / request event. Each row includes the agent's observation state, its chosen action (both continuous and one-hot), step reward, cumulative episode reward, the next observed state, and observation metadata. Stamped at trigger time by LaboObservation.Stamp().
Only built when the USING_AGENTS scripting define is active. Non-agent experiences won't have this file.
When it writes
Whenever the agent pipeline calls LaboDataCapture.Instance.AgentEntry(observation). This is typically:
- Per agent step / decision cycle.
- On
StepRequestevents from the agent'sRequestDecision()/RequestAction()calls. - At episode transitions (start, end, reward events).
File & location
- Default:
AgentsData.csvin the run directory. - Writer:
LaboAgentDataWriter.cs. - Observation:
Runtime/DataCapture/Observations/AgentObservation.cs. - Gated by
USING_AGENTSscripting define.
Configuration
AgentsDataCapture SO (subclass of DataCaptureConfig). Fields:
| Field | What it does |
|---|---|
enabledLogging | Master enable/disable. |
fileName | Override the default name. |
flushEveryNRows | Batched flush cadence. Default 30. |
writeHeader | Write the header row on first emission. Default true. |
Per-agent configuration (observation space, action space, reward shaping) lives on the experience's Agent components — this SO only controls how the writer emits rows. The writer fires whenever any agent calls LaboDataCapture.Instance.AgentEntry.
Not auto-created on experience open — assign manually if missing.
Columns
Shared prefix
See Column conventions — The shared prefix.
Domain columns
Sixteen columns covering state, actions, reward, and observations:
| Column | Type | Description |
|---|---|---|
Agent | string | Agent identifier (name or id). |
TeamID | int | Team this agent belongs to (for multi-agent / adversarial setups). |
Episode_Number | int | Current episode index for this agent. |
Step_Number | int | Current step within the episode. |
Request_Event | string | What triggered this row — StepRequest, EpisodeStart, EpisodeEnd, etc. |
State | string | Observation state at this step (serialised). |
Actions_OneHot | string | One-hot action vector as a list. |
Actions_Continuous | string | Continuous action vector as a list. |
Reward_Step | float | Reward received on this step. |
Reward_Episode | float | Cumulative reward for the episode so far. |
Next_State | string | Observation state after this step's action was applied. |
OneHot_Actions | int | Number of one-hot action branches. |
OneHot_BranchSizes | string | Branch sizes for one-hot actions (e.g. [3] for a single branch with 3 options). |
Continuous_Actions | int | Number of continuous action dimensions. |
Observations_Variables | string | Variable-space observations (serialised). |
Observations_Pixel | string | Pixel-space observations (serialised — usually a shape descriptor, not raw pixels). |
Serialised fields use semicolon separation internally where lists are embedded in a single cell.
Sample rows
...shared...,Agent,TeamID,Episode_Number,Step_Number,Request_Event,State,Actions_OneHot,Actions_Continuous,Reward_Step,Reward_Episode,Next_State,OneHot_Actions,OneHot_BranchSizes,Continuous_Actions,Observations_Variables,Observations_Pixel
...,AgentA,0,1,42,StepRequest,[obs],[0;1;0],[0.12;-0.3],1.0,15.0,[nextObs],3,[3],2,[3],[...]
...,AgentA,0,1,43,StepRequest,[obs],[1;0;0],[0.08;-0.1],0.0,15.0,[nextObs],3,[3],2,[3],[...]
Join with other streams
Standard FrameNumber join for per-frame context:
import pandas as pd
exp = pd.read_csv("ExperienceState.csv")
agents = pd.read_csv("AgentsData.csv")
enriched = agents.merge(exp, on="FrameNumber", how="left", suffixes=("_agent", "_frame"))
# All reward events for AgentA in Episode 1:
enriched[(enriched["Agent"] == "AgentA")
& (enriched["Episode_Number"] == 1)
& (enriched["Reward_Step"] != 0.0)]
Gotchas
USING_AGENTSgate. If the scripting define isn't active when the LABO package is compiled,AgentsData.csvwon't exist — and no agent data will be captured, regardless of runtime state.- State / Next_State are serialised strings. They can be large. Parse with care; the encoding depends on how the agent's observation is serialised (typically a JSON-ish list representation).
Reward_Episodeis cumulative.Reward_Stepis the per-step delta.Reward_Episoderesets atEpisodeStart. Don't sumReward_Stepover episodes without grouping by(Agent, Episode_Number).- Multi-agent: watch
TeamIDandAgent. Rows from different agents and teams interleave in the file. Always filter byAgent+TeamIDbefore per-agent analyses. Observations_Pixelis usually a descriptor, not raw pixels. Embedding raw camera frames in CSV would blow up file size; LABO stores a shape / hash-ish descriptor. Cross-reference with any external pixel-logging you set up.- Stamped at trigger time. Same as Events —
MonotonicExecutionTimeis accurate to the step-request moment, not the write moment.
Analysis recipes
- Stimulus-locked averaging — epoch-align agent reward or action traces around stimulus onsets from Events.
- Cross-device sync — if agent training data is logged to an external system,
MonotonicExecutionTimeis the reference clock.