Skip to main content

Agents

Irregular • File: AgentsData.csv • Writer: LaboAgentDataWriter.cs • Requires USING_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 StepRequest events from the agent's RequestDecision() / RequestAction() calls.
  • At episode transitions (start, end, reward events).

File & location

  • Default: AgentsData.csv in the run directory.
  • Writer: LaboAgentDataWriter.cs.
  • Observation: Runtime/DataCapture/Observations/AgentObservation.cs.
  • Gated by USING_AGENTS scripting define.

Configuration

AgentsDataCapture SO (subclass of DataCaptureConfig). Fields:

FieldWhat it does
enabledLoggingMaster enable/disable.
fileNameOverride the default name.
flushEveryNRowsBatched flush cadence. Default 30.
writeHeaderWrite 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:

ColumnTypeDescription
AgentstringAgent identifier (name or id).
TeamIDintTeam this agent belongs to (for multi-agent / adversarial setups).
Episode_NumberintCurrent episode index for this agent.
Step_NumberintCurrent step within the episode.
Request_EventstringWhat triggered this row — StepRequest, EpisodeStart, EpisodeEnd, etc.
StatestringObservation state at this step (serialised).
Actions_OneHotstringOne-hot action vector as a list.
Actions_ContinuousstringContinuous action vector as a list.
Reward_StepfloatReward received on this step.
Reward_EpisodefloatCumulative reward for the episode so far.
Next_StatestringObservation state after this step's action was applied.
OneHot_ActionsintNumber of one-hot action branches.
OneHot_BranchSizesstringBranch sizes for one-hot actions (e.g. [3] for a single branch with 3 options).
Continuous_ActionsintNumber of continuous action dimensions.
Observations_VariablesstringVariable-space observations (serialised).
Observations_PixelstringPixel-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_AGENTS gate. If the scripting define isn't active when the LABO package is compiled, AgentsData.csv won'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_Episode is cumulative. Reward_Step is the per-step delta. Reward_Episode resets at EpisodeStart. Don't sum Reward_Step over episodes without grouping by (Agent, Episode_Number).
  • Multi-agent: watch TeamID and Agent. Rows from different agents and teams interleave in the file. Always filter by Agent + TeamID before per-agent analyses.
  • Observations_Pixel is 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 EventsMonotonicExecutionTime is accurate to the step-request moment, not the write moment.

Analysis recipes