Agents API Reference
Module location
All agents live in src/agents/. Each file is extracted from its corresponding notebook (N25–N31).
Entry points
Every agent has two entry points:
| Agent |
FastF1 Entry |
RSM Adapter (no FastF1 session) |
| N25 Pace |
run_pace_agent(**kwargs) |
run_pace_agent_from_state(lap_state, laps_df) |
| N26 Tire |
run_tire_agent(stint_state) |
run_tire_agent_from_state(lap_state, laps_df) |
| N27 Situation |
run_race_situation_agent(lap_state) |
run_race_situation_agent_from_state(lap_state, laps_df) |
| N28 Pit |
run_pit_strategy_agent(lap_state) |
run_pit_strategy_agent_from_state(lap_state, laps_df) |
| N29 Radio |
run_radio_agent(lap_state) |
run_radio_agent_from_state(lap_state, laps_df) |
| N30 RAG |
run_rag_agent(question) |
run_rag_agent_from_state(lap_state) |
| N31 Orchestrator |
run_strategy_orchestrator(race_state, lap_state) |
run_strategy_orchestrator_from_state(race_state, laps_df) |
Each agent also exposes a get_*_react_agent() factory that returns a compiled LangGraph CompiledGraph for direct LangGraph usage.
Output dataclasses
PaceOutput (N25)
| Field |
Type |
Description |
lap_time_pred |
float |
Predicted lap time in seconds |
delta_vs_prev |
float |
Delta vs previous lap (negative = faster) |
delta_vs_median |
float |
Delta vs session median |
ci_p10 |
float |
10th percentile bootstrap CI |
ci_p90 |
float |
90th percentile bootstrap CI |
reasoning |
str |
LLM-generated reasoning text |
TireOutput (N26)
| Field |
Type |
Description |
compound |
str |
Current compound name (SOFT, MEDIUM, HARD) |
current_tyre_life |
int |
Current tire age in laps |
deg_rate |
float |
Degradation rate (seconds lost per lap) |
laps_to_cliff_p10 |
float |
10th percentile laps until cliff |
laps_to_cliff_p50 |
float |
50th percentile laps until cliff |
laps_to_cliff_p90 |
float |
90th percentile laps until cliff |
warning_level |
str |
OK, MONITOR, PIT_SOON, or CRITICAL |
reasoning |
str |
LLM-generated reasoning text |
RaceSituationOutput (N27)
| Field |
Type |
Description |
overtake_prob |
float |
Probability of being overtaken (0–1) |
sc_prob_3lap |
float |
Safety car probability within 3 laps (0–1) |
threat_level |
str |
LOW, MEDIUM, HIGH, CRITICAL |
gap_ahead_s |
float |
Gap to car ahead in seconds |
pace_delta_s |
float |
Pace difference vs car ahead |
reasoning |
str |
LLM-generated reasoning text |
PitStrategyOutput (N28)
| Field |
Type |
Description |
action |
str |
STAY_OUT, PIT_NOW, UNDERCUT, OVERCUT |
recommended_lap |
int or None |
Suggested pit lap |
compound_recommendation |
str |
Suggested next compound |
stop_duration_p05 |
float |
5th percentile stop duration (s) |
stop_duration_p50 |
float |
Median stop duration (s) |
stop_duration_p95 |
float |
95th percentile stop duration (s) |
undercut_prob |
float or None |
Undercut success probability (0–1) |
undercut_target |
str or None |
Target driver for undercut |
sc_reactive |
bool |
Whether recommendation is SC-reactive |
reasoning |
str |
LLM-generated reasoning text |
RadioOutput (N29)
| Field |
Type |
Description |
radio_events |
list |
Processed radio messages with sentiment, intent, NER |
rcm_events |
list |
Processed Race Control Messages |
alerts |
list |
Deterministic alert flags from NLP pipeline |
reasoning |
str |
LLM-generated reasoning text |
corrections |
list |
Driver-reported corrections (damage, handling issues) |
RegulationContext (N30)
| Field |
Type |
Description |
answer |
str |
Synthesized answer from regulation passages |
articles |
list[str] |
Referenced FIA article numbers |
chunks |
list |
Raw retrieved text chunks |
reasoning |
str |
Alias for answer |
StrategyRecommendation (N31)
| Field |
Type |
Description |
action |
str |
STAY_OUT, PIT_NOW, UNDERCUT, OVERCUT, ALERT |
pace_mode |
str |
PUSH, NEUTRAL, MANAGE, LIFT_AND_COAST |
risk_posture |
str |
AGGRESSIVE, BALANCED, DEFENSIVE |
reasoning |
str |
Multi-sentence LLM synthesis |
confidence |
float |
0–1 confidence score |
scenario_scores |
dict |
MC scores per strategy candidate |
contingencies |
list[Contingency] |
Conditional plan branches |
regulation_context |
str |
RAG answer if N30 was activated |
RaceState input (N31)
The orchestrator accepts a RaceState Pydantic model:
class RaceState(BaseModel):
driver: str # Three-letter driver code
lap: int # Current lap number
total_laps: int # Total race laps
position: int # Current race position
compound: str # Current tire compound
tyre_life: int # Current tire age (laps)
gap_ahead_s: float # Gap to car ahead (seconds)
pace_delta_s: float # Pace delta vs car ahead
air_temp: float # Air temperature (C)
track_temp: float # Track temperature (C)
rainfall: bool = False
radio_msgs: list = [] # RadioMessage dicts for current lap window
rcm_events: list = [] # RCMEvent dicts for current lap window
risk_tolerance: float = 0.5 # 0=conservative, 1=aggressive
Model artifacts
| Agent |
Model directory |
Files |
| N25 |
data/models/lap_time/ |
XGBoost model |
| N26 |
data/models/tire_degradation/ |
TireDegTCN .pt files + calibration JSON |
| N27 |
data/models/overtake_probability/ |
LightGBM + calibrator + config |
| N27 |
data/models/safety_car_probability/ |
LightGBM + calibrator + feature list |
| N28 |
data/models/pit_prediction/ |
HistGBT P05/P50/P95 + undercut LightGBM |
| N29 |
data/models/nlp/ |
pipeline_config_v1.json + .pt state dicts |
| N30 |
data/rag/ |
Qdrant index (built by scripts/build_rag_index.py) |
Testing examples
Tool-level (no LLM needed):
from src.agents.radio_agent import process_radio_tool
result = process_radio_tool.invoke({
"driver": "NOR", "lap": 18, "text": "Box this lap."
})
Agent-level (no LLM needed):
from src.agents.pace_agent import run_pace_agent_from_state
import pandas as pd
laps_df = pd.read_parquet("data/processed/laps_featured_2025.parquet")
lap_state = {"driver": "VER", "lap_number": 20}
output = run_pace_agent_from_state(lap_state, laps_df)
Full orchestrator (requires LM Studio or OpenAI):
from src.agents.strategy_orchestrator import RaceState, run_strategy_orchestrator_from_state
import pandas as pd
laps_df = pd.read_parquet("data/processed/laps_featured_2025.parquet")
race_state = RaceState(
driver="NOR", lap=18, total_laps=57, position=3,
compound="C2", tyre_life=20, gap_ahead_s=1.2, pace_delta_s=-0.3,
air_temp=32.0, track_temp=48.0,
)
rec = run_strategy_orchestrator_from_state(race_state, laps_df)
print(rec.action, rec.confidence, rec.reasoning)