Lumify Sports Intelligence
Server Details
Schedules, scores, odds, splits & explainable AI bet confidence — 8+ sports, free instant key.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
- Repository
- lumifyai/lumify
- GitHub Stars
- 4
- Server Listing
- Lumify Sports Intelligence
TDQS
Scored across 27 tools
The tools cover distinct resources and actions, and descriptions explicitly differentiate overlapping families such as get_odds, get_period_odds, get_player_props, and get_team_props. Some ambiguity remains in the broad odds/intelligence cluster and between get_event and get_live_score, but the guidance is generally strong.
All tool names use consistent snake_case with a clear verb_noun pattern (get_, list_, resolve_, search_, batch_get_, grade_, estimate_). Minor variations like list_ev use a standard abbreviation without breaking the convention.
At 27 tools the set is large, but the domain is broad (events, teams, players, odds, props, splits, forecasts, injuries, stats, grading, cost estimation) and most tools represent distinct endpoints. It is slightly over the ideal range but not excessively redundant.
Coverage is extensive for a read-only sports intelligence API: discovery, entity details, odds, props, stats, injuries, forecasts, +EV scanning, name resolution, and slip grading are all present. Minor gaps include league standings, team season stats, and player game logs, but core workflows are supported.
Available Tools
27 toolsbatch_get_eventsARead-onlyIdempotentInspect
Get multiple events by id in one call — for agents that already have a list of ids and want full detail for each without one call per event. Max 25 ids. Returns full detail for every id that exists plus a not_found list for any that don't (never billed). Use get_event for a single id, or list_events / query_events to discover ids first.
| Name | Required | Description | Default |
|---|---|---|---|
| bookmaker | No | Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all. | |
| event_ids | Yes | Event ids to fetch (max 25); duplicates are billed once. | |
| include_odds | No | Inline current odds scoped by bookmaker (default: pinnacle). Does not add credits — each found event stays 1 credit. | |
| include_intelligence | No | Inline bet intelligence on each event. Does not add credits. |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | No | |
| events | No | Full event detail (same shape as get_event) for every found id. |
| not_found | No | Requested event_ids that don't exist. Never billed. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds valuable behavioral context beyond annotations: the max 25 id limit, the not_found list for missing ids, that not_found entries are never billed, and that include_odds/include_intelligence do not add credits. It also clarifies that duplicates are billed once, which is crucial for cost-sensitive agents.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero wasted words. The primary purpose is front-loaded, followed by the max limit, return behavior, billing nuance, and sibling alternatives. Every clause adds value, and the structure guides the agent from action to edge cases.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists, the description doesn't need to enumerate return fields. It covers the critical contextual points: id list requirement, max 25, not_found behavior, billing implications, and when to use siblings. The description fully equips an agent to decide and call correctly without missing prerequisites or caveats.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter is already documented in the input schema. The description does not add new parameter-specific meaning beyond what the schema provides; it restates the max 25 limit and duplicates-billed-once, which are also in the schema. Baseline of 3 applies because the schema fully covers parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource ('Get multiple events by id in one call') and immediately distinguishes it from sibling tools by stating it's for agents that already have ids and want full detail without one call per event. It also names the sibling alternatives (get_event, list_events, query_events) and explains the distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool ('for agents that already have a list of ids') and when not to, naming the alternatives: 'Use get_event for a single id, or list_events / query_events to discover ids first.' This is clear guidance with no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
estimate_costARead-onlyIdempotentInspect
Estimate the credit cost of one or more planned tool calls before making them — no credits are spent. Costs are data-dependent (e.g. odds/intelligence/splits not yet ingested for an event are free, and batch_get_events ids that don't exist cost nothing), so this returns a [min_credits, max_credits] range per call rather than a single number. Pass the exact tool name and arguments you're considering, e.g. {"tool": "get_event", "arguments": {"event_id": 123, "include_odds": true}}.
| Name | Required | Description | Default |
|---|---|---|---|
| calls | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| estimates | No | |
| total_max_credits | No | |
| total_min_credits | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotentHint, destructiveHint), the description adds valuable behavioral detail: no credits are spent, results are a [min_credits, max_credits] range, costs are data-dependent, and specific free-call cases are given. This goes well beyond the structured safety hints and enriches the agent's mental model.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences accomplish all goals: purpose, behavior, and usage example. Nothing is redundant; every sentence carries essential information. The structure is front-loaded with the core function and then elaborates with context and a concrete example.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (array input, max 50 items) and the presence of an output schema, the description fully covers what an agent needs to invoke it correctly: the input format, the output format (range), and special cost edge cases. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates by explaining the required 'calls' array structure, the 'tool' and 'arguments' fields, and providing a concrete JSON example. The agent knows exactly what to pass without needing to infer from a bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Estimate') and resource ('credit cost of planned tool calls'), making it unmistakable. It explicitly states 'before making them' and 'no credits are spent,' distinguishing it from all sibling tools that actually fetch data. This is a model of clear purpose differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly conveys when to use the tool (before executing calls, to estimate cost) and provides a usage example. However, it does not explicitly state when not to use it or name alternatives. The context makes the use case obvious, but explicit exclusion guidance is missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventARead-onlyIdempotentInspect
Get a single event with participants and venue. Optionally inline current odds and/or bet intelligence (same 1 credit as the event call). Raises a not-found error if event_id doesn't exist. Use list_events / query_events to discover ids first, or batch_get_events to fetch several ids in one call.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. | |
| bookmaker | No | Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all. | |
| include_odds | No | Inline current odds scoped by bookmaker (default: pinnacle). Does not add credits — the event call stays 1 credit. | |
| include_intelligence | No | Inline bet intelligence. Does not add credits. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | |
| name | No | |
| sport | No | |
| venue | No | |
| league | No | |
| status | No | |
| starts_at | No | |
| updated_at | No | |
| participants | No | |
| inprogress_since | No | ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds valuable context beyond annotations: it states that a not-found error is raised for invalid ids and that inlining odds/intelligence does not add credits. This enriches the behavioral profile without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. It front-loads the core purpose, then covers alternatives and error behavior efficiently. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has an output schema, the description need not explain return values. It covers discovery, batching, error handling, and credit semantics. Nothing an agent needs to correctly invoke it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds meaningful extra semantics by noting that include_odds and include_intelligence do not increase the credit cost, which is not present in the schema. This justifies a score above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Get' and the resource 'a single event with participants and venue', which is specific and distinguishes it from batch_get_events, list_events, and query_events. It also mentions optional inlining of odds and intelligence, further clarifying scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly directs the agent to use list_events/query_events to discover ids first, or batch_get_events for multiple ids. It also clarifies when to use this tool versus alternatives, which is exactly what usage guidelines require.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_injuriesARead-onlyIdempotentInspect
Beta. Get late-breaking player injury and availability status for an event (out / doubtful / questionable / probable / day_to_day / ir / suspended / available), with previous_status, body_part, note, source_url, and severity (info / material / critical). Beta coverage: NFL and MLB (more sports rolling out). NFL monitoring starts ~4.5 days before kickoff (Wednesday/Thursday practice reports); MLB stays on a 48-hour window. Returns available:false with no charge until the injury monitor has written a first structured report. Checks run on cadence, on a significant main-market odds move, and at a guaranteed pre-kickoff checkpoint. Subscribe to webhook event_type=injury for material/critical changes. No in-game feed. Use exclude_status to drop noisy long-standing designations (e.g. ir) from the response — does not affect available or credit cost.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. | |
| exclude_status | No | Comma-separated statuses to drop, e.g. "ir" to hide injured-reserve/long-term-IL rows (long-standing roster designations, not late-breaking news). Valid values: out, doubtful, questionable, probable, day_to_day, ir, suspended, available. |
Output Schema
| Name | Required | Description |
|---|---|---|
| event_id | No | |
| injuries | No | Per-player rows: player, player_id, team, team_id, status, previous_status, body_part, note, source_url, severity, last_changed_at. team/team_id prefer the player's current roster team when that team is a participant in this event. |
| available | No | |
| confirmed_at | No | |
| next_check_at | No | |
| last_checked_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with annotations already marking readOnly/openWorld/idempotent, the description adds substantial behavioral detail: beta status, league coverage windows, the 'no charge' behavior before a first structured report, polling triggers, the absence of an in-game feed, and the non-effect of exclude_status on availability or credit. This goes well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence contributes operational knowledge an agent needs. It is front-loaded with the primary purpose and then efficiently covers coverage, timing, webhooks, and parameter behavior without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is exceptionally complete for a complex data tool: it covers availability semantics, timing, charge behavior, update triggers, webhook subscription, limitations, and parameter nuances. The presence of an output schema means return-value documentation is handled elsewhere, so no essential calling context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters. The description adds extra semantic value for exclude_status, explaining its purpose as dropping noisy long-standing designations and clarifying that it does not affect availability or credit, which is not evident from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Get late-breaking player injury and availability status for an event,' naming a specific verb, resource, and scope. It also enumerates the specific statuses and fields returned, and it is clearly distinct from sibling tools like get_event or get_player because it targets injury intelligence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides strong contextual guidance: Beta coverage is limited to NFL and MLB, with specific monitoring windows and cadence. It also explains when the tool may return 'available:false' and directs users to webhooks for material/critical changes, though it does not explicitly contrast with alternative tools since no direct sibling exists.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_intelligenceARead-onlyIdempotentInspect
Get predictive bet intelligence for an event: vig-stripped probability, fair_price, Price overlay, main-line ev (Beta), and forecasts[] — forecasted wagers from the model (same objects as list_forecasts): player props plus tennis moneyline/spreads/totals. bets[] is live for MLB, tennis, soccer (MLS + big-five), NFL, and NCAAF. forecasts[] covers MLB, NFL, NCAAF, NBA, NCAAB, NHL, and tennis and can populate when available is false. Fair-price + line-shopping on bets[] today (edge/tier null; has_recommend false). bookmaker is ignored. Match-level tokens (OVER, UNDER, ML_DRAW) have null player/team attribution. Free only when available is false and forecasts is empty. Field catalog: https://lumify.ai/docs/reference#event-intelligence
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. | |
| bookmaker | No | Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada. |
Output Schema
| Name | Required | Description |
|---|---|---|
| bets | No | |
| sport | No | Sport slug for this event. |
| league | No | League slug for this event, if any. |
| matchup | No | Not returned. Use get_stats for pitcher/lineup Data. |
| players | No | Home/away (or p1/p2) participant identification, keyed by role: {role: {name, player_id, team_id}}. |
| event_id | No | Lumify event ID this intelligence describes. |
| available | No | False when no predictive bets[] have been computed for this event yet. forecasts[] can still populate on MLB/NFL/NCAAF/NBA/NCAAB/NHL. Free only when available is false and forecasts is empty. |
| forecasts | No | Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows on team sports; tennis main-line via bet_type ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), OVER/UNDER (total games). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts |
| rationale | No | Event-level factual pre-game matchup chips (injuries, recent form, lineup/availability news — sport-shaped). Written before kickoff; the request path only reads the stored row. |
| odds_source | No | Bookmaker bets[].market prices were sourced from. For probability-model sports this is the book the assessment was priced against, not a bookmaker overlay; per-bet market.book is authoritative if they ever differ. |
| has_recommend | No | True when at least one bet meets the recommendation threshold; null when intelligence has not been computed. False while Edge is not published (current MLB/soccer/tennis Stage 1) — a recommendation requires a non-null tier derived from edge. |
| match_overview | No | Natural-language pre-game matchup preview — form, context, what to watch. Written before kickoff by a Search-backed overlay on every event sport (MLB, NFL, NCAAF, NBA, NCAAB, NHL, soccer, tennis); sport-shaped queries. The request path only reads the stored row. Null when the pre-kickoff job has not run or the fixture was not eligible. |
| intelligence_updated_at | No | ISO-8601 UTC timestamp of the most recent change anywhere in this payload (max of per-bet computed_at). Use per-bet computed_at to reason about a specific bet. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly/idempotent/non-destructive behavior. The description adds substantial beyond-annotation behavior: bookmaker is ignored, match-level tokens have null player/team attribution, edge/tier are null, has_recommend is false, and free access is conditional on available being false and forecasts being empty. This is exactly the kind of operational nuance an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loaded with the core outputs before moving to coverage details. It is longer than average, but the complexity of the tool justifies most sentences; the run-on style and jargon ('vig-stripped', 'Price overlay') make it slightly harder to parse, so it is not a perfect 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description does not need to explain return shapes, and it still covers important call-time context: sports availability, the free-access condition, null attribution for match-level tokens, ignored parameters, and a field-catalog link. This is complete for a complex intelligence tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Parameter schema coverage is 100%, so the schema documents both event_id and bookmaker. The description reinforces that bookmaker is ignored, which is already stated in the schema, but it does not add new parameter-level semantics beyond that. It earns the baseline 3 for high schema coverage rather than extra credit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource ('predictive bet intelligence for an event') and enumerates its distinctive contents: vig-stripped probability, fair_price, Price overlay, main-line ev, forecasts[], and bets[]. It also clarifies scope by noting sports coverage and by referencing list_forecasts, making it easy to tell apart from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives rich contextual usage signals: which sports bets[] is live for, which sports forecasts[] covers, when forecasts can populate, and when the tool is free. It references list_forecasts as the source of forecasted-wager objects, but it does not explicitly state when to prefer this tool over list_forecasts or other siblings, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_live_scoreARead-onlyIdempotentInspect
Get a lightweight live score snapshot for an event: status, period, clock, per-participant score and period-by-period scores, and last-updated time. Cheaper and faster than get_event when you only need the score, not participants or venue. Capped at 20 calls/min per key (shared with GET /v1/events/{id}/score and list_events include_scores=true). For live updates prefer the SSE stream. Raises a not-found error if event_id doesn't exist.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| clock | No | |
| period | No | |
| scores | No | |
| status | No | |
| event_id | No | |
| finished | No | |
| updated_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds material operational context they do not cover: a 20 calls/min per-key cap shared with two other endpoints, a preference for the SSE stream under live updates, and a not-found error when event_id is invalid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences with the payload, the cost/sibling comparison, the rate limit, and the error condition front-loaded in that order. No filler or restatement of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-field detail need not be re-explained; the description still summarizes the payload shape. Rate limiting, error behavior, and the streaming alternative are all covered, leaving nothing an agent needs to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Single required parameter with 100% schema description coverage, so the schema already documents event_id and its provenance (list_events, query_events, search results). The prose adds nothing beyond that, which is the expected baseline when the schema does the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource (get a live score snapshot) and enumerates the returned fields (status, period, clock, per-participant score, period scores, last-updated). It explicitly contrasts itself with the sibling get_event, so an agent can separate the two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States when to choose this over the alternative ("cheaper and faster than get_event when you only need the score, not participants or venue") and names a third option for live updates ("prefer the SSE stream"). Both a selection condition and an exclusion are given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_oddsARead-onlyIdempotentInspect
Get current betting odds for an event: per-bookmaker lines and last-updated time. Includes in-play quotes while the event is underway; books that have not quoted since kickoff are omitted. bookmaker defaults to pinnacle. Use 'all' or a comma-separated list for multiple books — still 1 credit. Default is main lines (is_main=true); set include_alts for alternate spread/total rungs. Final events include result (won/lost/push/void) graded from the pre-kickoff close. MLB, tennis, and soccer (MLS + big-five) mains also include fair_price and consensus mirrored from published assessments. Returns available:false with no charge if odds aren't posted for this event yet. If bookmaker is omitted and Pinnacle hasn't posted a line yet (common for the first/last games of a preseason slate), falls back to the best-covered other book and adds requested_bookmaker='pinnacle' plus fallback_bookmaker to the response instead of reporting no odds; an explicit bookmaker='pinnacle' never falls back. Use get_odds_history for line movement over time.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. | |
| bookmaker | No | Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list. | |
| include_alts | No | Include alternate spread/total rungs. Default false (mains only). |
Output Schema
| Name | Required | Description |
|---|---|---|
| event_id | No | |
| available | No | |
| bookmakers | No | Per-book markets. Outcomes include is_main. In-play omits books that have not quoted since kickoff. Final events add result (won/lost/push/void) and close on the pre-kickoff point. |
| last_updated | No | |
| fallback_bookmaker | No | The book actually returned when requested_bookmaker is present. |
| requested_bookmaker | No | Present only when the default (no bookmaker arg) request fell back to a different book because Pinnacle has no line yet — always 'pinnacle' when present. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only and idempotent, but the description adds substantial behavioral detail beyond that: no-charge available:false responses, fallback to another bookmaker, credit cost for multiple books, omission of books that have not quoted since kickoff, and result grading from pre-kickoff close. This is far more than the annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded with the core purpose, and every sentence adds useful operational or behavioral context. No filler is present, and the detail about fallback, credits, and alternatives earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the existence of an output schema, the description is complete enough for correct invocation. It covers defaults, edge cases (unposted odds, preseason slates), in-play behavior, final-event results, and related tools, leaving no critical ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description goes well beyond the schema: it explains 'all' and comma-separated lists cost 1 credit, clarifies the default main-lines behavior, and documents the fallback semantics when bookmaker is omitted. This adds meaning that the schema does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Get current betting odds for an event: per-bookmaker lines and last-updated time.' It clearly defines the tool's scope and distinguishes it from get_odds_history by directing line-movement queries to that sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit usage context: defaults, multi-book selection, in-play behavior, final-event result grading, and a clear alternative ('Use get_odds_history for line movement over time'). It also explains fallback behavior when Pinnacle has no posted line, which helps the agent decide when this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_odds_historyARead-onlyIdempotentInspect
Get line-movement history for an event: a list of past odds snapshots (movements), each with its own timestamp, up to limit entries. bookmaker defaults to pinnacle. Use get_odds instead if you only need the current line.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max line-movement entries to return. Default 50. | |
| event_id | Yes | Event id, from list_events, query_events, or search results. | |
| bookmaker | No | Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list. |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | No | |
| event_id | No | |
| movements | No | Odds snapshots over time; each entry carries its own timestamp. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and idempotentHint=true, so the safety profile is covered. The description adds useful context about the output structure (list of movements with timestamps) and the limit behavior. It does not mention ordering or pagination details, but given the annotation coverage, this is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero fluff. The main purpose is front-loaded, the default is stated, and the alternative is given. Every word earns its place; the description is efficient and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with three parameters (one required), 100% schema coverage, an output schema present, and rich annotations, the description covers everything an agent needs to invoke it correctly. It explains what the tool returns, the default bookmaker, and when to use a sibling. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: all three parameters (limit, event_id, bookmaker) are fully documented with defaults and valid values. The description adds only marginal clarification (e.g., 'up to limit entries' and 'bookmaker defaults to pinnacle'), which essentially restates schema information. Baseline 3 is appropriate since the schema already does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the specific verb and resource: 'Get line-movement history for an event' and describes the output as 'a list of past odds snapshots (movements), each with its own timestamp.' It explicitly distinguishes from sibling get_odds by saying 'Use get_odds instead if you only need the current line.' This leaves no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage guidance by naming the alternative (get_odds) and the condition for choosing it ('if you only need the current line'). It also mentions the default bookmaker, which sets expectations for typical use. No exclusions are needed beyond the single alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_period_oddsARead-onlyIdempotentInspect
Get first-half / first-five / first-set lines and live progress for an NFL, NCAAF, NBA, NCAAB, MLB, soccer, or tennis event. Joins persisted first_half_spreads / first_half_totals mains to this-event period scores (1H = Q1+Q2, NCAAB or soccer native 1H; MLB F5 = innings 1–5; tennis S1 = first-set games) and grades the period, not the full game. GET /odds / get_odds stay on moneyline/spread/total. Returns available:false with no charge if no period mains have been ingested. Other sports return HTTP 400.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| clock | No | Game clock from the live score snapshot. |
| sport | No | Sport slug: nfl, ncaaf, nba, ncaab, mlb, soccer, or tennis. |
| period | No | Current period from the live score snapshot. |
| status | No | Event status (scheduled, inprogress, delayed, final, …). |
| event_id | No | Lumify event ID. |
| available | No | False when no first-half / first-five / first-set mains have been ingested; period_odds is empty and the call isn't billed. |
| period_odds | No | One row per (scope, market, line). Fields: scope (1H, F5, or S1), market (first_half_spreads / first_half_totals), line (home-perspective for spreads), home_score, away_score, current (totals only), current_margin (spreads only), pct_of_line, settleable, scope_complete, result (totals), home_result / away_result (spreads), books ({book_slug: {home, away} or {over, under}}). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only/idempotent/non-destructive, and the description adds meaningful behavior beyond that: it joins persisted period mains to live scores, grades the period rather than the full game, explains the no-charge available:false state, and documents the HTTP 400 restriction. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place and the main purpose is front-loaded. The description is somewhat dense and the phrase 'GET /odds / get_odds' is slightly awkward, but overall it is efficiently structured for the amount of domain nuance it conveys.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of period definitions and sport-specific rules, the description is remarkably complete. It covers supported sports, how period scores are computed, the difference from full-game grades, the no-charge empty state, and the error case. With an output schema present, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 100% coverage for the single required parameter, event_id, and already explains where it comes from. The description does not add parameter-specific detail, but the schema carries the full burden, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), a specific resource ('first-half / first-five / first-set lines and live progress'), and the sports covered. It explicitly distinguishes itself from get_odds, which stays on moneyline/spread/total, so an agent can immediately tell what this tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says when to use this tool: when period-specific lines/progress are needed, not full-game odds. It names the alternative (GET /odds / get_odds) and gives exclusion signals such as 'Other sports return HTTP 400' and 'available:false with no charge if no period mains have been ingested.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_playerARead-onlyIdempotentInspect
Get a single player identity profile: name, sport, country, position/handedness, physical stats, current team, rankings (tennis {singles, points}; null on every other sport), and image_url (Lumify media URL, null until the sport's headshot/enrichment job). Raises a not-found error if player_id doesn't exist. Resolve ids via search_players.
| Name | Required | Description | Default |
|---|---|---|---|
| player_id | Yes | Player id, from search_players. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | Lumify player ID. |
| slug | No | URL-safe unique slug. |
| sport | No | Sport slug, e.g. mlb, tennis, nfl. |
| position | No | Roster position abbreviation when the sport has one (e.g. C, P, SS for MLB; QB, WR for NFL). Null for tennis and when not yet ingested. |
| rankings | No | Sport ranking block. Tennis: {singles, points} from ATP/WTA standings. Null for every other sport. Tennis /stats also exposes ranking / ranking_points on the tennis player block. |
| birthdate | No | YYYY-MM-DD date of birth. |
| full_name | No | Display name. |
| height_cm | No | Height in centimetres. Null when not ingested. |
| image_url | No | Lumify media URL for the player headshot (https://lumify.ai/media/players/{sport}/{id}.{ext}). Null until the sport's headshot/enrichment job. Never a vendor CDN. |
| is_active | No | False when deactivated or retired. |
| last_name | No | |
| weight_kg | No | Weight in kilograms. Null when not ingested. |
| first_name | No | |
| handedness | No | left | right | switch. Meaning is sport-specific (bats for MLB, shoots for NHL, playing hand for tennis). Null when unknown. |
| retired_at | No | YYYY-MM-DD retirement date when known. |
| country_code | No | ISO 3166-1 alpha-3 country code. |
| current_team_id | No | Lumify team ID when the player is on a club roster. Null for tennis. |
| current_team_name | No | Current team display name. Null for tennis. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent, non-destructive), the description discloses important runtime behavior: it raises a not-found error for invalid player_id, and it explains null semantics for rankings on non-tennis sports and image_url before enrichment. This gives the agent accurate expectations for edge cases and return values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense but well-structured and front-loaded. Every sentence earns its place: the first defines the tool and its output fields, the second states error behavior, and the third gives id resolution guidance. There is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single required parameter, a high-coverage schema, an output schema, and strong annotations, the description is complete. It covers the return payload's special cases, the error case, and how to obtain a valid player_id. An agent has everything needed to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents player_id with 100% coverage, including 'from search_players.' The description reinforces this by saying 'Resolve ids via search_players,' but it does not add meaningful new parameter semantics beyond what the schema provides. The error behavior is useful context but is more behavioral than parameter-specific.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Get a single player identity profile', then enumerates the fields returned (name, sport, country, position/handedness, physical stats, current team, rankings, image_url). It clearly distinguishes from siblings like get_team, get_player_events, and get_player_props by scoping the tool to identity/profile data rather than events, odds, or props.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool: to retrieve a single player's identity profile, and it explicitly routes id resolution via search_players. It does not explicitly state when not to use it or name alternatives for events/props, but the profile-scoped wording and the mention of search_players provide adequate guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_player_eventsARead-onlyIdempotentInspect
List a player's events (schedule/results), paginated by id (after_id). Defaults to ±30 days around today when no date filter is given. Resolve player_id via search_players first.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | End date YYYY-MM-DD. | |
| from | No | Start date YYYY-MM-DD. | |
| limit | No | Max events to return per page. | |
| status | No | Filter to events in this status. | |
| after_id | No | Cursor: last event id from the previous page's next_after_id. | |
| player_id | Yes | Player id, from search_players. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | Events in the same shape as list_events' EventSummary. |
| has_more | No | |
| player_id | No | |
| next_after_id | No | Pass as after_id to fetch the next page; null on the last page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate read-only and idempotent. The description adds useful behavioral details: pagination by after_id and the default ±30-day date window when no filter is provided. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with the core action. Every clause adds value: scope, pagination, default window, and prerequisite. Zero waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a full output schema and rich annotations, the description doesn't need to detail return format or safety. It covers core behavior, pagination, defaults, and the player_id prerequisite, making it complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover 100% of parameters, including player_id origin and after_id cursor semantics. The description reiterates these but doesn't add substantially new parameter-level information beyond connecting the pagination flow.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists a player's events, with 'player's' distinguishing it from broader event tools. The parenthetical (schedule/results) and pagination mention add specificity. This is a specific verb+resource+scope, meeting the top criteria.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context: it's for retrieving a specific player's events, and instructs to resolve player_id via search_players first. However, it does not explicitly contrast with alternative event-listing tools like list_events or query_events, so it lacks explicit exclusions or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_player_propsARead-onlyIdempotentInspect
Get player-prop lines and live progress for an NFL, NCAAF, NBA, NCAAB, NHL, MLB, or soccer event. Joins persisted player-prop mains to this-event player box counts and grades over/under/push (1:1 slugs, combo sums, weighted total bases, anytime TD, double-double/triple-double, hockey points). Sport × market catalog: https://lumify.ai/docs/player-props. GET /odds / get_odds stay on moneyline/spread/total. Returns available:false with no charge if no prop mains have been ingested. Other sports return HTTP 400.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| clock | No | Game clock from the live score snapshot. |
| sport | No | Sport slug: nfl, ncaaf, nba, ncaab, nhl, or mlb. |
| period | No | Current period from the live score snapshot. |
| status | No | Event status (scheduled, inprogress, delayed, final, …). |
| event_id | No | Lumify event ID. |
| available | No | False when no player-prop mains have been ingested; player_props is empty and the call isn't billed. |
| player_props | No | One row per (player, market, line). Fields: player, player_id (null if unmatched), market (prop category), line, current (this-event box count), pct_of_line, settleable, result (in_progress / over / under / push / dnp — box landed and this player has zero rows / no_stat — played but this slug never landed, unmatched, or box not landed yet; null when not settleable), books ({book_slug: {over, under}} American prices). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses additional runtime behaviors beyond the annotations, such as returning available:false with no charge when no prop mains are ingested, and returning HTTP 400 for unsupported sports. These are critical operational details not captured by readOnlyHint or other annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise yet packed with information, front-loading the main purpose and then covering details like the join and grading logic, differentiation from get_odds, and error/charge behaviors. Each sentence serves a clear role with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and the presence of an output schema, the description covers all key aspects: purpose, supported sports, differentiation from similar tools, error handling, and cost implications. It provides enough context for an agent to decide when and how to use it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description for event_id already explains its origin (from list_events, query_events, or search results), and the tool description does not add further parameter-specific context. With 100% schema coverage, the baseline score of 3 is appropriate, as no additional parameter semantics are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it gets player-prop lines and live progress for specific sports (NFL, NCAAF, NBA, NCAAB, NHL, MLB, soccer), and differentiates from get_odds by explicitly noting that GET /odds and get_odds handle moneyline/spread/total. This makes the tool's purpose unambiguous and distinct from its siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use, including supported sports, a link to the catalog for more details, and differentiation from get_odds. It also mentions error behavior (HTTP 400 for unsupported sports) and the no-charge condition, helping an agent decide if this tool is appropriate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_splitsARead-onlyIdempotentInspect
Get public betting splits (bets% and handle%) for an event: a consensus split plus a per-bookmaker breakdown (bookmakers[].bookmaker uses the same odds slugs as get_odds, e.g. draftkings — not upstream short keys like dk), with a captured_at timestamp. Available for MLB, NBA, NHL, NFL, NCAAF, and NCAAB. Not available for tennis or soccer (upstream 400). Returns available:false with no charge if splits haven't been captured for this event yet or the sport is unsupported.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| event_id | No | |
| available | No | |
| consensus | No | Aggregate bets%/handle% across bookmakers. |
| bookmakers | No | Per-bookmaker splits. Each item has bookmaker (odds slug), name, moneyline, spread, total. |
| captured_at | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, openWorld, idempotent, and non-destructive behavior. The description adds valuable detail beyond that: no charge when splits are unavailable, upstream 400 errors for unsupported sports, and the bookmaker slug mapping convention relative to get_odds.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and front-loaded with the core purpose, followed by availability and fallback behavior. The first sentence is long with parentheticals, but every part earns its place; it could be slightly restructured for readability without losing content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with an output schema, the description is complete: it states what is returned, which sports are supported, when no data is available, and the billing behavior. No critical calling context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully covers the only required parameter, event_id, with guidance to source it from list_events, query_events, or search results. The description does not add extra parameter-level meaning beyond what the schema already provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Get public betting splits (bets% and handle%) for an event'. It clearly distinguishes the tool from siblings like get_odds by describing the exact data returned: consensus split, per-bookmaker breakdown, and captured_at timestamp.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context by listing supported sports (MLB, NBA, NHL, NFL, NCAAF, NCAAB) and explicitly stating tennis and soccer are not available. It also explains when the tool returns available:false, but it does not name an alternative tool or explicitly say when to prefer get_splits over get_odds.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_statsARead-onlyIdempotentInspect
Get raw, deterministic team/match statistics for a soccer, MLB, tennis, NFL, NCAAF, NBA, NCAAB, or NHL event — no odds (use get_odds) and no scoring (use get_intelligence). Payload is sport-specific: teams.home/away except tennis (players.player_1/player_2). Tennis doubles/qualifying return available:false. Form/record/H2H exclude walkovers and NFL/NCAAF/NBA/NCAAB preseason. Other sports return HTTP 400. Field catalog: https://lumify.ai/docs/reference#event-stats
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| match | No | Tennis only. Match context: surface, competition_id/name, tier, round (ingested labels like 'Round of 16'/'Quarterfinal'/'Final', not 'R16'), court (not currently populated), status, result_type, scoreboard (sets_won + per-set games; tiebreak_score not currently populated). |
| teams | No | Soccer/MLB/NFL/NCAAF/NBA/NCAAB/NHL only (home/away). Each side includes image_url (Lumify media URL, null until ingest; never a vendor CDN). Soccer: recent_form, team_strength, venue, rest_days, sos, lineup, rates_l5, rates_season. MLB: record, recent_form, rest_days, rates_l5/rates_season (incl. OBP/SLG/OPS/RBI/TB), starting_pitcher (post-box only), lineup, player_box (this event's per-player batting/pitching counting stats). NFL/NCAAF: record (points_for/against), recent_form (points_scored/allowed), rest_days, rates_l5/rates_season (total/passing/rushing yards, attempts, turnovers, third_down_pct), player_box (one players[] line per athlete with passing/rushing/receiving/defense/kicking counts; final only). NBA/NCAAB: record (points_for/against), recent_form (points_scored/allowed), rest_days, rates_l5/rates_season (rebounds/assists/steals/blocks/turnovers/fouls, fg_pct/three_point_pct/free_throw_pct as ratio-of-sums), player_box (points/rebounds/assists/…; final only). NHL: record (goals_for/against), recent_form (goals_scored/allowed), rest_days, rates_l5/rates_season (shots_on_goal/hits/penalty_minutes/power_play_goals/giveaways/takeaways/blocked_shots), player_box (skaters[] + goalies[]; assists/hits remapped from assists_nhl/hits_nhl; final only). Settleables stay on get_player_props. Absent on tennis responses — use players instead. |
| players | No | Tennis only (player_1/player_2). Each side: player_id, name, country_code, ranking, ranking_points, rest_days, recent_form, surface_form, record (tour_lookback wins/losses), career_rates (Stage-2 serve/return percentages; null until ingest), career_surface (Stage-2 match-surface W/L over windows.career_surface_years; null when empty). History windows exclude walkovers (unplayed) and include retirements. |
| profile | No | Soccer only. 'world_cup' or 'club'. |
| windows | No | Explicit sample depths. Soccer: recent_form (5), rates_l5 (5), rates_season ('season'), head_to_head (10), sos (5). MLB/NFL/NCAAF/NBA/NCAAB/NHL: recent_form (5), rates_l5 (5), rates_season ('season'), head_to_head (10). Tennis: recent_form (10), surface_form (10), head_to_head (10), record_lookback_days (365), career_surface_years (3). |
| event_id | No | Lumify event ID. |
| available | No | False when participants haven't resolved, or tennis draw_type is not exactly 'singles' (doubles/qualifying out of scope); every other field is omitted and the call isn't billed. |
| draw_type | No | Tennis only. Always 'singles' when available is true. Values other than 'singles' (including 'doubles' and 'qualifying') return available:false. |
| league_slug | No | League/tour slug, e.g. 'mls', 'mlb', 'nfl', 'atp', 'wta'. |
| head_to_head | No | Past meetings: {window, meetings, total}. Soccer: {home_goals, away_goals}. MLB: {home_runs, away_runs}. NFL/NCAAF/NBA/NCAAB: {home_points, away_points}. NHL: {home_goals, away_goals}. Tennis: {event_id, starts_at, surface, winner_role, sets_won} relative to this fixture's player_1/player_2 (walkovers excluded). |
| neutral_site | No | Soccer only. Whether this fixture is at a neutral venue. Informational here; factored into home-advantage scoring on get_intelligence. |
| league_context | No | Soccer only. {avg_goals_per_team}: league-wide baseline goals/team/game, used by get_intelligence's attack/defense scoring. Null for fixed-baseline competitions. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare safety (readOnly, openWorld, idempotent) but the description adds rich behavioral detail beyond them: sport-specific payload shape, tennis doubles/qualifying returning available:false, exclusions from form/record/H2H, and HTTP 400 behavior. This materially improves an agent's understanding of what to expect when calling the tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description packs critical usage information into three tightly written sentences, front-loading the core purpose and differentiating siblings first. Every sentence earns its place; there is zero fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, the description covers supported sports, payload structure, edge-case availability, statistical exclusions, and error handling. Combined with annotations and output schema, an agent has everything needed to invoke this tool correctly without additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, event_id, is fully described in the schema (coverage 100%) with a clear source and type. The description adds no extra parameter-level meaning, but the baseline of 3 applies because the schema already carries the necessary semantic weight.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Get'), a clear resource ('raw, deterministic team/match statistics'), and enumerates supported sports, explicitly distinguishing it from siblings by excluding odds and scoring. This makes the tool's purpose unmistakable and differentiates it from get_odds and get_intelligence.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool (raw statistics) and when not to, naming alternatives: 'no odds (use get_odds) and no scoring (use get_intelligence)'. It also provides error conditions (HTTP 400 for unsupported sports), leaving no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_teamARead-onlyIdempotentInspect
Get a single team profile with its home venue. Raises a not-found error if team_id doesn't exist. Resolve ids via list_teams.
| Name | Required | Description | Default |
|---|---|---|---|
| team_id | Yes | Team id, from list_teams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | No | |
| city | No | |
| name | No | |
| slug | No | |
| sport | No | |
| venue | No | |
| league | No | |
| division | No | |
| image_url | No | Lumify media URL for the team logo (https://lumify.ai/media/teams/{sport}/{id}.png). Null until ingest. Never a vendor CDN. |
| is_active | No | |
| conference | No | |
| abbreviation | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only, idempotent, non-destructive behavior. The description adds value by disclosing the not-found error behavior for invalid team_id, which the annotations do not cover, and notes the return includes home venue.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each carrying distinct information: purpose, error behavior, and id resolution. No filler or repetition of annotation fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one required parameter, a full output schema, and strong annotations, the description covers the essential call pattern and failure mode. Nothing needed to invoke correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents team_id as an id from list_teams, so the baseline is 3. The description adds meaning by warning that a nonexistent team_id triggers an error and reinforces the resolution path, going slightly beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'Get' with the resource 'single team profile' and adds 'with its home venue' to define scope. It contrasts with list_teams by indicating a single team, and the explicit mention of list_teams helps disambiguate from that sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a clear prerequisite sequence: resolve ids via list_teams before calling get_team. It implies use when a single team profile or home venue is needed, though it does not enumerate exclusions like team props or stats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_team_propsARead-onlyIdempotentInspect
Get team-total lines and live progress for an NFL, NCAAF, MLB, or soccer event. Joins persisted Pinnacle team-total mains (each team's full-game points/runs/goals Over/Under) to this-event participant scores and grades over/under/push. GET /odds / get_odds stay on moneyline/spread/total. Returns available:false with no charge if no team-total mains have been ingested. Other sports return HTTP 400.
| Name | Required | Description | Default |
|---|---|---|---|
| event_id | Yes | Event id, from list_events, query_events, or search results. |
Output Schema
| Name | Required | Description |
|---|---|---|
| clock | No | Game clock from the live score snapshot. |
| sport | No | Sport slug: nfl, ncaaf, mlb, or soccer. |
| period | No | Current period from the live score snapshot. |
| status | No | Event status (scheduled, inprogress, delayed, final, …). |
| event_id | No | Lumify event ID. |
| available | No | False when no team-total mains have been ingested; team_props is empty and the call isn't billed. |
| team_props | No | One row per (team, line). Fields: team, team_id, side (home/away), market (team_total), line, current (this-event team score), pct_of_line, settleable, result (in_progress / over / under / push, or null), books ({book_slug: {over, under}} American prices). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, and non-destructive behavior. The description adds meaningful operational context: joining persisted Pinnacle team-total mains to live scores, grading over/under/push, and no-charge behavior when data is unavailable. This goes well beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four tightly packed sentences with no filler. The main action is front-loaded, and every clause adds new information: supported sports, data join logic, sibling differentiation, and edge-case behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and only one well-documented parameter, the description covers all essential selection and invocation context. It includes sport restrictions, no-data behavior, and the relationship to get_odds, so nothing critical is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, event_id, is already fully described in the schema with sourcing guidance ('from list_events, query_events, or search results'). The description's supported-sport scope is useful but does not add parameter-level mechanics, so the high schema coverage baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource ('team-total lines and live progress') and scopes it to NFL, NCAAF, MLB, and soccer events. It explicitly contrasts with get_odds's moneyline/spread/total scope, so an agent can distinguish it from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states when to use this tool for team-total props and indicates that GET /odds and get_odds cover moneyline/spread/total instead. It also gives practical fallback/edge behavior: available:false with no charge when no team-total mains exist, and HTTP 400 for unsupported sports.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
grade_slipARead-onlyIdempotentInspect
Grade settleable player-prop legs (over / under / push / in_progress / dnp / no_stat) for NFL and MLB. Prefer structured event_id + player_id + market_key + line + side. Free text is interpreted with a rule-based parser and graded only when player and event resolve uniquely — never guesses an ambiguous name. A team span (CIN, vs Bills, Niners) is resolved first; unique team_id scopes the player, and ambiguous/not_found stays on team_resolve. Not live trading odds. Not wagering advice. Attribution is always Graded by Lumify.
| Name | Required | Description | Default |
|---|---|---|---|
| legs | No | ||
| text | No | Free-text slip (e.g. Chase over 74.5 receiving yards). A team span is resolved first; unique team_id scopes the player, and ambiguous/not_found stays on team_resolve. Graded only when player and event are unique. | |
| clues | No | Optional sport / league / event_id / team_id / team_text hints for free-text mode. |
Output Schema
| Name | Required | Description |
|---|---|---|
| legs | No | |
| status | No | graded | partial | pending | unmapped |
| honesty | No | |
| slip_id | No | |
| summary | No | |
| branding | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world), but the description adds substantive behavior: a rule-based parser, a resolve-first/never-guess stance, team-span resolution ordering, and the fixed 'Graded by Lumify' attribution. It does not mention the 8-leg cap or any rate/limit behavior, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then mode guidance, then resolution rules and disclaimers; every sentence carries information. The clipped fragments ('Not live trading odds. Not wagering advice.') are slightly terse but compactly purposeful rather than wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the description covers input modes, ambiguity handling, and attribution. The only meaningful omission is that the 8-leg cap and any server-side validation limits live solely in the schema, leaving an agent without narrative context on batch behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
At 67% schema coverage the description compensates by naming the canonical structured field set and explaining the free-text resolution path (team span first, unique team_id scopes player, else stay on team_resolve) plus the purpose of clues. This adds real meaning beyond the nested schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (grade) and resource (settleable player-prop legs), enumerates the outcome set (over/under/push/in_progress/dnp/no_stat), and scopes the sport space (NFL and MLB). It also distinguishes itself from neighbors like get_odds and get_player_props by declaring it is neither odds nor wagering advice.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear mode preference ('Prefer structured event_id + player_id + market_key + line + side') and explains when free-text mode applies and how ambiguity is handled ('ambiguous/not_found stays on team_resolve'). It does not name other grading alternatives, but for this tool the primary when-to-use decision (structured vs free text) is covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_evARead-onlyIdempotentInspect
Beta. List pregame main-line +EV opportunities for a predictive-framework sport (soccer, mlb, tennis, nfl, ncaaf), sorted by ev_pct descending. market=h2h (default, moneyline), spreads, or totals. Tennis totals are not offered (Stage 1 is moneyline + spreads). Same gates as bets[].ev on get_intelligence: sharp-fair price gap, positive and ≤25%, suppressed MLB moneyline null books skipped in favor of the next eligible book. 1 credit. Field catalog: https://lumify.ai/docs/reference#intelligence-ev
| Name | Required | Description | Default |
|---|---|---|---|
| book | No | Restrict opportunities to one sportsbook slug (e.g. fanduel). | |
| limit | No | Max opportunities to return (1–200). Default 50. | |
| sport | Yes | Sport slug: soccer, mlb, tennis, nfl, or ncaaf. | |
| league | No | Optional league slug (mls, epl, atp, …). Soccer without a league scans every published soccer league (MLS + big-five). | |
| market | No | Main-line family: h2h (default, moneyline), spreads, or totals. Tennis + totals returns 400. | |
| min_ev | No | Minimum EV% to include. Default 0. Clamped to 0–25. |
Output Schema
| Name | Required | Description |
|---|---|---|
| beta | No | Always true. |
| book | No | Book filter, or null. |
| sport | No | Sport slug this scan was run for. |
| total | No | Count of opportunities on this page. |
| league | No | League filter, or null for the whole sport. |
| market | No | h2h, spreads, or totals — the family scanned. |
| max_ev | No | Stale-line cap (25). |
| min_ev | No | Minimum EV% applied. |
| opportunities | No | Positive-EV main-line rows: {event_id, sport, league, commence_time, home_team, away_team, side, team, bet_type, line, fair_probability, ev}. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnly, idempotent, and non-destructive behavior. The description adds substantial context beyond that: the tool costs 1 credit, is in Beta, sorts by ev_pct, suppresses MLB moneyline null books, skips to the next eligible book, applies sharp-fair price gates, and returns 400 for tennis totals.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-organized, front-loading the core purpose and then adding constraints, gates, cost, and a reference link. Every sentence earns its place; there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description does not need to explain return values. It covers supported sports, market families, default behavior, edge cases, EV gates, cost, and links to the full field catalog, making it fully actionable for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description goes beyond the schema by explaining the market default, the tennis totals 400 error, the MLB null-book behavior, and the soccer league scanning behavior, adding useful semantics for parameter selection.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists pregame main-line +EV opportunities, names the supported sports, and specifies sorting by ev_pct descending. It also differentiates the tool from siblings by mentioning market families and the tennis totals exclusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when to use the tool: it is for pregame +EV opportunities, not live events, and it specifies market defaults and unsupported combinations. It references get_intelligence for the shared EV gates, which helps an agent relate the tool to a sibling, though it does not explicitly say 'use this instead of X'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_eventsARead-onlyIdempotentInspect
List events (schedules and live scores), paginated by id (after_id). Filter by sport, league, status, date range, season, or team_id (resolve teams via list_teams / get_team). Returns event id, name, sport/league, start time, status, and venue for each; pass include_scores to also inline participants + scores (intended for small result sets — use get_event for one event's full detail, or query_events for free-text/natural-language filters instead of structured params). include_scores shares the 20/min score-poll budget with get_live_score; prefer the SSE stream for live boards.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | UTC end date YYYY-MM-DD (inclusive). | |
| date | No | UTC date YYYY-MM-DD (single day). | |
| from | No | UTC start date YYYY-MM-DD. | |
| sort | No | Sort order. sort=status is incompatible with after_id. | time |
| limit | No | Max events to return per page. | |
| sport | No | Sport slug, e.g. mlb, nfl, tennis, soccer. | |
| league | No | League slug, e.g. nfl, atp, mls. | |
| status | No | Filter to events in this status. | |
| team_id | No | Filter to events where this team participates. Resolve ids via list_teams. | |
| after_id | No | Cursor: return events with id > after_id (from the previous page's next_after_id). | |
| season_id | No | Filter by season ID (from list_seasons). | |
| has_recommend | No | When true, only events with at least one recommended bet. | |
| include_scores | No | Inline participants + scores in each event (intended for small result sets). Shares the 20/min score-poll budget with get_live_score. |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | No | |
| events | No | |
| next_after_id | No | Pass as after_id to fetch the next page; null on the last page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), but the description adds genuinely non-structured behavior: include_scores shares the 20/min score-poll budget with get_live_score and is intended only for small result sets. It also discloses cursor pagination via next_after_id. It stops short of describing pagination edge cases or failure behavior, so a 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the core purpose and pagination lead, then filtering, then the routing caveats. Nearly every clause carries information, though the long parenthetical about include_scores/query_events/get_event is syntactically sprawling and could be split for scanability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 13-parameter filtering tool with an output schema, the description covers purpose, pagination, filtering dimensions, alternatives, and a rate-limit caveat. Return values are already handled by the output schema, so nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 13 parameters are already documented in the schema, including the sort/after_id incompatibility. The description restates which filters exist and the include_scores cost, but adds no syntax or format detail beyond the schema. Baseline 3 applies when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List events (schedules and live scores)') and immediately scopes what is returned. It distinguishes itself from siblings by naming get_event for single-event detail and query_events for free-text filtering. An agent can pick this tool without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing: use get_event for one event's full detail, query_events for natural-language filters instead of structured params, list_teams/get_team to resolve team_id, and the SSE stream for live boards. This is when-to-use plus named alternatives, exceeding the bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_forecastsARead-onlyIdempotentInspect
Daily board of forecasted wagers from Lumify's model — a prediction, not a beat-the-market claim (no OOS/independence gate; see list_ev for the gated main-line +EV claim). Player props (rate model) on MLB, NCAAF, NFL, NBA, NCAAB, NHL. Tennis main-line: moneyline (ranking Bradley-Terry) as bet_type ML_P1/ML_P2, game handicap as SPREAD_P1/SPREAD_P2, and total games as OVER/UNDER (a Normal-approx games model; soft-book game-unit lines only, never Pinnacle's set-unit total). Each wager has p_hit, conviction (|p_hit−0.5|×2×sufficiency×research), and posted books prices. Use list_ev to scan main lines by sharp-fair price gap; use this tool to scan high-probability forecasts. reliability is emerging on v0. 1 credit; empty slate is still 200. How + field catalog: https://lumify.ai/docs/forecasts Worked wager: https://lumify.ai/docs/understanding-odds#forecasts
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | UTC slate date YYYY-MM-DD. Defaults to today UTC. | |
| limit | No | Max wagers (1–100). Default 25. | |
| sport | Yes | Sport slug: mlb, ncaaf, nfl, nba, ncaab, nhl, or tennis. | |
| market | No | Main-line family filter (h2h, spreads, or totals). Tennis publishes all three (moneyline, game-handicap, total-games). Ignored on prop-only sports. |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | No | UTC slate date (YYYY-MM-DD). |
| sport | No | Sport slug this slate was scored for. |
| total | No | Count of wagers on this page. |
| wagers | No | Selected forecasted wagers, highest conviction first. Read p_hit as P(the picked outcome — side on prop rows, bet_type on main-line rows — hits); conviction is the board rank. How + field catalog: https://lumify.ai/docs/forecasts |
| reliability | No | Default badge on this slate. v0 ships emerging; each wager repeats the same field. |
| model_version | No | Scorer version (forecast-v0). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds critical behavioral context: it's a prediction with no OOS/independence gate, notes 'reliability is emerging on v0,' discloses credit cost (1 credit), and mentions 'empty slate is still 200' (returns 200 even with no forecasts). It also describes the output fields (p_hit, conviction, posted books prices). No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence contributes essential information. It is front-loaded with the core purpose and the caveat about not being a beat-the-market claim, then details sports, bet types, fields, usage guidance, and links. While verbose, it avoids redundancy and fluff, justifying its length for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description doesn't need to detail return structures, yet it still mentions key fields. It covers the tool's scope, limitations, usage distinction, parameter nuances, credit cost, and even provides documentation links. For an agent, everything needed to decide when to call and how to call it is included.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for all 4 parameters, so the baseline is 3. The description adds extra meaning: it clarifies the market parameter is 'Ignored on prop-only sports,' notes tennis publishes all three main-line families, and provides the sport slug list. It also specifies date defaults to today UTC and limit defaults to 25, reinforcing the schema. This exceeds the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists daily forecasted wagers from Lumify's model, specifying it is a prediction rather than a beat-the-market claim. It distinguishes itself from sibling list_ev by noting list_ev is for gated +EV claims, while this tool scans high-probability forecasts. It also enumerates the sports and bet types covered, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given: 'Use list_ev to scan main lines by sharp-fair price gap; use this tool to scan high-probability forecasts.' It also directs to list_ev for the gated main-line +EV claim, providing clear when-to-use vs. alternative. No exclusions are left unstated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_seasonsARead-onlyIdempotentInspect
List seasons per sport/league. By default returns only currently active seasons; pass current_only=false to include historical seasons. Optionally filter by sport. Returns each season's id, year, phase, start/end dates, and whether it is_current. Use list_sports for just each sport's current season.
| Name | Required | Description | Default |
|---|---|---|---|
| sport | No | Filter by sport slug, e.g. nhl, nba, soccer. | |
| current_only | No | Return only currently active seasons (default true). Pass false for historical seasons. |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | No | |
| seasons | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (read-only, idempotent, non-destructive), and the description adds meaningful behavior: default active-only filtering, optional historical inclusion, and return field details. It does not contradict annotations and provides useful context beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with the core purpose, then defaults, return fields, and an alternative. Every sentence earns its place with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only list tool with an output schema and full annotations, the description fully covers defaults, filtering, and alternatives. There are no meaningful gaps for selection or invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description mirrors the schema's current_only and sport semantics without adding new parameter-level details, but it does reinforce them in natural language.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'List' with a clear resource 'seasons' and scope 'per sport/league'. It explicitly distinguishes itself from the sibling list_sports by directing users there for just current-season info.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states the default behavior (only active seasons), how to opt into historical seasons (current_only=false), optional sport filtering, and explicitly names list_sports as an alternative when simpler data suffices. This provides clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sportsARead-onlyIdempotentInspect
List supported sports with their leagues and current season. Returns each sport's id, slug, name, team-sport flag, and its leagues (each with its current_season). Use list_seasons with current_only=false for historical seasons.
| Name | Required | Description | Default |
|---|---|---|---|
| active_only | No | When true (default), omit sports with no active coverage. |
Output Schema
| Name | Required | Description |
|---|---|---|
| total | No | |
| sports | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and non-destructive behavior. The description adds useful context about the returned data structure (sport id, slug, name, team-sport flag, leagues with current_season) that is not redundant with the output schema, and it clarifies the tool's scope beyond the hints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: the first leads with the action and key outcome, the second details return fields and the alternative for historical data. Every sentence earns its place with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single optional parameter, rich annotations, and presence of an output schema, the description fully covers the tool's purpose, return shape, and related tool guidance. No important gaps remain for a simple list operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides a full description for active_only (100% coverage), so the schema does the heavy lifting. The description does not add additional parameter meaning beyond what is in the schema, meeting the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists supported sports with their leagues and current season, naming the exact fields returned. It distinguishes from sibling tools by explicitly pointing to list_seasons for historical seasons, and the scope (sports vs teams/events) is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance to use list_seasons with current_only=false for historical seasons, which is a clear alternative. Does not enumerate all when-not-to-use scenarios, but the primary use case is evident and the alternative is well-targeted.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_teamsARead-onlyIdempotentInspect
List teams, paginated by id (after_id). Filter by sport, league, conference, division, country, active status, or name (q, partial match). Returns each team's id, slug, name, city, conference/division, venue, and image_url (Lumify media URL, null until ingest). Use get_team for full detail on one id once resolved here.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Team name search (partial match). | |
| limit | No | Max teams to return per page. | |
| sport | No | Sport slug, e.g. nfl, nba, soccer. | |
| active | No | Filter by active status. | |
| league | No | League slug, e.g. nfl, mls. | |
| country | No | ISO country code, e.g. USA. | |
| after_id | No | Cursor: last team id from the previous page's next_after_id. | |
| division | No | Division name, e.g. AFC East. | |
| conference | No | Conference name, e.g. AFC, Eastern. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | |
| has_more | No | |
| next_after_id | No | Pass as after_id to fetch the next page; null on the last page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, so the description only needs to add extra context. It adds useful behavioral details: pagination is driven by after_id, results are a summary set, and image_url is null until ingest.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no filler; the main action and pagination are front-loaded, followed by filters, return fields, and the sibling-tool handoff. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a list endpoint with an output schema and annotations covering safety and idempotency, the description covers how to paginate, what filters exist, what fields come back, and how to get full detail afterwards. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all nine optional parameters. The description mostly restates the filter categories and cursor semantics rather than adding new parameter-level meaning, which is adequate but not additive.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (List teams), names the pagination mechanism, enumerates filters, and specifies the returned fields. It also distinguishes itself from get_team, so an agent can tell the two apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context for when to use this tool: resolve a team id here, then call get_team for full detail. This explicit routing to a sibling tool eliminates ambiguity about the boundary between list and detail operations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
query_eventsARead-onlyIdempotentInspect
Search events with a natural-language query instead of structured filters — e.g. 'live nfl games today' or 'college basketball this week'. Rule-based (not an LLM): recognizes sport (nfl/nba/mlb/nhl/tennis/soccer/ncaaf/ncaab + aliases like hockey, american football, college basketball), status (live/final/upcoming/…), dates (today/tomorrow, this week, next N days, YYYY-MM-DD ranges). Bare 'football' is ambiguous and left unrecognized. Response includes interpreted filters, equivalent REST call, and unrecognized_terms. Prefer list_events when you already know the structured filters you want.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Overrides any limit parsed from the query text. Max 100. | |
| query | Yes | Free text, e.g. 'live nfl games today'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | No | The original natural-language query text. |
| total | No | |
| events | No | |
| interpreted | No | The list_events-equivalent filters parsed from the query text (sport, status, date, from, to, limit). |
| next_after_id | No | |
| equivalent_request | No | The literal GET /v1/events request this query was translated to. |
| unrecognized_terms | No | Query words that didn't map to a known filter. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (read-only, idempotent, non-destructive), the description adds critical behavioral details: it is rule-based not an LLM, specific language features are recognized, bare 'football' is ambiguous and left unrecognized, and the response includes interpreted filters, equivalent REST call, and unrecognized_terms.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence contributes useful information. It opens with the primary purpose, provides illustrative examples, explains internal behavior, and closes with usage guidance—all without fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's natural-language processing complexity, the description thoroughly covers usage scope, behavioral limitations, and response contents. The output schema handles return values, so no additional detail is needed there. The description is comprehensive for an AI agent to decide when and how to invoke it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema documents both parameters, the description enriches the 'query' parameter by detailing supported sports, statuses, date formats, and the ambiguity behavior. It also clarifies the 'limit' parameter's override semantics, adding value beyond the schema fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: search events using natural-language queries instead of structured filters. It provides concrete examples and explicitly distinguishes it from sibling tools like list_events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit guidance on when to use this tool versus the alternative, stating 'Prefer list_events when you already know the structured filters you want.' This directly addresses tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_playerARead-onlyIdempotentInspect
Resolve messy sports player names to a Lumify player_id using sport, team, or event clues. Prefer this before grade_slip when the name is a fragment, initial, or nickname. Returns ambiguous instead of guessing — never auto-pick candidates[0]. Does not grade props.
| Name | Required | Description | Default |
|---|---|---|---|
| clues | No | Optional sport, team, event, or position clues. | |
| query | Yes | Messy player name or fragment, e.g. J. Chase. | |
| options | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| sport | No | |
| status | No | resolved | ambiguous | not_found | error |
| message | No | |
| team_id | No | |
| player_id | No | |
| candidates | No | |
| clues_used | No | |
| confidence | No | |
| display_name | No | |
| match_reasons | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive safety, so the bar is lower. The description still adds real behavioral value: it guarantees 'Returns ambiguous instead of guessing — never auto-pick candidates[0]' and scopes itself with 'Does not grade props,' which is exactly the kind of tie-breaking behavior an agent needs beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, each earning its place: purpose, usage routing, ambiguity behavior, and scope exclusion, with the core action front-loaded. No filler or repetition of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return formatting needn't be explained, and the description covers the key ambiguity-handling behavior for a resolver. It stops just short of describing the options semantics (strict/permissive/ingest modes), which would help an agent choose parameters for a fuzzy-matching tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 67% with nested clue/option objects, so the schema carries most of the load. The description only mentions that sport/team/event clues exist, adding little detail on the clues object or the options (mode, max_candidates, min_confidence) beyond what the schema already documents. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Resolve messy sports player names') and the concrete outcome ('to a Lumify player_id'), plus the clue types it consumes. It also distinguishes itself from siblings (grade_slip, search_players/get_player) by framing the task as normalization rather than search or grading.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Prefer this before grade_slip when the name is a fragment, initial, or nickname' gives an explicit trigger and a named alternative. However, it doesn't address the other plausibly overlapping siblings (search_players, get_player, resolve_team), so the routing guidance is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_teamARead-onlyIdempotentInspect
Resolve messy team names, abbreviations, metros, or aliases to a Lumify team_id using sport, league, event, or player clues. Prefer this before list_teams when the string is a nickname or city token. Returns ambiguous instead of guessing — never auto-pick candidates[0]. City-only metros sit below the auto-resolve floor.
| Name | Required | Description | Default |
|---|---|---|---|
| clues | No | Optional sport, league, event, player, or team-id clues. | |
| query | No | Team string, e.g. Niners, CIN, NY Giants. | |
| options | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| sport | No | |
| league | No | |
| method | No | |
| status | No | resolved | ambiguous | not_found | error |
| message | No | |
| team_id | No | |
| candidates | No | |
| clues_used | No | |
| confidence | No | |
| abbreviation | No | |
| display_name | No | |
| match_reasons | No | |
| sport_conflict | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, open-world, non-destructive. The description adds genuinely new behavioral detail: it returns ambiguous rather than guessing, never auto-picks candidates[0], and city-only metros fall below the auto-resolve floor. It doesn't discuss the confidence scoring model or pagination limits, but the ambiguity contract is a meaningful addition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, zero filler, with the primary purpose front-loaded and routing/behavioral caveats following. Every sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return-value structure need not be explained, and the description still covers the key ambiguity/return contract. Minor gaps remain around confidence semantics and what the candidate list contains, but overall complete for a resolver tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 67% and the description adds meaning to the resolution behavior tied to min_confidence ('city-only metros sit below the auto-resolve floor'), which clarifies the otherwise undocumented options.min_confidence parameter. The clues and query params are already described in the schema, so this compensates appropriately without redundancy.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Resolve) and resource (messy team names, abbreviations, metros, aliases) and names the output artifact (Lumify team_id). It explicitly distinguishes itself from the sibling list_teams, so an agent can route without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use guidance ('Prefer this before list_teams when the string is a nickname or city token'), naming the alternative and the condition that selects it. The rule about not auto-picking candidates[0] further constrains how the caller should behave on ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_playersARead-onlyIdempotentInspect
Search players by name, sport, country, ranking, or active status, paginated by id (after_id). Returns the same identity object on every sport (null means unknown, not wrong sport). Tennis standings nest under rankings.{singles, points}; rankings is null on every other sport. Use get_player for full detail on one id, or get_player_events for a player's schedule/results.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Name search (partial match). | |
| limit | No | Max players to return per page. | |
| sport | No | Sport slug, e.g. tennis, nba. | |
| active | No | Filter by active status. | |
| ranked | No | If true, only tennis players with an ATP/WTA singles ranking (rankings.singles). | |
| country | No | ISO 3166-1 alpha-3 country code, e.g. USA. | |
| after_id | No | Cursor: last player id from the previous page's next_after_id. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | |
| has_more | No | |
| next_after_id | No | Pass as after_id to fetch the next page; null on the last page. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as readOnly, openWorld, idempotent, and non-destructive, so the bar is lower. The description adds valuable behavioral context: the identity object is the same across sports with null meaning unknown, not wrong sport, and that rankings only nests under tennis while being null elsewhere. This goes beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. The main action and filters are front-loaded in the first sentence, behavior notes in the second, and routing to alternatives in the third. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover the safety profile, the description covers the remaining important context: null/unknown semantics, sport-specific rankings shape, and the relationship to sibling tools. Nothing critical is missing for an agent to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description reinforces the role of parameters like sport, country, ranking, and after_id, and clarifies pagination via id, but it does not significantly deepen the semantics beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Search players by name, sport, country, ranking, or active status, paginated by id (after_id).' It clearly identifies the action, the target, and the available filters, and distinguishes itself from get_player and get_player_events by naming them as alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use alternatives: 'Use get_player for full detail on one id, or get_player_events for a player's schedule/results.' It also provides pagination context with after_id and next_after_id, making the usage conditions clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
- Added
grade_slip - Changed
list_events1 field changed- changed
Input schema / properties / include_scores / descriptionPrevious value: -"Inline participants + scores in each event (intended for small result sets)."New value: +"Inline participants + scores in each event (intended for small result sets). Shares the 20/min score-poll budget with get_live_score."
- Added
resolve_player - Added
resolve_team
24 tool updates
- Added
batch_get_events - Added
estimate_cost - Changed
get_event5 fields changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds; defaults to pinnacle, 'all' for every book."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all." - added
Input schema / properties / event_id / descriptionAdded value: +"Event id, from list_events, query_events, or search results." - changed
Input schema / properties / include_intelligence / descriptionPrevious value: -"Inline bet intelligence (+1 credit when available)."New value: +"Inline bet intelligence. Does not add credits." - changed
Input schema / properties / include_odds / descriptionPrevious value: -"Inline current odds (+1 credit when odds are available)."New value: +"Inline current odds scoped by bookmaker (default: pinnacle). Does not add credits — the event call stays 1 credit." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "id": { + "type": "integer" + }, + "inprogress_since": { + "description": "ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final.", + "type": [ + "string", + "null" + ] + }, + "league": { + "type": "string" + }, + "name": { + "type": "string" + }, + "participants": { + "items": { + "properties": { + "is_winner": { + "type": [ + "boolean", + "null" + ] + }, + "participant_id": { + "type": "integer" + }, + "player": { + "type": [ + "object", + "null" + ] + }, + "role": { + "type": "string" + }, + "score": { + "type": [ + "string", + "null" + ] + }, + "team": { + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "sport": { + "type": "string" + }, + "starts_at": { + "type": "string" + }, + "status": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + }, + "venue": { + "type": [ + "object", + "null" + ] + } + }, + "type": "object" +}
- Added
get_injuries - Changed
get_intelligence3 fields changed- added
Input schema / properties / bookmaker / descriptionAdded value: +"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada." - added
Input schema / properties / event_id / descriptionAdded value: +"Event id, from list_events, query_events, or search results." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "available": { + "description": "False when no predictive bets[] have been computed for this event yet. forecasts[] can still populate on MLB/NFL/NCAAF/NBA/NCAAB/NHL. Free only when available is false and forecasts is empty.", + "type": "boolean" + }, + "bets": { + "items": { + "properties": { + "alignment": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "type": [ + "object", + "null" + ] + }, + "attribution": { + "description": "Not published.", + "items": { + "type": "string" + }, + "type": "array" + }, + "best": { + "description": "Highest price-gap book across edges_by_book: {book, price, edge, quote_age_seconds}. Tier C informational line-shopping.", + "type": [ + "object", + "null" + ] + }, + "bet_type": { + "description": "Canonical bet token, e.g. ML_HOME/ML_AWAY/ML_DRAW (soccer), ML_P1/ML_P2 (head-to-head sports), SPREAD_HOME/SPREAD_AWAY, OVER, UNDER.", + "type": "string" + }, + "blend_w": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "type": [ + "number", + "null" + ] + }, + "computed_at": { + "description": "ISO-8601 UTC time this bet's numbers last materially changed — not when last checked. Rows are only rewritten when price, line, or probability moves beyond a tolerance, so an older value means 'unchanged since', not 'stale'. Differs between bets on one event because markets move independently.", + "type": [ + "string", + "null" + ] + }, + "confidence_score": { + "description": "Not published. Use probability.", + "type": [ + "number", + "null" + ] + }, + "coverage": { + "description": "Not published.", + "type": [ + "number", + "null" + ] + }, + "drivers": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "items": { + "type": "object" + }, + "type": "array" + }, + "edge": { + "description": "Expected profit per 1 unit staked at market.price. Null while no model-backed edge is published (Stage 1). Present on customer surface for recommend gating.", + "type": [ + "number", + "null" + ] + }, + "edges_by_book": { + "description": "Price gap versus fair.probability per soft book (fair.probability × decimal_odds − 1). Line-shopping metric: rank soft books by gap.", + "type": [ + "object", + "null" + ] + }, + "ev": { + "description": "Beta. Customer-facing EV estimate: {beta: true, book, price, ev_pct, kelly_fraction, quote_age_seconds, n_books}. Re-packages the same fair price gap for direct display. Moneyline only. n=1 Pinnacle is a valid fair (soccer/tennis). Null when the gap is ≤0, above 25% (stale-line), or only suppressed books remain (MLB ML × DK/FD proven null; BetMGM/Bet365/BetOnline unscreened).", + "type": [ + "object", + "null" + ] + }, + "fair": { + "description": "Sharp-consensus fair: {probability, books, n_books, is_consensus}. MLB/NFL: Pinnacle+Circa; MLS/tennis: Pinnacle. Price-gap reference for edges_by_book/best.", + "type": [ + "object", + "null" + ] + }, + "fair_price": { + "description": "American-odds fair price implied by probability — the vig-free line. Compare to market.price for the book's margin on this side.", + "type": [ + "integer", + "null" + ] + }, + "interval": { + "description": "[lo, hi] band around probability — how much evidence backs the number, not a statistical confidence interval.", + "items": { + "type": "number" + }, + "type": [ + "array", + "null" + ] + }, + "market": { + "description": "Market quote: {price: American odds, line: handicap/total line or null for moneyline, book: bookmaker slug when known (always set for probability-model sports)}.", + "type": [ + "object", + "null" + ] + }, + "model_version": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "type": [ + "string", + "null" + ] + }, + "narrative": { + "description": "Not published.", + "type": [ + "string", + "null" + ] + }, + "p_market": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis). Use probability/fair_price.", + "type": [ + "number", + "null" + ] + }, + "p_model": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "type": [ + "number", + "null" + ] + }, + "phase": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "type": [ + "string", + "null" + ] + }, + "player_id": { + "description": "Set when this bet is about an individual player. Null for team bets and match-level tokens.", + "type": [ + "integer", + "null" + ] + }, + "player_name": { + "description": "Display name of the player or team this bet is about. Null for match-level tokens. Duplicates players[player_role].name.", + "type": [ + "string", + "null" + ] + }, + "player_role": { + "description": "'home'/'away' or 'p1'/'p2'. Null for match-level tokens (OVER, UNDER, ML_DRAW).", + "type": [ + "string", + "null" + ] + }, + "probability": { + "description": "Published probability for this outcome, 0-1. Outcomes of one market sum to 1. Customer surface for MLB, soccer, tennis, NFL.", + "type": [ + "number", + "null" + ] + }, + "rationale": { + "description": "Not published. Top-level rationale is the event-level context overlay.", + "items": { + "type": "string" + }, + "type": "array" + }, + "signals": { + "description": "Not published.", + "type": [ + "object", + "null" + ] + }, + "sufficiency": { + "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", + "type": [ + "number", + "null" + ] + }, + "team_id": { + "description": "Set when this bet is about a team. Null for match-level tokens (OVER, UNDER, ML_DRAW) — a draw is not a bet on either team, so summing exposure by team_id never double-counts it.", + "type": [ + "integer", + "null" + ] + }, + "tier": { + "description": "Confidence tier: 'very_high', 'strong', 'moderate', or 'avoid'. Null whenever edge is null. Present on MLB customer surface and all other shapes.", + "type": [ + "string", + "null" + ] + }, + "validator": { + "description": "Not published.", + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "event_id": { + "description": "Lumify event ID this intelligence describes.", + "type": "integer" + }, + "forecasts": { + "description": "Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows on team sports; tennis main-line via bet_type ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), OVER/UNDER (total games). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts", + "items": { + "properties": { + "away_team": { + "description": "Away team display name. Slate only.", + "type": [ + "string", + "null" + ] + }, + "bet_type": { + "description": "Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis sets ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), and OVER/UNDER (total games).", + "type": [ + "string", + "null" + ] + }, + "books": { + "description": "American price for the picked outcome, keyed by bookmaker slug (e.g. {draftkings: -453}). Posted market price for the side/bet_type the model picked.", + "type": "object" + }, + "commence_time": { + "description": "ISO-8601 UTC scheduled start. Slate only.", + "type": [ + "string", + "null" + ] + }, + "conviction": { + "description": "Board rank key on 0–1: |p_hit−0.5|×2×sufficiency×research. A high p_hit on a thin sample ranks below a moderate p_hit on a long one. Highest conviction first on the daily slate.", + "type": "number" + }, + "drivers": { + "description": "Signed contributions that moved p_hit. Read input as the measured rate/rating behind the pick and effect as how far it lifts the chosen outcome versus a baseline.", + "items": { + "properties": { + "direction": { + "description": "up / down / neutral from the sign of effect.", + "type": "string" + }, + "effect": { + "description": "Signed shift in p_hit versus a baseline case on the same line. 0.0 on yardage markets.", + "type": "number" + }, + "id": { + "description": "Prop rows: typically player.l10_rate — the recent-form rate that fed Poisson. Main-line rows would use a different namespace once a main-line forecast model ships.", + "type": "string" + }, + "input": { + "description": "Measured rate/rating behind this driver, in native units.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "event_id": { + "description": "Lumify event ID. Present on list_forecasts; omitted on get_intelligence.forecasts (the event is the argument).", + "type": [ + "integer", + "null" + ] + }, + "home_team": { + "description": "Home team display name. Slate only.", + "type": [ + "string", + "null" + ] + }, + "interval": { + "description": "[lo, hi] stated band around p_hit. Wider when sufficiency is low. A stated evidence band, not a statistical confidence interval.", + "items": { + "type": "number" + }, + "type": "array" + }, + "league": { + "description": "League slug, if any. Slate only.", + "type": [ + "string", + "null" + ] + }, + "line": { + "description": "Posted line the model was scored against. Prop and totals main-line rows: Over/Under number. Spreads main-line rows: the spread number. Null on h2h/moneyline rows.", + "type": [ + "number", + "null" + ] + }, + "market": { + "description": "Player-prop rows: prop category (counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions, passing_tds, rushing_tds, touchdowns (anytime-TD combo: rushing + receiving + defensive TDs). NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals.", + "type": "string" + }, + "model_version": { + "description": "Scorer version, e.g. forecast-v0.", + "type": "string" + }, + "p_hit": { + "description": "Model probability (0–1) that the picked outcome (side on prop rows, bet_type on main-line rows) hits. Prop rows: built from the player's shrunken counting-stat rate (Poisson vs the posted Over/Under). Optional research may nudge a prop's p_hit by at most ±0.03; the chosen side stays the same.", + "type": "number" + }, + "player": { + "description": "Player display name from the priced line. Null on main-line rows with no player attribution (bet_type is a match-level token like OVER/UNDER/ML_DRAW).", + "type": [ + "string", + "null" + ] + }, + "player_id": { + "description": "Lumify player ID. Bound by exact / Jr-stripped name match. Null on main-line rows with no player attribution.", + "type": [ + "integer", + "null" + ] + }, + "player_role": { + "description": "'home'/'away' for team sports or 'p1'/'p2' for head-to-head sports, set only alongside a non-null bet_type. Null for player-prop rows and for match-level main-line tokens (OVER, UNDER, ML_DRAW).", + "type": [ + "string", + "null" + ] + }, + "reliability": { + "description": "Badge on this sport×market cell: emerging, moderate, high, or informational. v0 ships emerging for every wager.", + "type": "string" + }, + "research": { + "description": "Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction. Invalidate drops the wager from forecasts[] and the daily board — it is not a recommended pick. The chosen side stays. Null means read p_hit from the rate model alone.", + "type": [ + "object", + "null" + ] + }, + "selected": { + "description": "True when this wager is on the daily board (top conviction). On get_intelligence the array includes selected and the rest of the event catalog.", + "type": "boolean" + }, + "side": { + "description": "Prop rows: 'over' or 'under' — the more likely side given the player's shrunken rate versus line. Null on main-line rows — read the picked outcome from bet_type instead.", + "type": [ + "string", + "null" + ] + }, + "sport": { + "description": "Sport slug. Slate only.", + "type": [ + "string", + "null" + ] + }, + "sufficiency": { + "description": "Evidence weight on 0–1: n/(n+12), where n is the recent-form game count (typically L10). A player with 10 games has sufficiency ≈ 0.45. The wager still ships; this field tells you how much of p_hit is earned from this player's own boxes.", + "type": "number" + } + }, + "type": "object" + }, + "type": "array" + }, + "has_recommend": { + "description": "True when at least one bet meets the recommendation threshold; null when intelligence has not been computed. False while Edge is not published (current MLB/soccer/tennis Stage 1) — a recommendation requires a non-null tier derived from edge.", + "type": [ + "boolean", + "null" + ] + }, + "intelligence_updated_at": { + "description": "ISO-8601 UTC timestamp of the most recent change anywhere in this payload (max of per-bet computed_at). Use per-bet computed_at to reason about a specific bet.", + "type": [ + "string", + "null" + ] + }, + "league": { + "description": "League slug for this event, if any.", + "type": [ + "string", + "null" + ] + }, + "match_overview": { + "description": "Natural-language pre-game matchup preview — form, context, what to watch. Written before kickoff by a Search-backed overlay on every event sport (MLB, NFL, NCAAF, NBA, NCAAB, NHL, soccer, tennis); sport-shaped queries. The request path only reads the stored row. Null when the pre-kickoff job has not run or the fixture was not eligible.", + "type": [ + "string", + "null" + ] + }, + "matchup": { + "description": "Not returned. Use get_stats for pitcher/lineup Data.", + "type": [ + "object", + "null" + ] + }, + "odds_source": { + "description": "Bookmaker bets[].market prices were sourced from. For probability-model sports this is the book the assessment was priced against, not a bookmaker overlay; per-bet market.book is authoritative if they ever differ.", + "type": [ + "string", + "null" + ] + }, + "players": { + "description": "Home/away (or p1/p2) participant identification, keyed by role: {role: {name, player_id, team_id}}.", + "type": "object" + }, + "rationale": { + "description": "Event-level factual pre-game matchup chips (injuries, recent form, lineup/availability news — sport-shaped). Written before kickoff; the request path only reads the stored row.", + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "sport": { + "description": "Sport slug for this event.", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_live_score2 fields changed- added
Input schema / properties / event_id / descriptionAdded value: +"Event id, from list_events, query_events, or search results." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "clock": { + "type": [ + "string", + "null" + ] + }, + "event_id": { + "type": "integer" + }, + "finished": { + "type": "boolean" + }, + "period": { + "type": [ + "string", + "null" + ] + }, + "scores": { + "items": { + "properties": { + "abbreviation": { + "type": [ + "string", + "null" + ] + }, + "is_winner": { + "type": [ + "boolean", + "null" + ] + }, + "name": { + "type": "string" + }, + "period_scores": { + "items": { + "type": "object" + }, + "type": "array" + }, + "role": { + "type": "string" + }, + "score": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "status": { + "type": "string" + }, + "updated_at": { + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_odds4 fields changed- added
Input schema / properties / bookmaker / descriptionAdded value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list." - added
Input schema / properties / event_id / descriptionAdded value: +"Event id, from list_events, query_events, or search results." - added
Input schema / properties / include_altsAdded value: +{ + "description": "Include alternate spread/total rungs. Default false (mains only).", + "type": "boolean" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "available": { + "type": "boolean" + }, + "bookmakers": { + "description": "Per-book markets. Outcomes include is_main. In-play omits books that have not quoted since kickoff. Final events add result (won/lost/push/void) and close on the pre-kickoff point.", + "items": { + "type": "object" + }, + "type": "array" + }, + "event_id": { + "type": "integer" + }, + "fallback_bookmaker": { + "description": "The book actually returned when requested_bookmaker is present.", + "type": "string" + }, + "last_updated": { + "type": [ + "string", + "null" + ] + }, + "requested_bookmaker": { + "description": "Present only when the default (no bookmaker arg) request fell back to a different book because Pinnacle has no line yet — always 'pinnacle' when present.", + "type": "string" + } + }, + "type": "object" +}
- Changed
get_odds_history4 fields changed- added
Input schema / properties / bookmaker / descriptionAdded value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list." - added
Input schema / properties / event_id / descriptionAdded value: +"Event id, from list_events, query_events, or search results." - added
Input schema / properties / limit / descriptionAdded value: +"Max line-movement entries to return. Default 50." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "event_id": { + "type": "integer" + }, + "movements": { + "description": "Odds snapshots over time; each entry carries its own timestamp.", + "items": { + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "type": "object" +}
- Added
get_period_odds - Changed
get_player2 fields changed- added
Input schema / properties / player_id / descriptionAdded value: +"Player id, from search_players." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "birthdate": { + "description": "YYYY-MM-DD date of birth.", + "type": [ + "string", + "null" + ] + }, + "country_code": { + "description": "ISO 3166-1 alpha-3 country code.", + "type": [ + "string", + "null" + ] + }, + "current_team_id": { + "description": "Lumify team ID when the player is on a club roster. Null for tennis.", + "type": [ + "integer", + "null" + ] + }, + "current_team_name": { + "description": "Current team display name. Null for tennis.", + "type": [ + "string", + "null" + ] + }, + "first_name": { + "type": [ + "string", + "null" + ] + }, + "full_name": { + "description": "Display name.", + "type": "string" + }, + "handedness": { + "description": "left | right | switch. Meaning is sport-specific (bats for MLB, shoots for NHL, playing hand for tennis). Null when unknown.", + "type": [ + "string", + "null" + ] + }, + "height_cm": { + "description": "Height in centimetres. Null when not ingested.", + "type": [ + "integer", + "null" + ] + }, + "id": { + "description": "Lumify player ID.", + "type": "integer" + }, + "image_url": { + "description": "Lumify media URL for the player headshot (https://lumify.ai/media/players/{sport}/{id}.{ext}). Null until the sport's headshot/enrichment job. Never a vendor CDN.", + "type": [ + "string", + "null" + ] + }, + "is_active": { + "description": "False when deactivated or retired.", + "type": "boolean" + }, + "last_name": { + "type": [ + "string", + "null" + ] + }, + "position": { + "description": "Roster position abbreviation when the sport has one (e.g. C, P, SS for MLB; QB, WR for NFL). Null for tennis and when not yet ingested.", + "type": [ + "string", + "null" + ] + }, + "rankings": { + "description": "Sport ranking block. Tennis: {singles, points} from ATP/WTA standings. Null for every other sport. Tennis /stats also exposes ranking / ranking_points on the tennis player block.", + "properties": { + "points": { + "description": "ATP/WTA ranking points. Tennis only.", + "type": [ + "integer", + "null" + ] + }, + "singles": { + "description": "ATP/WTA singles ranking. Tennis only.", + "type": [ + "integer", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "retired_at": { + "description": "YYYY-MM-DD retirement date when known.", + "type": [ + "string", + "null" + ] + }, + "slug": { + "description": "URL-safe unique slug.", + "type": "string" + }, + "sport": { + "description": "Sport slug, e.g. mlb, tennis, nfl.", + "type": "string" + }, + "weight_kg": { + "description": "Weight in kilograms. Null when not ingested.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" +}
- Changed
get_player_events5 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: last event id from previous page."New value: +"Cursor: last event id from the previous page's next_after_id." - added
Input schema / properties / limit / descriptionAdded value: +"Max events to return per page." - added
Input schema / properties / player_id / descriptionAdded value: +"Player id, from search_players." - added
Input schema / properties / status / descriptionAdded value: +"Filter to events in this status." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Events in the same shape as list_events' EventSummary.", + "items": { + "type": "object" + }, + "type": "array" + }, + "has_more": { + "type": "boolean" + }, + "next_after_id": { + "description": "Pass as after_id to fetch the next page; null on the last page.", + "type": [ + "integer", + "null" + ] + }, + "player_id": { + "type": "integer" + } + }, + "type": "object" +}
- Added
get_player_props - Changed
get_splits2 fields changed- added
Input schema / properties / event_id / descriptionAdded value: +"Event id, from list_events, query_events, or search results." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "available": { + "type": "boolean" + }, + "bookmakers": { + "description": "Per-bookmaker splits. Each item has bookmaker (odds slug), name, moneyline, spread, total.", + "items": { + "type": "object" + }, + "type": "array" + }, + "captured_at": { + "type": [ + "string", + "null" + ] + }, + "consensus": { + "description": "Aggregate bets%/handle% across bookmakers.", + "type": [ + "object", + "null" + ] + }, + "event_id": { + "type": "integer" + } + }, + "type": "object" +}
- Added
get_stats - Changed
get_team2 fields changed- added
Input schema / properties / team_id / descriptionAdded value: +"Team id, from list_teams." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "abbreviation": { + "type": [ + "string", + "null" + ] + }, + "city": { + "type": [ + "string", + "null" + ] + }, + "conference": { + "type": [ + "string", + "null" + ] + }, + "division": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "image_url": { + "description": "Lumify media URL for the team logo (https://lumify.ai/media/teams/{sport}/{id}.png). Null until ingest. Never a vendor CDN.", + "type": [ + "string", + "null" + ] + }, + "is_active": { + "type": "boolean" + }, + "league": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "sport": { + "type": "string" + }, + "venue": { + "type": [ + "object", + "null" + ] + } + }, + "type": "object" +}
- Added
get_team_props - Added
list_ev - Changed
list_events7 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: return events with id > after_id."New value: +"Cursor: return events with id > after_id (from the previous page's next_after_id)." - changed
Input schema / properties / league / descriptionPrevious value: -"League slug, e.g. nfl, atp, fifa_world_cup."New value: +"League slug, e.g. nfl, atp, mls." - added
Input schema / properties / limit / descriptionAdded value: +"Max events to return per page." - changed
Input schema / properties / season_id / descriptionPrevious value: -"Filter by season ID."New value: +"Filter by season ID (from list_seasons)." - added
Input schema / properties / status / descriptionAdded value: +"Filter to events in this status." - added
Input schema / properties / team_idAdded value: +{ + "description": "Filter to events where this team participates. Resolve ids via list_teams.", + "type": "integer" +} - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "EventSummary": { + "properties": { + "clock": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "inprogress_since": { + "description": "ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final.", + "type": [ + "string", + "null" + ] + }, + "league": { + "type": "string" + }, + "name": { + "type": "string" + }, + "period": { + "type": [ + "string", + "null" + ] + }, + "season_id": { + "type": [ + "integer", + "null" + ] + }, + "sport": { + "type": "string" + }, + "starts_at": { + "description": "ISO-8601 UTC start time.", + "type": "string" + }, + "status": { + "type": "string" + }, + "venue": { + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + } + }, + "properties": { + "events": { + "items": { + "$ref": "#/$defs/EventSummary" + }, + "type": "array" + }, + "next_after_id": { + "description": "Pass as after_id to fetch the next page; null on the last page.", + "type": [ + "integer", + "null" + ] + }, + "total": { + "type": "integer" + } + }, + "type": "object" +}
- Added
list_forecasts - Changed
list_seasons3 fields changed- changed
Input schema / properties / current_only / defaultPrevious value: -falseNew value: +true - changed
Input schema / properties / current_only / descriptionPrevious value: -"Return only currently active seasons."New value: +"Return only currently active seasons (default true). Pass false for historical seasons." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "seasons": { + "items": { + "properties": { + "end_date": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "is_current": { + "type": "boolean" + }, + "league": { + "type": "object" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "phase": { + "type": [ + "string", + "null" + ] + }, + "sport": { + "type": "object" + }, + "start_date": { + "type": [ + "string", + "null" + ] + }, + "year": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "type": "object" +}
- Changed
list_sports2 fields changed- added
Input schema / properties / active_only / descriptionAdded value: +"When true (default), omit sports with no active coverage." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "sports": { + "items": { + "properties": { + "id": { + "type": "integer" + }, + "is_team_sport": { + "type": "boolean" + }, + "leagues": { + "items": { + "properties": { + "current_season": { + "type": [ + "object", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "total": { + "type": "integer" + } + }, + "type": "object" +}
- Changed
list_teams7 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: last team id from previous page."New value: +"Cursor: last team id from the previous page's next_after_id." - added
Input schema / properties / conference / descriptionAdded value: +"Conference name, e.g. AFC, Eastern." - added
Input schema / properties / division / descriptionAdded value: +"Division name, e.g. AFC East." - added
Input schema / properties / league / descriptionAdded value: +"League slug, e.g. nfl, mls." - added
Input schema / properties / limit / descriptionAdded value: +"Max teams to return per page." - added
Input schema / properties / sport / descriptionAdded value: +"Sport slug, e.g. nfl, nba, soccer." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "Team": { + "properties": { + "abbreviation": { + "type": [ + "string", + "null" + ] + }, + "city": { + "type": [ + "string", + "null" + ] + }, + "conference": { + "type": [ + "string", + "null" + ] + }, + "country_code": { + "type": [ + "string", + "null" + ] + }, + "division": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "image_url": { + "description": "Lumify media URL for the team logo (https://lumify.ai/media/teams/{sport}/{id}.png). Null until ingest. Never a vendor CDN.", + "type": [ + "string", + "null" + ] + }, + "is_active": { + "type": "boolean" + }, + "league": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + }, + "short_name": { + "type": [ + "string", + "null" + ] + }, + "slug": { + "type": "string" + }, + "sport": { + "type": "string" + }, + "state": { + "type": [ + "string", + "null" + ] + }, + "venue": { + "type": [ + "object", + "null" + ] + } + }, + "type": "object" + } + }, + "properties": { + "data": { + "items": { + "$ref": "#/$defs/Team" + }, + "type": "array" + }, + "has_more": { + "type": "boolean" + }, + "next_after_id": { + "description": "Pass as after_id to fetch the next page; null on the last page.", + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" +}
- Added
query_events - Changed
search_players5 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: last player id from previous page."New value: +"Cursor: last player id from the previous page's next_after_id." - added
Input schema / properties / limit / descriptionAdded value: +"Max players to return per page." - changed
Input schema / properties / ranked / descriptionPrevious value: -"If true, only players with a tennis ranking."New value: +"If true, only tennis players with an ATP/WTA singles ranking (rankings.singles)." - added
Input schema / properties / sport / descriptionAdded value: +"Sport slug, e.g. tennis, nba." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$defs": { + "Player": { + "properties": { + "birthdate": { + "description": "YYYY-MM-DD date of birth.", + "type": [ + "string", + "null" + ] + }, + "country_code": { + "description": "ISO 3166-1 alpha-3 country code.", + "type": [ + "string", + "null" + ] + }, + "current_team_id": { + "description": "Lumify team ID when the player is on a club roster. Null for tennis.", + "type": [ + "integer", + "null" + ] + }, + "current_team_name": { + "description": "Current team display name. Null for tennis.", + "type": [ + "string", + "null" + ] + }, + "first_name": { + "type": [ + "string", + "null" + ] + }, + "full_name": { + "description": "Display name.", + "type": "string" + }, + "handedness": { + "description": "left | right | switch. Meaning is sport-specific (bats for MLB, shoots for NHL, playing hand for tennis). Null when unknown.", + "type": [ + "string", + "null" + ] + }, + "height_cm": { + "description": "Height in centimetres. Null when not ingested.", + "type": [ + "integer", + "null" + ] + }, + "id": { + "description": "Lumify player ID.", + "type": "integer" + }, + "image_url": { + "description": "Lumify media URL for the player headshot (https://lumify.ai/media/players/{sport}/{id}.{ext}). Null until the sport's headshot/enrichment job. Never a vendor CDN.", + "type": [ + "string", + "null" + ] + }, + "is_active": { + "description": "False when deactivated or retired.", + "type": "boolean" + }, + "last_name": { + "type": [ + "string", + "null" + ] + }, + "position": { + "description": "Roster position abbreviation when the sport has one (e.g. C, P, SS for MLB; QB, WR for NFL). Null for tennis and when not yet ingested.", + "type": [ + "string", + "null" + ] + }, + "rankings": { + "description": "Sport ranking block. Tennis: {singles, points} from ATP/WTA standings. Null for every other sport. Tennis /stats also exposes ranking / ranking_points on the tennis player block.", + "properties": { + "points": { + "description": "ATP/WTA ranking points. Tennis only.", + "type": [ + "integer", + "null" + ] + }, + "singles": { + "description": "ATP/WTA singles ranking. Tennis only.", + "type": [ + "integer", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "retired_at": { + "description": "YYYY-MM-DD retirement date when known.", + "type": [ + "string", + "null" + ] + }, + "slug": { + "description": "URL-safe unique slug.", + "type": "string" + }, + "sport": { + "description": "Sport slug, e.g. mlb, tennis, nfl.", + "type": "string" + }, + "weight_kg": { + "description": "Weight in kilograms. Null when not ingested.", + "type": [ + "number", + "null" + ] + } + }, + "type": "object" + } + }, + "properties": { + "data": { + "items": { + "$ref": "#/$defs/Player" + }, + "type": "array" + }, + "has_more": { + "type": "boolean" + }, + "next_after_id": { + "description": "Pass as after_id to fetch the next page; null on the last page.", + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" +}
24 tool updates
- Removed
batch_get_events - Removed
estimate_cost - Changed
get_event5 fields changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all."New value: +"Bookmaker for inlined odds; defaults to pinnacle, 'all' for every book." - removed
Input schema / properties / event_id / descriptionRemoved value: -"Event id, from list_events, query_events, or search results." - changed
Input schema / properties / include_intelligence / descriptionPrevious value: -"Inline bet intelligence. Does not add credits."New value: +"Inline bet intelligence (+1 credit when available)." - changed
Input schema / properties / include_odds / descriptionPrevious value: -"Inline current odds scoped by bookmaker (default: pinnacle). Does not add credits — the event call stays 1 credit."New value: +"Inline current odds (+1 credit when odds are available)." - changed
Output schema / (root)Previous value: -{ - "properties": { - "id": { - "type": "integer" - }, - "inprogress_since": { - "description": "ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final.", - "type": [ - "string", - "null" - ] - }, - "league": { - "type": "string" - }, - "name": { - "type": "string" - }, - "participants": { - "items": { - "properties": { - "is_winner": { - "type": [ - "boolean", - "null" - ] - }, - "participant_id": { - "type": "integer" - }, - "player": { - "type": [ - "object", - "null" - ] - }, - "role": { - "type": "string" - }, - "score": { - "type": [ - "string", - "null" - ] - }, - "team": { - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "sport": { - "type": "string" - }, - "starts_at": { - "type": "string" - }, - "status": { - "type": "string" - }, - "updated_at": { - "type": [ - "string", - "null" - ] - }, - "venue": { - "type": [ - "object", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Removed
get_injuries - Changed
get_intelligence3 fields changed- removed
Input schema / properties / bookmaker / descriptionRemoved value: -"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada." - removed
Input schema / properties / event_id / descriptionRemoved value: -"Event id, from list_events, query_events, or search results." - changed
Output schema / (root)Previous value: -{ - "properties": { - "available": { - "description": "False when no predictive bets[] have been computed for this event yet. forecasts[] can still populate on MLB/NFL/NCAAF/NBA/NCAAB/NHL. Free only when available is false and forecasts is empty.", - "type": "boolean" - }, - "bets": { - "items": { - "properties": { - "alignment": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "type": [ - "object", - "null" - ] - }, - "attribution": { - "description": "Not published.", - "items": { - "type": "string" - }, - "type": "array" - }, - "best": { - "description": "Highest price-gap book across edges_by_book: {book, price, edge, quote_age_seconds}. Tier C informational line-shopping.", - "type": [ - "object", - "null" - ] - }, - "bet_type": { - "description": "Canonical bet token, e.g. ML_HOME/ML_AWAY/ML_DRAW (soccer), ML_P1/ML_P2 (head-to-head sports), SPREAD_HOME/SPREAD_AWAY, OVER, UNDER.", - "type": "string" - }, - "blend_w": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "type": [ - "number", - "null" - ] - }, - "computed_at": { - "description": "ISO-8601 UTC time this bet's numbers last materially changed — not when last checked. Rows are only rewritten when price, line, or probability moves beyond a tolerance, so an older value means 'unchanged since', not 'stale'. Differs between bets on one event because markets move independently.", - "type": [ - "string", - "null" - ] - }, - "confidence_score": { - "description": "Not published. Use probability.", - "type": [ - "number", - "null" - ] - }, - "coverage": { - "description": "Not published.", - "type": [ - "number", - "null" - ] - }, - "drivers": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "items": { - "type": "object" - }, - "type": "array" - }, - "edge": { - "description": "Expected profit per 1 unit staked at market.price. Null while no model-backed edge is published (Stage 1). Present on customer surface for recommend gating.", - "type": [ - "number", - "null" - ] - }, - "edges_by_book": { - "description": "Price gap versus fair.probability per soft book (fair.probability × decimal_odds − 1). Line-shopping metric: rank soft books by gap.", - "type": [ - "object", - "null" - ] - }, - "ev": { - "description": "Beta. Customer-facing EV estimate: {beta: true, book, price, ev_pct, kelly_fraction, quote_age_seconds, n_books}. Re-packages the same fair price gap for direct display. Moneyline only. n=1 Pinnacle is a valid fair (soccer/tennis). Null when the gap is ≤0, above 25% (stale-line), or only suppressed books remain (MLB ML × DK/FD proven null; BetMGM/Bet365/BetOnline unscreened).", - "type": [ - "object", - "null" - ] - }, - "fair": { - "description": "Sharp-consensus fair: {probability, books, n_books, is_consensus}. MLB/NFL: Pinnacle+Circa; MLS/tennis: Pinnacle. Price-gap reference for edges_by_book/best.", - "type": [ - "object", - "null" - ] - }, - "fair_price": { - "description": "American-odds fair price implied by probability — the vig-free line. Compare to market.price for the book's margin on this side.", - "type": [ - "integer", - "null" - ] - }, - "interval": { - "description": "[lo, hi] band around probability — how much evidence backs the number, not a statistical confidence interval.", - "items": { - "type": "number" - }, - "type": [ - "array", - "null" - ] - }, - "market": { - "description": "Market quote: {price: American odds, line: handicap/total line or null for moneyline, book: bookmaker slug when known (always set for probability-model sports)}.", - "type": [ - "object", - "null" - ] - }, - "model_version": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "type": [ - "string", - "null" - ] - }, - "narrative": { - "description": "Not published.", - "type": [ - "string", - "null" - ] - }, - "p_market": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis). Use probability/fair_price.", - "type": [ - "number", - "null" - ] - }, - "p_model": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "type": [ - "number", - "null" - ] - }, - "phase": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "type": [ - "string", - "null" - ] - }, - "player_id": { - "description": "Set when this bet is about an individual player. Null for team bets and match-level tokens.", - "type": [ - "integer", - "null" - ] - }, - "player_name": { - "description": "Display name of the player or team this bet is about. Null for match-level tokens. Duplicates players[player_role].name.", - "type": [ - "string", - "null" - ] - }, - "player_role": { - "description": "'home'/'away' or 'p1'/'p2'. Null for match-level tokens (OVER, UNDER, ML_DRAW).", - "type": [ - "string", - "null" - ] - }, - "probability": { - "description": "Published probability for this outcome, 0-1. Outcomes of one market sum to 1. Customer surface for MLB, soccer, tennis, NFL.", - "type": [ - "number", - "null" - ] - }, - "rationale": { - "description": "Not published. Top-level rationale is the event-level context overlay.", - "items": { - "type": "string" - }, - "type": "array" - }, - "signals": { - "description": "Not published.", - "type": [ - "object", - "null" - ] - }, - "sufficiency": { - "description": "Internal — omitted from customer payloads (MLB/soccer/tennis).", - "type": [ - "number", - "null" - ] - }, - "team_id": { - "description": "Set when this bet is about a team. Null for match-level tokens (OVER, UNDER, ML_DRAW) — a draw is not a bet on either team, so summing exposure by team_id never double-counts it.", - "type": [ - "integer", - "null" - ] - }, - "tier": { - "description": "Confidence tier: 'very_high', 'strong', 'moderate', or 'avoid'. Null whenever edge is null. Present on MLB customer surface and all other shapes.", - "type": [ - "string", - "null" - ] - }, - "validator": { - "description": "Not published.", - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "event_id": { - "description": "Lumify event ID this intelligence describes.", - "type": "integer" - }, - "forecasts": { - "description": "Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows on team sports; tennis main-line via bet_type ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), OVER/UNDER (total games). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts", - "items": { - "properties": { - "away_team": { - "description": "Away team display name. Slate only.", - "type": [ - "string", - "null" - ] - }, - "bet_type": { - "description": "Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis sets ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), and OVER/UNDER (total games).", - "type": [ - "string", - "null" - ] - }, - "books": { - "description": "American price for the picked outcome, keyed by bookmaker slug (e.g. {draftkings: -453}). Posted market price for the side/bet_type the model picked.", - "type": "object" - }, - "commence_time": { - "description": "ISO-8601 UTC scheduled start. Slate only.", - "type": [ - "string", - "null" - ] - }, - "conviction": { - "description": "Board rank key on 0–1: |p_hit−0.5|×2×sufficiency×research. A high p_hit on a thin sample ranks below a moderate p_hit on a long one. Highest conviction first on the daily slate.", - "type": "number" - }, - "drivers": { - "description": "Signed contributions that moved p_hit. Read input as the measured rate/rating behind the pick and effect as how far it lifts the chosen outcome versus a baseline.", - "items": { - "properties": { - "direction": { - "description": "up / down / neutral from the sign of effect.", - "type": "string" - }, - "effect": { - "description": "Signed shift in p_hit versus a baseline case on the same line. 0.0 on yardage markets.", - "type": "number" - }, - "id": { - "description": "Prop rows: typically player.l10_rate — the recent-form rate that fed Poisson. Main-line rows would use a different namespace once a main-line forecast model ships.", - "type": "string" - }, - "input": { - "description": "Measured rate/rating behind this driver, in native units.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "event_id": { - "description": "Lumify event ID. Present on list_forecasts; omitted on get_intelligence.forecasts (the event is the argument).", - "type": [ - "integer", - "null" - ] - }, - "home_team": { - "description": "Home team display name. Slate only.", - "type": [ - "string", - "null" - ] - }, - "interval": { - "description": "[lo, hi] stated band around p_hit. Wider when sufficiency is low. A stated evidence band, not a statistical confidence interval.", - "items": { - "type": "number" - }, - "type": "array" - }, - "league": { - "description": "League slug, if any. Slate only.", - "type": [ - "string", - "null" - ] - }, - "line": { - "description": "Posted line the model was scored against. Prop and totals main-line rows: Over/Under number. Spreads main-line rows: the spread number. Null on h2h/moneyline rows.", - "type": [ - "number", - "null" - ] - }, - "market": { - "description": "Player-prop rows: prop category (counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions, passing_tds, rushing_tds, touchdowns (anytime-TD combo: rushing + receiving + defensive TDs). NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals.", - "type": "string" - }, - "model_version": { - "description": "Scorer version, e.g. forecast-v0.", - "type": "string" - }, - "p_hit": { - "description": "Model probability (0–1) that the picked outcome (side on prop rows, bet_type on main-line rows) hits. Prop rows: built from the player's shrunken counting-stat rate (Poisson vs the posted Over/Under). Optional research may nudge a prop's p_hit by at most ±0.03; the chosen side stays the same.", - "type": "number" - }, - "player": { - "description": "Player display name from the priced line. Null on main-line rows with no player attribution (bet_type is a match-level token like OVER/UNDER/ML_DRAW).", - "type": [ - "string", - "null" - ] - }, - "player_id": { - "description": "Lumify player ID. Bound by exact / Jr-stripped name match. Null on main-line rows with no player attribution.", - "type": [ - "integer", - "null" - ] - }, - "player_role": { - "description": "'home'/'away' for team sports or 'p1'/'p2' for head-to-head sports, set only alongside a non-null bet_type. Null for player-prop rows and for match-level main-line tokens (OVER, UNDER, ML_DRAW).", - "type": [ - "string", - "null" - ] - }, - "reliability": { - "description": "Badge on this sport×market cell: emerging, moderate, high, or informational. v0 ships emerging for every wager.", - "type": "string" - }, - "research": { - "description": "Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction. Invalidate drops the wager from forecasts[] and the daily board — it is not a recommended pick. The chosen side stays. Null means read p_hit from the rate model alone.", - "type": [ - "object", - "null" - ] - }, - "selected": { - "description": "True when this wager is on the daily board (top conviction). On get_intelligence the array includes selected and the rest of the event catalog.", - "type": "boolean" - }, - "side": { - "description": "Prop rows: 'over' or 'under' — the more likely side given the player's shrunken rate versus line. Null on main-line rows — read the picked outcome from bet_type instead.", - "type": [ - "string", - "null" - ] - }, - "sport": { - "description": "Sport slug. Slate only.", - "type": [ - "string", - "null" - ] - }, - "sufficiency": { - "description": "Evidence weight on 0–1: n/(n+12), where n is the recent-form game count (typically L10). A player with 10 games has sufficiency ≈ 0.45. The wager still ships; this field tells you how much of p_hit is earned from this player's own boxes.", - "type": "number" - } - }, - "type": "object" - }, - "type": "array" - }, - "has_recommend": { - "description": "True when at least one bet meets the recommendation threshold; null when intelligence has not been computed. False while Edge is not published (current MLB/soccer/tennis Stage 1) — a recommendation requires a non-null tier derived from edge.", - "type": [ - "boolean", - "null" - ] - }, - "intelligence_updated_at": { - "description": "ISO-8601 UTC timestamp of the most recent change anywhere in this payload (max of per-bet computed_at). Use per-bet computed_at to reason about a specific bet.", - "type": [ - "string", - "null" - ] - }, - "league": { - "description": "League slug for this event, if any.", - "type": [ - "string", - "null" - ] - }, - "match_overview": { - "description": "Natural-language pre-game matchup preview — form, context, what to watch. Written before kickoff by a Search-backed overlay on every event sport (MLB, NFL, NCAAF, NBA, NCAAB, NHL, soccer, tennis); sport-shaped queries. The request path only reads the stored row. Null when the pre-kickoff job has not run or the fixture was not eligible.", - "type": [ - "string", - "null" - ] - }, - "matchup": { - "description": "Not returned. Use get_stats for pitcher/lineup Data.", - "type": [ - "object", - "null" - ] - }, - "odds_source": { - "description": "Bookmaker bets[].market prices were sourced from. For probability-model sports this is the book the assessment was priced against, not a bookmaker overlay; per-bet market.book is authoritative if they ever differ.", - "type": [ - "string", - "null" - ] - }, - "players": { - "description": "Home/away (or p1/p2) participant identification, keyed by role: {role: {name, player_id, team_id}}.", - "type": "object" - }, - "rationale": { - "description": "Event-level factual pre-game matchup chips (injuries, recent form, lineup/availability news — sport-shaped). Written before kickoff; the request path only reads the stored row.", - "items": { - "type": "string" - }, - "type": [ - "array", - "null" - ] - }, - "sport": { - "description": "Sport slug for this event.", - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_live_score2 fields changed- removed
Input schema / properties / event_id / descriptionRemoved value: -"Event id, from list_events, query_events, or search results." - changed
Output schema / (root)Previous value: -{ - "properties": { - "clock": { - "type": [ - "string", - "null" - ] - }, - "event_id": { - "type": "integer" - }, - "finished": { - "type": "boolean" - }, - "period": { - "type": [ - "string", - "null" - ] - }, - "scores": { - "items": { - "properties": { - "abbreviation": { - "type": [ - "string", - "null" - ] - }, - "is_winner": { - "type": [ - "boolean", - "null" - ] - }, - "name": { - "type": "string" - }, - "period_scores": { - "items": { - "type": "object" - }, - "type": "array" - }, - "role": { - "type": "string" - }, - "score": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "status": { - "type": "string" - }, - "updated_at": { - "type": [ - "string", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_odds4 fields changed- removed
Input schema / properties / bookmaker / descriptionRemoved value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list." - removed
Input schema / properties / event_id / descriptionRemoved value: -"Event id, from list_events, query_events, or search results." - removed
Input schema / properties / include_altsRemoved value: -{ - "description": "Include alternate spread/total rungs. Default false (mains only).", - "type": "boolean" -} - changed
Output schema / (root)Previous value: -{ - "properties": { - "available": { - "type": "boolean" - }, - "bookmakers": { - "description": "Per-book markets. Outcomes include is_main. In-play omits books that have not quoted since kickoff. Final events add result (won/lost/push/void) and close on the pre-kickoff point.", - "items": { - "type": "object" - }, - "type": "array" - }, - "event_id": { - "type": "integer" - }, - "fallback_bookmaker": { - "description": "The book actually returned when requested_bookmaker is present.", - "type": "string" - }, - "last_updated": { - "type": [ - "string", - "null" - ] - }, - "requested_bookmaker": { - "description": "Present only when the default (no bookmaker arg) request fell back to a different book because Pinnacle has no line yet — always 'pinnacle' when present.", - "type": "string" - } - }, - "type": "object" -}New value: +null
- Changed
get_odds_history4 fields changed- removed
Input schema / properties / bookmaker / descriptionRemoved value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list." - removed
Input schema / properties / event_id / descriptionRemoved value: -"Event id, from list_events, query_events, or search results." - removed
Input schema / properties / limit / descriptionRemoved value: -"Max line-movement entries to return. Default 50." - changed
Output schema / (root)Previous value: -{ - "properties": { - "event_id": { - "type": "integer" - }, - "movements": { - "description": "Odds snapshots over time; each entry carries its own timestamp.", - "items": { - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "integer" - } - }, - "type": "object" -}New value: +null
- Removed
get_period_odds - Changed
get_player2 fields changed- removed
Input schema / properties / player_id / descriptionRemoved value: -"Player id, from search_players." - changed
Output schema / (root)Previous value: -{ - "properties": { - "birthdate": { - "description": "YYYY-MM-DD date of birth.", - "type": [ - "string", - "null" - ] - }, - "country_code": { - "description": "ISO 3166-1 alpha-3 country code.", - "type": [ - "string", - "null" - ] - }, - "current_team_id": { - "description": "Lumify team ID when the player is on a club roster. Null for tennis.", - "type": [ - "integer", - "null" - ] - }, - "current_team_name": { - "description": "Current team display name. Null for tennis.", - "type": [ - "string", - "null" - ] - }, - "first_name": { - "type": [ - "string", - "null" - ] - }, - "full_name": { - "description": "Display name.", - "type": "string" - }, - "handedness": { - "description": "left | right | switch. Meaning is sport-specific (bats for MLB, shoots for NHL, playing hand for tennis). Null when unknown.", - "type": [ - "string", - "null" - ] - }, - "height_cm": { - "description": "Height in centimetres. Null when not ingested.", - "type": [ - "integer", - "null" - ] - }, - "id": { - "description": "Lumify player ID.", - "type": "integer" - }, - "image_url": { - "description": "Lumify media URL for the player headshot (https://lumify.ai/media/players/{sport}/{id}.{ext}). Null until the sport's headshot/enrichment job. Never a vendor CDN.", - "type": [ - "string", - "null" - ] - }, - "is_active": { - "description": "False when deactivated or retired.", - "type": "boolean" - }, - "last_name": { - "type": [ - "string", - "null" - ] - }, - "position": { - "description": "Roster position abbreviation when the sport has one (e.g. C, P, SS for MLB; QB, WR for NFL). Null for tennis and when not yet ingested.", - "type": [ - "string", - "null" - ] - }, - "rankings": { - "description": "Sport ranking block. Tennis: {singles, points} from ATP/WTA standings. Null for every other sport. Tennis /stats also exposes ranking / ranking_points on the tennis player block.", - "properties": { - "points": { - "description": "ATP/WTA ranking points. Tennis only.", - "type": [ - "integer", - "null" - ] - }, - "singles": { - "description": "ATP/WTA singles ranking. Tennis only.", - "type": [ - "integer", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "retired_at": { - "description": "YYYY-MM-DD retirement date when known.", - "type": [ - "string", - "null" - ] - }, - "slug": { - "description": "URL-safe unique slug.", - "type": "string" - }, - "sport": { - "description": "Sport slug, e.g. mlb, tennis, nfl.", - "type": "string" - }, - "weight_kg": { - "description": "Weight in kilograms. Null when not ingested.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Changed
get_player_events5 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: last event id from the previous page's next_after_id."New value: +"Cursor: last event id from previous page." - removed
Input schema / properties / limit / descriptionRemoved value: -"Max events to return per page." - removed
Input schema / properties / player_id / descriptionRemoved value: -"Player id, from search_players." - removed
Input schema / properties / status / descriptionRemoved value: -"Filter to events in this status." - changed
Output schema / (root)Previous value: -{ - "properties": { - "data": { - "description": "Events in the same shape as list_events' EventSummary.", - "items": { - "type": "object" - }, - "type": "array" - }, - "has_more": { - "type": "boolean" - }, - "next_after_id": { - "description": "Pass as after_id to fetch the next page; null on the last page.", - "type": [ - "integer", - "null" - ] - }, - "player_id": { - "type": "integer" - } - }, - "type": "object" -}New value: +null
- Removed
get_player_props - Changed
get_splits2 fields changed- removed
Input schema / properties / event_id / descriptionRemoved value: -"Event id, from list_events, query_events, or search results." - changed
Output schema / (root)Previous value: -{ - "properties": { - "available": { - "type": "boolean" - }, - "bookmakers": { - "description": "Per-bookmaker splits. Each item has bookmaker (odds slug), name, moneyline, spread, total.", - "items": { - "type": "object" - }, - "type": "array" - }, - "captured_at": { - "type": [ - "string", - "null" - ] - }, - "consensus": { - "description": "Aggregate bets%/handle% across bookmakers.", - "type": [ - "object", - "null" - ] - }, - "event_id": { - "type": "integer" - } - }, - "type": "object" -}New value: +null
- Removed
get_stats - Changed
get_team2 fields changed- removed
Input schema / properties / team_id / descriptionRemoved value: -"Team id, from list_teams." - changed
Output schema / (root)Previous value: -{ - "properties": { - "abbreviation": { - "type": [ - "string", - "null" - ] - }, - "city": { - "type": [ - "string", - "null" - ] - }, - "conference": { - "type": [ - "string", - "null" - ] - }, - "division": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer" - }, - "image_url": { - "description": "Lumify media URL for the team logo (https://lumify.ai/media/teams/{sport}/{id}.png). Null until ingest. Never a vendor CDN.", - "type": [ - "string", - "null" - ] - }, - "is_active": { - "type": "boolean" - }, - "league": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - }, - "sport": { - "type": "string" - }, - "venue": { - "type": [ - "object", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Removed
get_team_props - Removed
list_ev - Changed
list_events7 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: return events with id > after_id (from the previous page's next_after_id)."New value: +"Cursor: return events with id > after_id." - changed
Input schema / properties / league / descriptionPrevious value: -"League slug, e.g. nfl, atp, mls."New value: +"League slug, e.g. nfl, atp, fifa_world_cup." - removed
Input schema / properties / limit / descriptionRemoved value: -"Max events to return per page." - changed
Input schema / properties / season_id / descriptionPrevious value: -"Filter by season ID (from list_seasons)."New value: +"Filter by season ID." - removed
Input schema / properties / status / descriptionRemoved value: -"Filter to events in this status." - removed
Input schema / properties / team_idRemoved value: -{ - "description": "Filter to events where this team participates. Resolve ids via list_teams.", - "type": "integer" -} - changed
Output schema / (root)Previous value: -{ - "$defs": { - "EventSummary": { - "properties": { - "clock": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer" - }, - "inprogress_since": { - "description": "ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final.", - "type": [ - "string", - "null" - ] - }, - "league": { - "type": "string" - }, - "name": { - "type": "string" - }, - "period": { - "type": [ - "string", - "null" - ] - }, - "season_id": { - "type": [ - "integer", - "null" - ] - }, - "sport": { - "type": "string" - }, - "starts_at": { - "description": "ISO-8601 UTC start time.", - "type": "string" - }, - "status": { - "type": "string" - }, - "venue": { - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - } - }, - "properties": { - "events": { - "items": { - "$ref": "#/$defs/EventSummary" - }, - "type": "array" - }, - "next_after_id": { - "description": "Pass as after_id to fetch the next page; null on the last page.", - "type": [ - "integer", - "null" - ] - }, - "total": { - "type": "integer" - } - }, - "type": "object" -}New value: +null
- Removed
list_forecasts - Changed
list_seasons3 fields changed- changed
Input schema / properties / current_only / defaultPrevious value: -trueNew value: +false - changed
Input schema / properties / current_only / descriptionPrevious value: -"Return only currently active seasons (default true). Pass false for historical seasons."New value: +"Return only currently active seasons." - changed
Output schema / (root)Previous value: -{ - "properties": { - "seasons": { - "items": { - "properties": { - "end_date": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer" - }, - "is_current": { - "type": "boolean" - }, - "league": { - "type": "object" - }, - "name": { - "type": [ - "string", - "null" - ] - }, - "phase": { - "type": [ - "string", - "null" - ] - }, - "sport": { - "type": "object" - }, - "start_date": { - "type": [ - "string", - "null" - ] - }, - "year": { - "type": [ - "integer", - "null" - ] - } - }, - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "integer" - } - }, - "type": "object" -}New value: +null
- Changed
list_sports2 fields changed- removed
Input schema / properties / active_only / descriptionRemoved value: -"When true (default), omit sports with no active coverage." - changed
Output schema / (root)Previous value: -{ - "properties": { - "sports": { - "items": { - "properties": { - "id": { - "type": "integer" - }, - "is_team_sport": { - "type": "boolean" - }, - "leagues": { - "items": { - "properties": { - "current_season": { - "type": [ - "object", - "null" - ] - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "name": { - "type": "string" - }, - "slug": { - "type": "string" - } - }, - "type": "object" - }, - "type": "array" - }, - "total": { - "type": "integer" - } - }, - "type": "object" -}New value: +null
- Changed
list_teams7 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: last team id from the previous page's next_after_id."New value: +"Cursor: last team id from previous page." - removed
Input schema / properties / conference / descriptionRemoved value: -"Conference name, e.g. AFC, Eastern." - removed
Input schema / properties / division / descriptionRemoved value: -"Division name, e.g. AFC East." - removed
Input schema / properties / league / descriptionRemoved value: -"League slug, e.g. nfl, mls." - removed
Input schema / properties / limit / descriptionRemoved value: -"Max teams to return per page." - removed
Input schema / properties / sport / descriptionRemoved value: -"Sport slug, e.g. nfl, nba, soccer." - changed
Output schema / (root)Previous value: -{ - "$defs": { - "Team": { - "properties": { - "abbreviation": { - "type": [ - "string", - "null" - ] - }, - "city": { - "type": [ - "string", - "null" - ] - }, - "conference": { - "type": [ - "string", - "null" - ] - }, - "country_code": { - "type": [ - "string", - "null" - ] - }, - "division": { - "type": [ - "string", - "null" - ] - }, - "id": { - "type": "integer" - }, - "image_url": { - "description": "Lumify media URL for the team logo (https://lumify.ai/media/teams/{sport}/{id}.png). Null until ingest. Never a vendor CDN.", - "type": [ - "string", - "null" - ] - }, - "is_active": { - "type": "boolean" - }, - "league": { - "type": [ - "string", - "null" - ] - }, - "name": { - "type": "string" - }, - "short_name": { - "type": [ - "string", - "null" - ] - }, - "slug": { - "type": "string" - }, - "sport": { - "type": "string" - }, - "state": { - "type": [ - "string", - "null" - ] - }, - "venue": { - "type": [ - "object", - "null" - ] - } - }, - "type": "object" - } - }, - "properties": { - "data": { - "items": { - "$ref": "#/$defs/Team" - }, - "type": "array" - }, - "has_more": { - "type": "boolean" - }, - "next_after_id": { - "description": "Pass as after_id to fetch the next page; null on the last page.", - "type": [ - "integer", - "null" - ] - } - }, - "type": "object" -}New value: +null
- Removed
query_events - Changed
search_players5 fields changed- changed
Input schema / properties / after_id / descriptionPrevious value: -"Cursor: last player id from the previous page's next_after_id."New value: +"Cursor: last player id from previous page." - removed
Input schema / properties / limit / descriptionRemoved value: -"Max players to return per page." - changed
Input schema / properties / ranked / descriptionPrevious value: -"If true, only tennis players with an ATP/WTA singles ranking (rankings.singles)."New value: +"If true, only players with a tennis ranking." - removed
Input schema / properties / sport / descriptionRemoved value: -"Sport slug, e.g. tennis, nba." - changed
Output schema / (root)Previous value: -{ - "$defs": { - "Player": { - "properties": { - "birthdate": { - "description": "YYYY-MM-DD date of birth.", - "type": [ - "string", - "null" - ] - }, - "country_code": { - "description": "ISO 3166-1 alpha-3 country code.", - "type": [ - "string", - "null" - ] - }, - "current_team_id": { - "description": "Lumify team ID when the player is on a club roster. Null for tennis.", - "type": [ - "integer", - "null" - ] - }, - "current_team_name": { - "description": "Current team display name. Null for tennis.", - "type": [ - "string", - "null" - ] - }, - "first_name": { - "type": [ - "string", - "null" - ] - }, - "full_name": { - "description": "Display name.", - "type": "string" - }, - "handedness": { - "description": "left | right | switch. Meaning is sport-specific (bats for MLB, shoots for NHL, playing hand for tennis). Null when unknown.", - "type": [ - "string", - "null" - ] - }, - "height_cm": { - "description": "Height in centimetres. Null when not ingested.", - "type": [ - "integer", - "null" - ] - }, - "id": { - "description": "Lumify player ID.", - "type": "integer" - }, - "image_url": { - "description": "Lumify media URL for the player headshot (https://lumify.ai/media/players/{sport}/{id}.{ext}). Null until the sport's headshot/enrichment job. Never a vendor CDN.", - "type": [ - "string", - "null" - ] - }, - "is_active": { - "description": "False when deactivated or retired.", - "type": "boolean" - }, - "last_name": { - "type": [ - "string", - "null" - ] - }, - "position": { - "description": "Roster position abbreviation when the sport has one (e.g. C, P, SS for MLB; QB, WR for NFL). Null for tennis and when not yet ingested.", - "type": [ - "string", - "null" - ] - }, - "rankings": { - "description": "Sport ranking block. Tennis: {singles, points} from ATP/WTA standings. Null for every other sport. Tennis /stats also exposes ranking / ranking_points on the tennis player block.", - "properties": { - "points": { - "description": "ATP/WTA ranking points. Tennis only.", - "type": [ - "integer", - "null" - ] - }, - "singles": { - "description": "ATP/WTA singles ranking. Tennis only.", - "type": [ - "integer", - "null" - ] - } - }, - "type": [ - "object", - "null" - ] - }, - "retired_at": { - "description": "YYYY-MM-DD retirement date when known.", - "type": [ - "string", - "null" - ] - }, - "slug": { - "description": "URL-safe unique slug.", - "type": "string" - }, - "sport": { - "description": "Sport slug, e.g. mlb, tennis, nfl.", - "type": "string" - }, - "weight_kg": { - "description": "Weight in kilograms. Null when not ingested.", - "type": [ - "number", - "null" - ] - } - }, - "type": "object" - } - }, - "properties": { - "data": { - "items": { - "$ref": "#/$defs/Player" - }, - "type": "array" - }, - "has_more": { - "type": "boolean" - }, - "next_after_id": { - "description": "Pass as after_id to fetch the next page; null on the last page.", - "type": [ - "integer", - "null" - ] - } - }, - "type": "object" -}New value: +null
2 tool updates
- Changed
get_intelligence1 field changed- changed
Output schema / properties / forecasts / items / properties / research / descriptionPrevious value: -"Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction; invalidate does the reverse. The chosen side stays. Null means read p_hit from the rate model alone."New value: +"Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction. Invalidate drops the wager from forecasts[] and the daily board — it is not a recommended pick. The chosen side stays. Null means read p_hit from the rate model alone."
- Changed
list_forecasts1 field changed- changed
Output schema / properties / wagers / items / properties / research / descriptionPrevious value: -"Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction; invalidate does the reverse. The chosen side stays. Null means read p_hit from the rate model alone."New value: +"Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction. Invalidate drops the wager from forecasts[] and the daily board — it is not a recommended pick. The chosen side stays. Null means read p_hit from the rate model alone."
2 tool updates
- Changed
get_intelligence1 field changed- changed
Output schema / properties / forecasts / items / properties / market / descriptionPrevious value: -"Player-prop rows: prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."New value: +"Player-prop rows: prop category (counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions, passing_tds, rushing_tds, touchdowns (anytime-TD combo: rushing + receiving + defensive TDs). NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."
- Changed
list_forecasts1 field changed- changed
Output schema / properties / wagers / items / properties / market / descriptionPrevious value: -"Player-prop rows: prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."New value: +"Player-prop rows: prop category (counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions, passing_tds, rushing_tds, touchdowns (anytime-TD combo: rushing + receiving + defensive TDs). NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."
1 tool update
- Removed
get_prediction_markets
6 tool updates
- Changed
batch_get_events1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all."
- Changed
get_event1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all."
- Changed
get_intelligence1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig."New value: +"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada."
- Changed
get_odds1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all, or a comma-separated list."New value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list."
- Changed
get_odds_history1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all, or a comma-separated list."New value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, bovada, all, or a comma-separated list."
- Changed
get_player_props1 field changed- changed
Output schema / properties / player_props / descriptionPrevious value: -"One row per (player, market, line). Fields: player, player_id (null if unmatched), market (prop category), line, current (this-event box count), pct_of_line, settleable, result (in_progress / over / under / push, or null), books ({book_slug: {over, under}} American prices)."New value: +"One row per (player, market, line). Fields: player, player_id (null if unmatched), market (prop category), line, current (this-event box count), pct_of_line, settleable, result (in_progress / over / under / push / dnp — box landed and this player has zero rows / no_stat — played but this slug never landed, unmatched, or box not landed yet; null when not settleable), books ({book_slug: {over, under}} American prices)."
1 tool update
- Changed
get_injuries1 field changed- changed
Output schema / properties / injuries / descriptionPrevious value: -"Per-player rows: player, player_id, team, team_id, status, previous_status, body_part, note, source_url, severity, last_changed_at."New value: +"Per-player rows: player, player_id, team, team_id, status, previous_status, body_part, note, source_url, severity, last_changed_at. team/team_id prefer the player's current roster team when that team is a participant in this event."
1 tool update
- Changed
get_injuries1 field changed- added
Input schema / properties / exclude_statusAdded value: +{ + "description": "Comma-separated statuses to drop, e.g. \"ir\" to hide injured-reserve/long-term-IL rows (long-standing roster designations, not late-breaking news). Valid values: out, doubtful, questionable, probable, day_to_day, ir, suspended, available.", + "type": "string" +}
1 tool update
- Added
get_injuries
6 tool updates
- Changed
batch_get_events1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all."
- Changed
get_event1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all."
- Changed
get_intelligence1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers."New value: +"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig."
- Changed
get_odds1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all, or a comma-separated list."New value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all, or a comma-separated list."
- Changed
get_odds_history1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all, or a comma-separated list."New value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, lowvig, all, or a comma-separated list."
- Added
get_prediction_markets
5 tool updates
- Changed
get_event1 field changed- added
Output schema / properties / inprogress_sinceAdded value: +{ + "description": "ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final.", + "type": [ + "string", + "null" + ] +}
- Changed
get_intelligence1 field changed- changed
Output schema / properties / forecasts / items / properties / market / descriptionPrevious value: -"Player-prop rows: Owls prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."New value: +"Player-prop rows: prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."
- Changed
get_stats1 field changed- changed
Output schema / properties / players / descriptionPrevious value: -"Tennis only (player_1/player_2). Each side: player_id, name, country_code, ranking, ranking_points, rest_days, recent_form, surface_form, record (tour_lookback wins/losses), career_rates (Stage-2 serve/return percentages from RapidAPI Tennis API; null until ingest), career_surface (Stage-2 match-surface W/L over windows.career_surface_years; null when empty). History windows exclude walkovers (unplayed) and include retirements."New value: +"Tennis only (player_1/player_2). Each side: player_id, name, country_code, ranking, ranking_points, rest_days, recent_form, surface_form, record (tour_lookback wins/losses), career_rates (Stage-2 serve/return percentages; null until ingest), career_surface (Stage-2 match-surface W/L over windows.career_surface_years; null when empty). History windows exclude walkovers (unplayed) and include retirements."
- Changed
list_events1 field changed- added
Output schema / $defs / EventSummary / properties / inprogress_sinceAdded value: +{ + "description": "ISO-8601 UTC when status first became inprogress (first live tick). Null until then; stays set after final.", + "type": [ + "string", + "null" + ] +}
- Changed
list_forecasts1 field changed- changed
Output schema / properties / wagers / items / properties / market / descriptionPrevious value: -"Player-prop rows: Owls prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."New value: +"Player-prop rows: prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals."
5 tool updates
- Changed
batch_get_events1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, hardrock, betonline, all."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all."
- Changed
get_event1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, hardrock, betonline, all."New value: +"Bookmaker for inlined odds and intelligence market prices. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all."
- Changed
get_intelligence1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, hardrock, betonline."New value: +"Ignored. Intelligence always reports the book the assessment was priced against. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers."
- Changed
get_odds1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, hardrock, betonline, all, or a comma-separated list."New value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all, or a comma-separated list."
- Changed
get_odds_history1 field changed- changed
Input schema / properties / bookmaker / descriptionPrevious value: -"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, hardrock, betonline, all, or a comma-separated list."New value: +"Bookmaker slug. Defaults to pinnacle. Valid: pinnacle, fanduel, draftkings, betmgm, caesars, bet365, circa, westgate, wynn, south_point, stations, hardrock, betonline, betr, betrivers, all, or a comma-separated list."
1 tool update
- Changed
get_intelligence2 fields changed- changed
Output schema / properties / match_overview / descriptionPrevious value: -"Natural-language matchup preview — form, context, what to watch. Search-backed context overlay on every event sport (MLB, NFL, NCAAF, NBA, NCAAB, NHL, soccer, tennis); sport-shaped queries. Null when no narrative has been generated."New value: +"Natural-language pre-game matchup preview — form, context, what to watch. Written before kickoff by a Search-backed overlay on every event sport (MLB, NFL, NCAAF, NBA, NCAAB, NHL, soccer, tennis); sport-shaped queries. The request path only reads the stored row. Null when the pre-kickoff job has not run or the fixture was not eligible." - changed
Output schema / properties / rationale / descriptionPrevious value: -"Event-level factual matchup chips (injuries, recent form, lineup/availability news — sport-shaped). Search-backed context overlay; may populate on first get_intelligence, later calls reuse the stored row."New value: +"Event-level factual pre-game matchup chips (injuries, recent form, lineup/availability news — sport-shaped). Written before kickoff; the request path only reads the stored row."
2 tool updates
- Changed
get_intelligence2 fields changed- changed
Output schema / properties / forecasts / descriptionPrevious value: -"Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows on team sports; tennis moneyline via bet_type ML_P1/ML_P2. selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts"New value: +"Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows on team sports; tennis main-line via bet_type ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), OVER/UNDER (total games). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts" - changed
Output schema / properties / forecasts / items / properties / bet_type / descriptionPrevious value: -"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis moneyline rows set ML_P1 / ML_P2."New value: +"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis sets ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), and OVER/UNDER (total games)."
- Changed
list_forecasts2 fields changed- changed
Input schema / properties / market / descriptionPrevious value: -"Main-line family filter (h2h, spreads, or totals). Tennis publishes h2h only. Ignored on prop-only sports."New value: +"Main-line family filter (h2h, spreads, or totals). Tennis publishes all three (moneyline, game-handicap, total-games). Ignored on prop-only sports." - changed
Output schema / properties / wagers / items / properties / bet_type / descriptionPrevious value: -"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis moneyline rows set ML_P1 / ML_P2."New value: +"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis sets ML_P1/ML_P2 (moneyline), SPREAD_P1/SPREAD_P2 (game handicap), and OVER/UNDER (total games)."
2 tool updates
- Changed
get_intelligence2 fields changed- changed
Output schema / properties / forecasts / descriptionPrevious value: -"Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows today; schema also carries main-line rows via bet_type (none shipped yet). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts"New value: +"Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows on team sports; tennis moneyline via bet_type ML_P1/ML_P2. selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts" - changed
Output schema / properties / forecasts / items / properties / bet_type / descriptionPrevious value: -"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. No sport ships a non-null bet_type here yet."New value: +"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis moneyline rows set ML_P1 / ML_P2."
- Changed
list_forecasts3 fields changed- changed
Input schema / properties / market / descriptionPrevious value: -"Main-line family filter (h2h, spreads, or totals) for a sport's main-line forecast rows, once one exists. No sport publishes main-line forecasts today, so this has no effect yet. Ignored on prop-only sports."New value: +"Main-line family filter (h2h, spreads, or totals). Tennis publishes h2h only. Ignored on prop-only sports." - changed
Input schema / properties / sport / descriptionPrevious value: -"Sport slug: mlb, ncaaf, nfl, nba, ncaab, or nhl."New value: +"Sport slug: mlb, ncaaf, nfl, nba, ncaab, nhl, or tennis." - changed
Output schema / properties / wagers / items / properties / bet_type / descriptionPrevious value: -"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. No sport ships a non-null bet_type here yet."New value: +"Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. Tennis moneyline rows set ML_P1 / ML_P2."
3 tool updates
- Changed
get_intelligence19 fields changed- changed
Output schema / properties / forecasts / descriptionPrevious value: -"Forecasted Over/Under player-prop wagers for this event (same object as list_forecasts). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(side hits the posted line) from the player's shrunken rate. How + field catalog: https://lumify.ai/docs/forecasts"New value: +"Forecasted wagers for this event (same object as list_forecasts) — a model prediction, not a beat-the-market claim. Player-prop rows today; schema also carries main-line rows via bet_type (none shipped yet). selected marks the top-conviction rows on the daily slate; the rest of the event catalog is included with selected:false. Read p_hit as P(the picked outcome hits). How + field catalog: https://lumify.ai/docs/forecasts" - added
Output schema / properties / forecasts / items / properties / bet_typeAdded value: +{ + "description": "Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. No sport ships a non-null bet_type here yet.", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / forecasts / items / properties / books / descriptionPrevious value: -"American price for the chosen side, keyed by bookmaker slug (e.g. {draftkings: -453}). Posted market price for the side the model picked."New value: +"American price for the picked outcome, keyed by bookmaker slug (e.g. {draftkings: -453}). Posted market price for the side/bet_type the model picked." - changed
Output schema / properties / forecasts / items / properties / drivers / descriptionPrevious value: -"Signed contributions that moved p_hit. Read input as the player's measured rate and effect as how far that rate lifts the chosen side versus a league-mean player."New value: +"Signed contributions that moved p_hit. Read input as the measured rate/rating behind the pick and effect as how far it lifts the chosen outcome versus a baseline." - changed
Output schema / properties / forecasts / items / properties / drivers / items / properties / effect / descriptionPrevious value: -"Signed shift in p_hit versus a league-mean player on the same line. 0.0 on yardage markets."New value: +"Signed shift in p_hit versus a baseline case on the same line. 0.0 on yardage markets." - changed
Output schema / properties / forecasts / items / properties / drivers / items / properties / id / descriptionPrevious value: -"e.g. player.l10_rate — the recent-form rate that fed Poisson."New value: +"Prop rows: typically player.l10_rate — the recent-form rate that fed Poisson. Main-line rows would use a different namespace once a main-line forecast model ships." - changed
Output schema / properties / forecasts / items / properties / drivers / items / properties / input / descriptionPrevious value: -"Measured rate in counting-stat units per game after shrinkage."New value: +"Measured rate/rating behind this driver, in native units." - changed
Output schema / properties / forecasts / items / properties / line / descriptionPrevious value: -"Posted Over/Under main line the model was scored against."New value: +"Posted line the model was scored against. Prop and totals main-line rows: Over/Under number. Spreads main-line rows: the spread number. Null on h2h/moneyline rows." - changed
Output schema / properties / forecasts / items / properties / line / typePrevious value: -"number"New value: +[ + "number", + "null" +] - changed
Output schema / properties / forecasts / items / properties / market / descriptionPrevious value: -"Owls prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal."New value: +"Player-prop rows: Owls prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals." - changed
Output schema / properties / forecasts / items / properties / p_hit / descriptionPrevious value: -"Model probability (0–1) that side hits line, from the player's shrunken counting-stat rate (Poisson vs the posted Over/Under). Optional research may nudge this by at most ±0.03; the side stays."New value: +"Model probability (0–1) that the picked outcome (side on prop rows, bet_type on main-line rows) hits. Prop rows: built from the player's shrunken counting-stat rate (Poisson vs the posted Over/Under). Optional research may nudge a prop's p_hit by at most ±0.03; the chosen side stays the same." - changed
Output schema / properties / forecasts / items / properties / player / descriptionPrevious value: -"Player display name from the priced line."New value: +"Player display name from the priced line. Null on main-line rows with no player attribution (bet_type is a match-level token like OVER/UNDER/ML_DRAW)." - changed
Output schema / properties / forecasts / items / properties / player / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / forecasts / items / properties / player_id / descriptionPrevious value: -"Lumify player ID. Bound by exact / Jr-stripped name match."New value: +"Lumify player ID. Bound by exact / Jr-stripped name match. Null on main-line rows with no player attribution." - changed
Output schema / properties / forecasts / items / properties / player_id / typePrevious value: -"integer"New value: +[ + "integer", + "null" +] - added
Output schema / properties / forecasts / items / properties / player_roleAdded value: +{ + "description": "'home'/'away' for team sports or 'p1'/'p2' for head-to-head sports, set only alongside a non-null bet_type. Null for player-prop rows and for match-level main-line tokens (OVER, UNDER, ML_DRAW).", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / forecasts / items / properties / research / descriptionPrevious value: -"Optional Deep Research overlay: {stance, conviction, note}. stance is validate / neutral / invalidate. Validate nudges p_hit up by at most 0.03 and lifts conviction; invalidate does the reverse. The chosen side stays. Null means read p_hit from the rate model alone."New value: +"Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction; invalidate does the reverse. The chosen side stays. Null means read p_hit from the rate model alone." - changed
Output schema / properties / forecasts / items / properties / side / descriptionPrevious value: -"'over' or 'under' — the more likely side given the player's shrunken rate versus line."New value: +"Prop rows: 'over' or 'under' — the more likely side given the player's shrunken rate versus line. Null on main-line rows — read the picked outcome from bet_type instead." - changed
Output schema / properties / forecasts / items / properties / side / typePrevious value: -"string"New value: +[ + "string", + "null" +]
- Changed
list_ev1 field changed- added
Input schema / properties / market / enumAdded value: +[ + "h2h", + "spreads", + "totals" +]
- Changed
list_forecasts20 fields changed- added
Input schema / properties / marketAdded value: +{ + "description": "Main-line family filter (h2h, spreads, or totals) for a sport's main-line forecast rows, once one exists. No sport publishes main-line forecasts today, so this has no effect yet. Ignored on prop-only sports.", + "enum": [ + "h2h", + "spreads", + "totals" + ], + "type": "string" +} - changed
Output schema / properties / wagers / descriptionPrevious value: -"Selected forecasted wagers, highest conviction first. Read p_hit as P(side hits the posted line); conviction is the board rank. How + field catalog: https://lumify.ai/docs/forecasts"New value: +"Selected forecasted wagers, highest conviction first. Read p_hit as P(the picked outcome — side on prop rows, bet_type on main-line rows — hits); conviction is the board rank. How + field catalog: https://lumify.ai/docs/forecasts" - added
Output schema / properties / wagers / items / properties / bet_typeAdded value: +{ + "description": "Main-line token when this row is a main-line forecast — ML_P1/ML_P2/ML_HOME/ML_AWAY/ML_DRAW, SPREAD_P1/SPREAD_P2/SPREAD_HOME/SPREAD_AWAY, or OVER/UNDER (same vocabulary as get_intelligence bets[].bet_type and list_ev). Null on player-prop rows — that's the discriminator between the two row shapes. No sport ships a non-null bet_type here yet.", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / wagers / items / properties / books / descriptionPrevious value: -"American price for the chosen side, keyed by bookmaker slug (e.g. {draftkings: -453}). Posted market price for the side the model picked."New value: +"American price for the picked outcome, keyed by bookmaker slug (e.g. {draftkings: -453}). Posted market price for the side/bet_type the model picked." - changed
Output schema / properties / wagers / items / properties / drivers / descriptionPrevious value: -"Signed contributions that moved p_hit. Read input as the player's measured rate and effect as how far that rate lifts the chosen side versus a league-mean player."New value: +"Signed contributions that moved p_hit. Read input as the measured rate/rating behind the pick and effect as how far it lifts the chosen outcome versus a baseline." - changed
Output schema / properties / wagers / items / properties / drivers / items / properties / effect / descriptionPrevious value: -"Signed shift in p_hit versus a league-mean player on the same line. 0.0 on yardage markets."New value: +"Signed shift in p_hit versus a baseline case on the same line. 0.0 on yardage markets." - changed
Output schema / properties / wagers / items / properties / drivers / items / properties / id / descriptionPrevious value: -"e.g. player.l10_rate — the recent-form rate that fed Poisson."New value: +"Prop rows: typically player.l10_rate — the recent-form rate that fed Poisson. Main-line rows would use a different namespace once a main-line forecast model ships." - changed
Output schema / properties / wagers / items / properties / drivers / items / properties / input / descriptionPrevious value: -"Measured rate in counting-stat units per game after shrinkage."New value: +"Measured rate/rating behind this driver, in native units." - changed
Output schema / properties / wagers / items / properties / line / descriptionPrevious value: -"Posted Over/Under main line the model was scored against."New value: +"Posted line the model was scored against. Prop and totals main-line rows: Over/Under number. Spreads main-line rows: the spread number. Null on h2h/moneyline rows." - changed
Output schema / properties / wagers / items / properties / line / typePrevious value: -"number"New value: +[ + "number", + "null" +] - changed
Output schema / properties / wagers / items / properties / market / descriptionPrevious value: -"Owls prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal."New value: +"Player-prop rows: Owls prop category (1:1 counting stats). MLB: strikeouts_pitcher, hits, rbis, runs, strikeouts_batter, hits_allowed, earned_runs, outs_recorded. NFL/NCAAF: passing/rushing/receiving_yards, receptions. NBA/NCAAB: points, rebounds, assists, steals, blocks, threes_made. NHL: goals, hockey_assists, shots_on_goal. Main-line rows (bet_type set): the main-line family — h2h, spreads, or totals." - changed
Output schema / properties / wagers / items / properties / p_hit / descriptionPrevious value: -"Model probability (0–1) that side hits line, from the player's shrunken counting-stat rate (Poisson vs the posted Over/Under). Optional research may nudge this by at most ±0.03; the side stays."New value: +"Model probability (0–1) that the picked outcome (side on prop rows, bet_type on main-line rows) hits. Prop rows: built from the player's shrunken counting-stat rate (Poisson vs the posted Over/Under). Optional research may nudge a prop's p_hit by at most ±0.03; the chosen side stays the same." - changed
Output schema / properties / wagers / items / properties / player / descriptionPrevious value: -"Player display name from the priced line."New value: +"Player display name from the priced line. Null on main-line rows with no player attribution (bet_type is a match-level token like OVER/UNDER/ML_DRAW)." - changed
Output schema / properties / wagers / items / properties / player / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / wagers / items / properties / player_id / descriptionPrevious value: -"Lumify player ID. Bound by exact / Jr-stripped name match."New value: +"Lumify player ID. Bound by exact / Jr-stripped name match. Null on main-line rows with no player attribution." - changed
Output schema / properties / wagers / items / properties / player_id / typePrevious value: -"integer"New value: +[ + "integer", + "null" +] - added
Output schema / properties / wagers / items / properties / player_roleAdded value: +{ + "description": "'home'/'away' for team sports or 'p1'/'p2' for head-to-head sports, set only alongside a non-null bet_type. Null for player-prop rows and for match-level main-line tokens (OVER, UNDER, ML_DRAW).", + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / wagers / items / properties / research / descriptionPrevious value: -"Optional Deep Research overlay: {stance, conviction, note}. stance is validate / neutral / invalidate. Validate nudges p_hit up by at most 0.03 and lifts conviction; invalidate does the reverse. The chosen side stays. Null means read p_hit from the rate model alone."New value: +"Optional Deep Research overlay on high-probability wagers (p_hit ≥ 0.80): {stance, conviction, note}. stance is validate / neutral / invalidate. note is the wager-level why. Validate / invalidate rows always carry a note. Validate nudges p_hit up by at most 0.03 and lifts conviction; invalidate does the reverse. The chosen side stays. Null means read p_hit from the rate model alone." - changed
Output schema / properties / wagers / items / properties / side / descriptionPrevious value: -"'over' or 'under' — the more likely side given the player's shrunken rate versus line."New value: +"Prop rows: 'over' or 'under' — the more likely side given the player's shrunken rate versus line. Null on main-line rows — read the picked outcome from bet_type instead." - changed
Output schema / properties / wagers / items / properties / side / typePrevious value: -"string"New value: +[ + "string", + "null" +]
2 tool updates
- Changed
get_intelligence2 fields changed- changed
Output schema / properties / match_overview / descriptionPrevious value: -"Natural-language matchup preview — form, context, what to watch. On predictive MLB may be a Search-backed context overlay. Null when no narrative has been generated."New value: +"Natural-language matchup preview — form, context, what to watch. Search-backed context overlay on every event sport (MLB, NFL, NCAAF, NBA, NCAAB, NHL, soccer, tennis); sport-shaped queries. Null when no narrative has been generated." - changed
Output schema / properties / rationale / descriptionPrevious value: -"Event-level factual matchup chips (starting pitchers, injuries, form). Event-level context overlay. Predictive MLB may populate on first get_intelligence; later calls reuse the stored row."New value: +"Event-level factual matchup chips (injuries, recent form, lineup/availability news — sport-shaped). Search-backed context overlay; may populate on first get_intelligence, later calls reuse the stored row."
- Changed
list_ev3 fields changed- added
Input schema / properties / marketAdded value: +{ + "description": "Main-line family: h2h (default, moneyline), spreads, or totals. Tennis + totals returns 400.", + "type": "string" +} - changed
Output schema / properties / market / descriptionPrevious value: -"Always h2h (moneyline) in v1."New value: +"h2h, spreads, or totals — the family scanned." - changed
Output schema / properties / opportunities / descriptionPrevious value: -"Positive-EV moneyline rows: {event_id, sport, league, commence_time, home_team, away_team, side, team, bet_type, fair_probability, ev}."New value: +"Positive-EV main-line rows: {event_id, sport, league, commence_time, home_team, away_team, side, team, bet_type, line, fair_probability, ev}."
Related MCP Connectors
Sports odds, player props and source coverage for AI assistants. Connect with your own API key.
Sports data across 8 sports under one canonical schema — scores, stats, standings, Elo, odds
NFL/NBA/MLB/NHL/PGA + DFS and prediction-market data. Browse free; query with a free API key.
Live odds, cross-book +EV and graded player-prop results across 27 books. Hosted endpoint included.
Related MCP Servers
- AlicenseAqualityCmaintenanceProvides AI assistants with sports model win probabilities and fair odds across nine sports without requiring an API key.360MIT
- FlicenseNot gradedqualityCmaintenanceProvides comprehensive sports intelligence including live scores, standings, schedules, betting odds, news, highlights, and more via SSE transport.-

PropLineofficial
AlicenseAqualityAmaintenanceLive sports betting odds, cross-book +EV, and graded player-prop resolution across 13 books.116561MIT- AlicenseBqualityCmaintenanceProvides AI agents with live, grounded sports data including model probabilities, track records, and European soccer and tennis arbitrage opportunities, so they answer from real numbers instead of stale guesses.135121MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.