Extension docs
Equipe Startlist AI
Startlist AI helps show organizers turn rider PM notes into structured start-list wishes, test those wishes against Equipe's prepared start slots, and export a proposed order back to Equipe.
What The Extension Does
Imports Equipe data
Pulls competitions, starts, riders, horses, horse numbers, and PM notes from the current meeting.
Parses rider wishes
Uses AI to extract wishes such as late starts, near another rider, before or after a break, and spacing or order between a rider's own horses.
Evaluates the order
Moves starts within the existing imported slots and shows which wishes are honored, unhonored, or unenforceable.
Exports changes
Writes the proposed position, start number, and time back to Equipe when those values are available. After a successful export, fulfilled PM todos can also be marked completed in Equipe. Export stops if affected competitions contain ridden or ranked starts.
Before You Start In Equipe
The extension works from Equipe's existing start slots. Prepare the meeting in Equipe first:
- 1. Draw every competition. The extension does not create a start list from scratch.
- 2. Add planned breaks. Breaks should already exist in the Equipe schedule before import.
- 3. Run Equipe's automatic start-time conflict resolver. Use the magic wand in Equipe so the start slots and estimated times are ready. Note the Min between you use there: enter the same value when you evaluate wishes, so Startlist AI keeps the time between each rider's starts that the magic wand gave them.
- 4. Verify the order and estimated times. Startlist AI moves starts between the imported slots; it does not recalculate the whole day plan.
- 5. Make sure PM notes are entered. Rider PM notes and horse PM notes are imported and parsed as the source wishes.
Workflow
Step 1
Import
Pull the prepared meeting data from Equipe.
Step 2
Parse wishes
Use AI to turn PM notes into structured wishes.
Step 3
Evaluate wishes
Move starts within existing slots, keep each rider's Min between, and check wish status.
Step 4
Export order
Write the proposed order back to Equipe and complete fully resolved PM todos.
Parse Throughput And Rate Limits
Wish parsing fans out to one background job per PM note. The app limits concurrent OpenAI parse requests per organizer/API key, so parsing several meetings at the same time does not multiply traffic past the same organizer's OpenAI rate limit.
- Parse concurrency
- PARSE_CONCURRENCY=2
- Job threads
- JOB_THREADS=10
- Job processes
- JOB_CONCURRENCY=1
Effective parallel parsing is bounded by the lowest of parse concurrency and available job worker capacity. A large meeting often uses more OpenAI tokens per minute than the API key allows. When OpenAI says the per-minute limit is reached, the note is rescheduled with backoff instead of continuing to occupy a worker thread: it waits at least 1 minute plus a random spread of up to 1 minute, so the waiting notes do not all come back at the same moment, and it tries up to 20 times. Parsing simply takes longer; the meeting page shows a per-minute limit message while it waits.
An OpenAI rate/spend limit that does not refill by waiting, such as an API key with no quota or billing left, stops the note at once with a message to check billing. Notes that could not be parsed are marked with the error on the wish inspection page. Parse missing notes then parses only the notes without a current result, so the notes that already worked are not sent to OpenAI again. Parse all again parses every note.
Supported Wish Types
The AI parser turns PM text into structured wishes. Only wishes with real Equipe ids for the rider, horse, competition, and target rider can be acted on by the resolver.
PM notes can be written in Swedish, Dutch, French, German, or English. Politeness wording and abbreviations — such as Dutch “a.u.b.”, “aub”, “ajb”, “graag”, or “gelieve”, French “s.v.p.” or “svp”, and German “bitte” for “please”, and greetings or sign-offs like “alvast bedankt”, “danke”, and “mvg” — are understood as politeness, not as wish content. They do not need to be removed or rewritten before parsing, and they never block a note from being parsed.
Horse names may be misspelled. A close spelling variant of one of the rider's horses, such as “Cappoccino” for “Cappuccino”, is matched to the imported horse. A fence height combined with a wish, such as “110 graag vooraan” or “Amigo in 100cm vanachter”, is read as a competition reference: the parser picks the rider's competition whose name carries that height (“1m10”, “1.10m”, and “110 cm” are the same height) and the horse the rider starts with there.
The parser knows the date of every competition. A weekday or date in a note, such as “vrijdag als eerste” or “Sunday first 10”, limits the wish to that day’s competition. A competition number in the note, such as “H: Dollar Baby / 1: Graag achteraan de proef”, limits the wish to that competition only, even when the horse also starts in other competitions. A horse note without a competition or day applies to every competition where that horse starts.
Wishes Written For Another Rider
Parents, partners, and trainers often write a PM note for someone else, for example “my daughters Lumi and Emma could jump in the beginning of the 110” or “Cappuccino als 1. Pferd” when Cappuccino is ridden by the writer's daughter. When a note names another rider, or a horse that the note's own rider does not start, the parser looks up who actually starts and stores the wish for that rider, in that rider's competition and with that rider's horse. Such a wish shows a For rider label in the rider wishes view and is resolved and exported like any other wish. A wish is never bound to a horse that only another rider starts: if the parser cannot tell which rider is meant, the wish is stored as unparseable so you can correct it with Edit for parsing. The PM note itself stays with the rider who wrote it, so its todo marker is only completed when every wish in that note is honored.
Placement
Requests to start in a part of a competition, in a numeric range, in the last places, or before/after a break. “Early”, “vooraan”, “in het begin”, and similar wording is the front of the competition. “Late”, “at the end”, “achteraan”, and similar wording is treated as the back of the competition, and so is vague wording such as “one of the last ones”. “Last”, “laatste”, “sist”, or “dernier” means exactly the last start, and “last 5” or “laatste 5” means within the last five starts. End or late wording without the word last, such as “op het einde van de proef”, “fin d’épreuve”, “zo laat mogelijk”, or “helemaal achteraan”, is the back of the competition, not the very last start. “Startnummer” without a number, as in “graag startnummer in laatste deel”, is not a start number request. Negative wording such as “niet te vroeg” or “pas trop tôt” is never read as front or back; it is kept as informational for a human. “First 10” is a position range from 1 to 10. Placement wishes must be bound to one horse in one competition.
- Zone
front,middle, orback- Range
minandmaxstart positions- Last
lastN start positions; 1 is the very last start- Break
beforeorafter, optional offset range
Starting Number
Requests for an exact start number, around a number, or within a start-number range.
A bare number with “around”, such as “Rond de 25” or “Around 40”, is a start number, and
“als eerste” or “as first” is start number 1.
A class number, such as “competition 1”, is not treated as a requested start number.
Neither is a time of day, such as “around 9.00”, or a horse label, such as “Paard 2”,
which riders use to point out which of their own horses a line is about. A fence height
on its own, such as “1m10” or “Handicap 110” in a multi-height competition, is the rider
declaring which height they jump and is stored as informational only; a height together
with a wish, such as “110 graag vooraan”, refers to the competition of that height.
If a PM note says a horse is “crazy”, the parser treats that as a hard request for
that horse to start first in every competition where the horse appears; “crazy horse last”
is a hard request for the very last start instead. A nervous or scared horse (“nervous
horse”, “paard is bang in de paddock”) is informational only and never moves the horse.
around means plus or minus one start number. These wishes must be bound to one horse in one competition.
Near Rider
Requests to start near, before, or after another rider. The parser must resolve the other rider
with the rider lookup tool and store target_equipe_person_id; a plain name is not enough.
A short note that is only a name with a direction, such as “Na Zelie Vanderstichelen”, “Altijd na
…”, “Voor …”, or “After …”, counts as a complete after/before wish for the whole rider.
The lookup ignores common accent differences, so a note can mention “Léa” even if the imported
rider name is stored as “Lea”. Close spelling variants are matched as well, so “Zelie van der
sticggelen” still finds “Zelie Vanderstichelen”; if the AI leaves out the target or picks a
person whose name does not match the written name, the app looks the written name up itself and
only keeps the wish when exactly one rider clearly matches. Otherwise the wish is stored as
unparseable so you can correct the name with Edit for parsing.
Overall support/travel/coaching requests can be rider-level. Start-list wording inside one concrete
horse/competition segment is competition-horse level.
Family or group requests such as “the Van Es and De Swert families together” are treated as
rider-level near-rider wishes: the names are looked up separately, every clear matching other rider
becomes a target, and the current PM rider is not used as their own target.
Own Horse Order And Spacing
Requests about the rider's own horses, either as an explicit horse order
(ordered_equipe_horse_ids) or as a time gap. “Nobel first of the 2 horses”,
“als tweede paard”, or “en 1er des 2 chevaux” is an order between the rider's own horses,
not a start number. With more horses, “als eerste van haar 3 paarden” puts that horse before
each of the rider's other horses in the competition. A count before or after one of the
rider's own horses, such as “20 paarden voor Valeriane” or “een uur voor het andere paard”,
is an order plus about that gap: from the stated distance up to
15 minutes more, so “een uur voor”
means 60 to 75 minutes before the other horse, not any time at least an hour earlier. Only
“minstens” or “at least” makes it a minimum. Asking for “voldoende tijd tussen” or “enough time
between my horses” without a number is not turned into a gap; the Min between you set when
evaluating already protects every rider's time between starts. When a note lists positions for several horses without saying which
horse gets which, such as “komt met 3 paarden, begin, midden en laatste”, the parser does
not put them all on one horse; the unassigned part is kept as informational for a human.
If the parser still gives one horse in one competition contradicting parts, such as front and
back, those wishes are kept as unparseable for a human, because no start order can honor
them.
A gap such as “30 starts between”
is converted during parsing with the rule of thumb 1 start = about 2 minutes, so it becomes
gap_minutes: 60. We store this as time instead of a start count because several arenas
and competitions can run in parallel, so “20 starts” is easier and safer to evaluate as about
40 minutes between the rider's own starts. A gap can also be a range with
gap_min_minutes and gap_max_minutes. A gap of zero minutes is
not a wish and is stored as unparseable.
Info And Unparseable
Non-actionable text is stored as info or unparseable so it can still be reviewed,
but the resolver marks it as unenforceable because no start-slot move can satisfy it.
Stabling requests are always informational: wording such as “stal/stallen/stalling bij …”,
“box naast …”, “écurie avec …”, or “stable next to …” asks for neighbouring stables, not
neighbouring start positions, so it never becomes a near-rider wish. If the same note also
contains start-list wording, such as “vlak voor of na …”, that part is still parsed as a wish.
Use the Info / unparseable filter in the rider wishes view
to focus on these notes. If the PM text is clear to the organizer but hard for the parser,
use Edit for parsing to save a local parsing override and
re-parse that note. This does not change the PM text in Equipe. If Equipe later imports a
changed PM for the same note, the local override is kept and marked for review.
An operator can also remove an extracted wish that should not be enforced; removed wishes
are ignored by the resolver and completed-note export until they are restored.
How The Resolver Works
The resolver does not build a new start list. It keeps Equipe's imported start slots and moves movable starts inside each competition to satisfy as many wishes as possible. Only starts that a wish refers to are placed by the optimizer; every other start keeps its imported relative order and just slides a few slots to make room. A rider without a wish is never thrown to a completely different part of the class.
Movable Starts
Only normal starts move. Pause rows stay fixed and are excluded from moves and gap analysis. The proposed start receives the target slot's position, start number, time, estimated time, and timestamp.
Per-Competition Search
The resolver optimizes one competition at a time. It starts from the imported order, seeds direct placement/starting-number wishes, then tries improving swaps for up to 80 iterations.
Scoring
A hard wish is worth 10 points and a soft wish is worth 1 point, unless a wish has an explicit custom weight. Each moved start costs 0.001 points, so unnecessary moves are avoided. A placement or start-number wish that cannot be honored costs more the further its start ends up from what the rider asked for, so the resolver keeps it as close as it can and does not push it away to make room for someone else. Time between a rider's starts is scored too, see below.
Statuses
Honored means the proposed order satisfies the wish. Unhonored means the wish was actionable but the chosen order does not satisfy it. Unenforceable means required data is missing or the wish cannot be checked by moving start slots.
Resolver Thresholds
Front, middle, back
The resolver divides each competition into thirds using the start's center position:
(position - 0.5) / total. Values up to 1/3 are front,
values up to 2/3 are middle, and the rest are back.
A last wish is honored when the start is within the last N positions of the
competition.
Near rider
near is honored when the starts are at most
5 starts apart in the same competition.
before and after require the correct side of the target rider;
they do not currently require a maximum distance.
Breaks
Breaks are inferred inside each competition from longer gaps between imported start times.
The resolver uses est_stamp when present, otherwise the displayed estimated/start time.
A gap is treated as a break when it is at least the greater of
median gap + 5 minutes
and median gap × 2.
If no break can be inferred, before/after-break wishes are unenforceable.
Riders with several horses
When you evaluate wishes you enter Min between, the minimum time between a rider's starts on the same day, just like in Equipe's start time check. It starts at 45 minutes and remembers the value of your last evaluation. The resolver measures the time between all of a rider's starts that day, across every competition and arena, and never makes it worse than in your prepared list. A gap that was already shorter than Min between in your list is not held against the result, but it is not made shorter either.
Every minute a rider loses below Min between costs 0.25 points. A soft wish is worth 1 point, so it never costs a rider more than 4 minutes; a hard wish may cost up to 40 minutes. When a rider only asks for the order of their horses, the resolver first lets the horses trade places among the rider's own slots, so the order changes and the time between them stays. Riders without a wish only slide a slot or two when other starts move past them; they may end up to 3 minutes below Min between before that counts. Riders whose own note asks for their horses closer together than Min between are exempt: their wish decides instead.
The result page lists every rider who ends up with less time between starts than in your prepared list, with the gaps before and after, so you can check them in Equipe's start time check.
Own-horse gaps
Own-horse gaps are checked in minutes using the proposed slots' displayed times, measured
between the rider's starts in time order.
gap_minutes is a minimum gap. gap_min_minutes and
gap_max_minutes define an accepted range, which is how “een uur voor” or
“20 paarden voor” another own horse is stored. If times are missing, the wish is unenforceable.
When the source note says combinations or starts instead of minutes, the parser converts it with
1 start = about 2 minutes before the resolver sees it.
What Export Writes Back
Export writes the proposed start-list values back to Equipe. It writes the new position for every moved start, and also writes start time when it exists in the imported start slots. Start numbers are read from the competition's current startlist in Equipe at the moment you export: the number stays with the slot, so a start that moves into a slot takes over that slot's number and the list stays numbered in running order. This also works when the competition was numbered after the import. If a competition has no start numbers at all, none are written and you can number it in Equipe afterwards as usual.
Start order
Starts are moved into existing Equipe slots. The extension does not create new slots or rewrite the whole schedule. Export stops before writing if affected competitions contain ridden or ranked starts.
PM todo status
Equipe PM notes can use [] for an open todo and [x] for a completed todo.
After the start order has been exported and verified, Startlist AI changes [] to
[x] only when every parsed item in that rider or horse PM note is fully resolved.
PM notes are completed conservatively
A PM note is left unchanged if any actionable wish in that note is unhonored or unenforceable, if the parser marked part of the note as info or unparseable, if the note has no actionable wishes, or if the live PM text in Equipe has changed since the last import. Horse PM notes are also left unchanged unless every imported copy for that horse is fully resolved.
Privacy And Data Responsibility
The organizer chooses to use their own OpenAI API key. That means the organizer is responsible for deciding whether the meeting's PM notes and related start-list context may be sent to OpenAI for processing.
What is sent to OpenAI
When parsing wishes, the extension sends the PM note text, the current rider name, the rider's imported competitions and horses, and any needed lookup queries/results for riders, horses, or competitions. A horse lookup also returns which rider starts that horse in which competition, and a rider lookup can return that rider's competitions and horses, so that notes written for another rider can be bound correctly.
What the organizer must check
Before parsing, the organizer should make sure they have the right permission/legal basis to process this data with OpenAI and that their OpenAI project has acceptable data retention and data sharing settings.
Retention settings matter
OpenAI data handling depends on the API endpoint, project settings, organization settings, and whether Zero Data Retention is enabled. Check OpenAI's current Data controls in the OpenAI platform and the organization's data sharing settings before using real rider data.
OpenAI API Key
Startlist AI needs an OpenAI API key to parse PM notes. The key is stored encrypted for the organizer and is used only when parsing rider wishes.
How to create the key
- Go to platform.openai.com and sign in.
- Open the API keys area for the project or organization that should pay for the usage.
- Create a new secret key.
- Use All permissions / full permissions for the key.
- Paste the key into AI access in this extension.
- Current parser model
- gpt-5.4
- Permission level
- All / full permissions
Keep the key private. Do not paste personal ChatGPT credentials here; this must be an OpenAI API key.
Important Limits
- The AI parser can misunderstand ambiguous notes. Use the rider wishes view to inspect original text vs. extracted data. Individual PM notes can be parsed again from that view; the note card updates in place when the new result is ready.
- The resolver only moves starts inside imported slots. It does not invent new slots or redesign the schedule.
- Export is blocked when affected competitions contain ridden or ranked starts, so live competition data is not overwritten.