Skip to content
All posts

Agents ·

Teaching an agent to take its time

A strong move played instantly gives a bot away. What 5.5 million rated games taught us about when people think, and how an Ocheso agent decides how long to wait.

Play a chess engine set to a low level and something feels off long before you notice the moves. It answers at the same speed every time: a quiet developing move, a desperate defence, a recapture anyone would see. People don't play like that. They rattle off the opening, slow down when the position gets complicated, take a recapture without thinking, and speed up as the clock runs down.

Ocheso Agents are opponents that platforms put in front of their players: in an empty lobby at a quiet hour, as a practice partner at the right level, in a seat someone has waited too long to fill. The first thing we wanted them to get right was the waiting.

Where the numbers come from

We took the Lichess open database, which Lichess publishes for anyone to use, and read the rated games from September 2026 that carried clock times: 5.5 million of them. For every move we noted how long the player spent, grouped by their rating, the time control, the move number and how much time they had left.

  • 800
  • 1200
  • 1600
  • 2000

Show the numbers
5+0: median seconds per move, by move number and rating
Move800120016002000
21.581.120.970.97
31.951.210.920.86
42.541.631.170.98
5–83.562.421.801.54
9–164.773.883.433.30
17–254.564.364.314.46
26–402.883.133.373.61
41+1.241.451.581.73
Median seconds per move, by move number and rating. Rated Lichess games with clocks, September 2026.

What people actually do

Three patterns stand out.

Openings are quick, and quicker for stronger players. In five-minute games, a player rated around 800 spends a median 1.6 seconds on their second move. A player around 2000 spends 1.0. They know the opening, so they don't need to think.

The middle of the game is where the time goes, at every level. Between moves 17 and 25 of a five-minute game, the medians for players rated 800, 1200 and 2000 are 4.6, 4.4 and 4.5 seconds: almost the same. Strength changes how well people use that time, not how much of it they take.

Given more time, stronger players use more of it. In 15+10 games the same stretch takes an 800-rated player about 10.5 seconds a move, and a 2000-rated player about 15.3.

The position matters as much as the move number. A recapture took about 40% of a player's usual time for that point in the game; an only move about 57%; getting out of check about 74%. And the clock bends it: with between a tenth and a half of their time left, people spent about 20% longer per move than with more than half, and with under ten seconds left they moved in about half their usual time.

How an agent uses it

For every move, an agent starts from the median for its rating, the time control and the moment in the game. It bends that for the position and the clock, then draws its actual think time at random around it, with the spread people show. Most moves come quickly and a few take a long time, so a given agent sometimes plays fast and sometimes sits on a move, without a rhythm you could learn.

Each agent also has a clock profile: even, fast start, slow start, or time trouble, for the player who thinks for ages early and plays the last ten moves on the increment.

Two hard limits keep it inside the rules people play by. Its first move comes within 12 seconds, well inside the 30-second abort many platforms use. And it doesn't lose on time unless its persona is the kind that runs the clock close.

And the moves themselves

Waiting like a person only helps if the move that follows is one a person would play. Agents choose moves with Stockfish 19, which ships inside our API and is pinned by its checksum, and, for ratings 1100 to 1900, with Maia: open neural networks from the CSSLab research group, trained to predict the moves people at a given rating actually play. The persona's character (how attacking, how careful, how attached to material) shapes the final choice.

We fitted how an agent weighs all of this on 2,003 real positions, each with the move the person played, their rating and their clock. Half the positions were used for the fit and the other half held back to check it. On the held-back half, the agent's most likely move was the one the person actually played 48.4% of the time.

48.4% can sound low, but it isn't a mark out of 100. People of the same rating disagree with each other all the time. The aim is to be indistinguishable from the crowd at a rating, not to predict one person.

What isn't right yet

From about 1600 up, our agents blunder too rarely. People rated 2000 and above make a serious mistake (a move that costs at least 20 points of winning percentage) in roughly 5 to 6% of moves, mostly in time scrambles. Our agents do it in under 1%. Turning up a mistake dial doesn't fix that, because a mistake only costs something when the bad move looks attractive. It needs a model of time pressure, and we haven't built it yet. When we do, it'll be in the changelog.

Manners, and a week of its own

People say good luck, nice move, oops and good game. Agents have seven things they can say: good luck, have fun, nice move, well played, good game, thanks and oops. The agent decides when; your platform decides the words, so an agent never writes free text into your chat. Agents also decide whether to offer or accept a draw, when to resign, and whether to play a rematch.

Each agent keeps a weekly routine too, with sessions of different lengths on the days and hours its persona plays, so the same opponent isn't online at every hour of every day, the way no person is.

How a move reaches your game

Your server asks for a move with a key. In sync mode you send the game so far and get back the move, with think_ms, how long a person would take, and play_at, the moment to show it. Look at a reply and you'll see the time split in two: compute_ms, the engines' own work, and wait_ms, the rest of the pause. Most of the thinking is the wait, on purpose.

SampleA dashed border means sample or replayed data, computed by Ocheso's own code; the line underneath says how it was made. Real, live data sits in a solid frame.
curl https://api.ocheso.com/v1/connect/sessions/$SESSION/move \  -H "Authorization: Bearer $OCHESO_AGENT_KEY" \  -H "Content-Type: application/json" \  -d '{"moves":["e2e4"],"clock_ms":294000,"wait":true}'
200 OK
{  "session": "5b0c…e21",  "ply": 1,  "move": "c7c5",  "san": "c5",  "resign": false,  "offer_draw": false,  "think_ms": 635,  "wait_ms": 551,  "compute_ms": 84,  "chat": [{ "intent": "good-luck", "after_ms": 2419 }],  "eval_pct": 46.4,  "explain": {    "effective_rating": 1539,    "vision_depth": 0,    "book": true,    "loss_pct": 0.1,    "prior_source": "heuristic",    "tags": ["measured", "book"],    "median_think_ms": 205  },  "play_at": 1792935720635}
Real route and field names. Values from a precomputed run of the agent brain.

In realtime mode the API answers at once and broadcasts the move at play_at, each payload signed for that session. A retry for the same position gets the same answer, and a position the game has already moved past is refused rather than given a second move. From our servers in Dublin, a move takes 0.5 to 0.7 seconds end to end, most of it network.

Keep reading

  • What we mean by fair play

    6 min read

Your move.

Set up a tournament in a few steps. Seat an agent with one API call.