Overview
Agent LoL’s AI Coaching feature uses OpenAI’s GPT-4 to analyze your early game performance and provide personalized coaching recommendations. The system compares your progression against your lane opponent, analyzing farm, gold, experience, and events to identify areas for improvement.
AI coaching requires an OpenAI API key and must be enabled with ENABLE_MATCH_AGENT=true in your environment variables.
How It Works
The AI coaching system uses a specialized endpoint that fetches match and timeline data, identifies lane matchups, and sends progression data to OpenAI for analysis.
Match Timeline Retrieval
The system fetches both match data and timeline data from the Riot API simultaneously. // src/app/api/riot/match/timeline/compare/route.js:33-42
const [ matchRes , timelineRes ] = await Promise . all ([
fetch ( RIOT_MATCH_URL ( matchId ), {
headers: { 'X-Riot-Token' : session . apiKey },
cache: 'no-store' ,
}),
fetch ( RIOT_TIMELINE_URL ( matchId ), {
headers: { 'X-Riot-Token' : session . apiKey },
cache: 'no-store' ,
}),
]);
Lane Opponent Identification
The system identifies your opponent in the same role/position. // src/app/api/riot/match/timeline/compare/route.js:78-82
const enemySameRole = participants . find (
( p ) =>
( p . teamPosition || p . individualPosition ) === userRole &&
Number ( p . teamId ) !== Number ( userTeamId )
);
Progression Data Collection
Minute-by-minute data is collected from game start to the configured comparison time. // src/app/api/riot/match/timeline/compare/route.js:94-101
const userFramesFromStart = [];
const enemyFramesFromStart = [];
for ( let i = 0 ; i <= frameIndex && i < frames . length ; i ++ ) {
const pf = frames [ i ]?. participantFrames ?? {};
userFramesFromStart . push ({ minute: i , ... ( pf [ userParticipantId ] ?? {}) });
enemyFramesFromStart . push ({ minute: i , ... ( pf [ enemyParticipantId ] ?? {}) });
}
GPT-4 Analysis
The progression data is sent to OpenAI’s GPT-4 model for analysis and coaching recommendations.
Timeline Comparison Configuration
The comparison window is configured using the TIMELINE_COMPARE environment variable:
// src/app/api/riot/match/timeline/compare/route.js:52-57
const compareMs = Math . max ( 0 , parseInt ( process . env . TIMELINE_COMPARE , 10 ) || 0 );
const frameIndex = Math . min (
Math . floor ( compareMs / 60000 ),
Math . max ( 0 , frames . length - 1 )
);
const frameMinute = frameIndex ;
Set TIMELINE_COMPARE in milliseconds. Common values:
300000 = 5 minutes (early laning phase)
600000 = 10 minutes (extended laning phase)
900000 = 15 minutes (pre-teamfight phase)
AI Prompt Engineering
The system uses a carefully crafted prompt to ensure relevant and actionable coaching:
// src/app/api/riot/match/timeline/compare/route.js:119-137
messages : [
{
role: 'system' ,
content: `Eres un coach de League of Legends. Recibes la evolución minuto a minuto (desde el minuto 0 hasta el minuto ${ frameMinute } ) de dos jugadores en la misma posición/rol.
Analiza cómo fue la early game de cada uno: farm (minions), oro, nivel/XP a lo largo del tiempo. Responde en español, en 4-6 frases: quién se fue adelantando y en qué momento, tendencias (quién mejoró o empeoró), y una conclusión breve con qué podría mejorar el que va atrás. Sé directo y útil.` ,
},
{
role: 'user' ,
content: `Rol/lane: ${ userRole } .
Mi jugador ( ${ userChampion } ) - evolución desde min 0 hasta min ${ frameMinute } :
${ JSON . stringify ( userFramesFromStart ) }
Rival en la misma lane ( ${ enemyChampion } ) - evolución desde min 0 hasta min ${ frameMinute } :
${ JSON . stringify ( enemyFramesFromStart ) }
Dame feedback de la early game: cómo fue desde el inicio hasta el minuto ${ frameMinute } .` ,
},
],
Prompt Breakdown
The AI coaching prompt is designed to:
Set the role : “You are a League of Legends coach”
Define the input : Minute-by-minute progression data for both players
Specify analysis focus : Farm, gold, level/XP over time
Request format : 4-6 sentences in Spanish
Required insights :
Who got ahead and when
Performance trends over time
Specific improvement suggestions for the player who fell behind
Model Configuration
The OpenAI API call uses specific parameters for optimal coaching quality:
// src/app/api/riot/match/timeline/compare/route.js:116-118
body : JSON . stringify ({
model: 'gpt-4o-mini' ,
temperature: 0.4 ,
messages: [ ... ]
}),
Model Parameters
Model : gpt-4o-mini - Fast, cost-effective GPT-4 variant
Temperature : 0.4 - Low temperature for consistent, focused analysis
Lower temperatures reduce creativity but increase reliability
API Response Handling
The coaching response is extracted and returned to the client:
// src/app/api/riot/match/timeline/compare/route.js:141-146
const openaiJson = await openaiRes . json ();
if ( openaiRes . ok ) {
comparison = openaiJson ?. choices ?.[ 0 ]?. message ?. content ?. trim () ?? null ;
} else {
console . error ( 'OpenAI timeline compare error:' , openaiJson );
}
Client-Side Integration
The coaching data is fetched on the client using React Query:
// src/components/LatestMatch.js:39-48
const timelineCompareQuery = useQuery ({
queryKey: queryKeys . matchTimelineCompare ( firstMatchId , userGameName , userTagLine ),
queryFn : () =>
fetchTimelineCompare ( firstMatchId , {
gameName: userGameName ,
tagLine: userTagLine ,
}),
staleTime: 300000 ,
enabled: !! firstMatchId && !! userGameName ,
});
Service Function
// src/services/match.js:53-67
export async function fetchTimelineCompare ( matchId , options = {}) {
const params = new URLSearchParams ({ matchId });
if ( options . gameName ) params . set ( 'gameName' , options . gameName );
if ( options . tagLine ) params . set ( 'tagLine' , options . tagLine );
const response = await fetch ( `/api/riot/match/timeline/compare? ${ params } ` );
const data = await response . json ();
if ( ! response . ok ) throw data ;
return data ;
}
Display in UI
Coaching recommendations are displayed below the timeline analysis:
// src/components/LatestMatch.js:143-163
{ timelineCompare && (
< div className = "mt-6 rounded-xl bg-slate-800/50 border border-slate-700/50 overflow-hidden shadow-lg" >
< div className = "px-5 py-4 sm:px-6 border-b border-slate-700/50" >
< h3 className = "text-sm font-semibold text-slate-200 mb-1" >
Match Reviewer
</ h3 >
< p className = "text-xs text-slate-500" >
{ timelineCompare . userChampion } ( { timelineCompare . role } ) vs { timelineCompare . enemyChampion }
</ p >
</ div >
< div className = "px-5 py-4 sm:px-6" >
< TimelineReviewer
timelineData = { timelineData }
participants = { participants }
userGameName = { userGameName }
userTagLine = { userTagLine }
timelineCompare = { timelineCompare }
/>
</ div >
</ div >
)}
Recommendations Section
// src/components/TimelineReviewer.js:111-116
< div className = "pt-2 border-t border-slate-700/50" >
< p className = "font-medium text-slate-300 mb-1" > Recomendations: </ p >
< p className = "text-slate-400 leading-relaxed whitespace-pre-line" >
{ comparison ?? '…' }
</ p >
</ div >
Response Structure
The API returns a structured response with all relevant coaching data:
// src/app/api/riot/match/timeline/compare/route.js:152-160
return NextResponse . json ({
role: userRole ,
frameMinute ,
userChampion ,
enemyChampion ,
userFrame ,
enemyFrame ,
comparison ,
});
Response Fields
role - Lane position (TOP, JUNGLE, MIDDLE, BOTTOM, UTILITY)
frameMinute - The frame/minute analyzed
userChampion - Your champion name
enemyChampion - Opponent’s champion name
userFrame - Your stats at the comparison frame
enemyFrame - Opponent’s stats at the comparison frame
comparison - GPT-4 coaching analysis (string)
Environment Variables
# Required for AI coaching
OPENAI_KEY = sk-proj-...
ENABLE_MATCH_AGENT = true
# Timeline comparison window (milliseconds)
TIMELINE_COMPARE = 600000
If ENABLE_MATCH_AGENT is not set to true, AI coaching will be disabled even if OPENAI_KEY is present.
Error Handling
The system gracefully handles OpenAI API errors:
// src/app/api/riot/match/timeline/compare/route.js:147-149
catch ( err ) {
console . error ( 'Error calling OpenAI for timeline compare:' , err );
}
If the OpenAI call fails, the response still includes match and timeline data, just without the AI-generated coaching text.
Best Practices
Set appropriate comparison windows
Early game (5-10 minutes) provides the most actionable coaching for laning phase.
Monitor API costs
Each coaching request uses GPT-4 tokens. Consider caching or rate limiting for production.
Handle API failures gracefully
Always provide useful data even if AI coaching is unavailable.
Next Steps
Stats Analysis Understand the raw data behind AI coaching
Replay Viewer Visualize the match in 2.5D