Who it's for. Web and Roblox hosts that already have an aig_ game license.
What you'll do. Infer actions with /play/act or /play/act/batch; report scores and ranks with /play/rounds. Never expect weights in the response.
Base URL: https://aia-hub.metamindinglab.com (Cloud Run Hub; do not call the old Vercel URL). Auth: Authorization: Bearer aig_… (or campus secret for first-party). Bind Roblox place_id and/or web Origin to the license. SDK zip: /developers/sdk.
| Method | Path | Purpose | Weights? |
|---|---|---|---|
| POST | /api/v1/play/act | Single AI infer → { m, j, f, seq } (+ Surge d/g/jh) | Never |
| POST | /api/v1/play/act/batch | 1–20 AIs, one HTTP tick → { acts[] } | Never |
| POST | /api/v1/play/rounds | Open heat → { round_id } | Never |
| POST | /api/v1/play/rounds/:id/complete | Scores, ranks, outcomes, events | Never |
| POST | /api/v1/play/rounds/:id/events | Mid-round event flush (≤500 total) | Never |
| GET | /api/v1/play/rounds?game_id= | List recent rounds (owner / aig_) | Never |
| GET | /api/v1/play/rounds/:id | Round detail + agents + events | Never |
| POST | /api/v1/training/licenses/game | Mint aig_ (creator cookie) | — |
| POST | /api/v1/training/licenses/brain | Grant play | train | director | — |
One brain per request. Prefer batch when N > 1.
{
"game_id": "uuid",
"brain_id": "uuid",
"room_slug": "surge_gauntlet",
"obs": [ /* 32 or 64 floats */ ],
"seq": 1,
"place_id": "123456789"
}
→ { "m": 0-8, "j": true|false, "f": true|false, "d": true|false, "g": true|false, "jh": 0-1, "seq": 1, "infer_ms": 2 }Cap agents.length ≤ 20. Think interval 0.15–0.2 s so Roblox stays under HttpService ~500 req/min. room_slug=surge_gauntlet → Hub expects 64-dim obs.
d / g / jh are Surge-only. Other rooms omit them or send zeros. Never map f (fire) to dash. Mint keys in Studio.
{
"game_id": "uuid",
"room_slug": "surge_gauntlet",
"place_id": "123456789",
"agents": [
{ "brain_id": "uuid-a", "obs": [/*64*/], "seq": 1 },
{ "brain_id": "uuid-b", "obs": [/*64*/], "seq": 1 }
]
}
→ { "acts": [{ "brain_id", "m", "j", "f", "d", "g", "jh", "seq", "infer_ms" }, ...], "infer_ms": 5 }The physics host computes score / rank / win. Hub persists for owner review (Round history). Does not write policy_weights or replace campus training sessions.
{
"game_id": "uuid",
"place_id": "123456789",
"room_slug": "surge_gauntlet",
"platform": "roblox",
"roster": [
{ "brain_id": "uuid-a", "slot": 0, "display_name": "Bolt" },
{ "brain_id": "uuid-b", "slot": 1, "display_name": "Spark" }
],
"meta": { "map_id": "map1" }
}
→ { "round_id": "uuid" }{
"duration_sec": 42.5,
"board": { "winner_brain_id": "uuid-a", "mode": "finish_first" },
"agents": [
{
"brain_id": "uuid-a",
"slot": 0,
"outcome": "win",
"rank": 1,
"score": 100,
"reward": { "coins": 50 },
"finish_time_sec": 38.2,
"alive": true,
"stats": { "jumps": 12 }
},
{
"brain_id": "uuid-b",
"slot": 1,
"outcome": "eliminated",
"rank": 2,
"score": 40,
"death_reason": "surge_caught",
"alive": false
}
],
"events": [
{ "t": 0, "type": "round_start" },
{ "t": 12.1, "type": "checkpoint", "brain_id": "uuid-a", "payload": { "cp": 3 } },
{ "t": 38.2, "type": "finish", "brain_id": "uuid-a" }
]
}
→ { "ok": true, "round_id": "uuid" }| Status | Meaning | Fix |
|---|---|---|
| 401 | Missing/invalid aig_ or campus secret | Mint key; ServerStorage / env only |
| 403 | Wrong game_id, place, origin, or no play grant | Bind place; grant scopes play |
| 400 | Bad obs dim / agents empty / events overflow | Match room_slug dim; caps 20 / 500 |
| 409 | Round already completed | New heat → new openRound |
| 404 | Brain or round not found | Valid brain_id / round_id |