Agent skill

Crud Otagent Supabase

by open-thoughts in open-thoughts/OpenThoughts-Agent

Read, aggregate, and (carefully) write OT-Agent eval/model data in the Supabase registry.

Apache-2.0Auto-check passedAI & LLM Engineering

Install Crud Otagent Supabase

skills CLI
$ npx skills add open-thoughts/OpenThoughts-Agent --skill crud-otagent-supabase -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install open-thoughts/OpenThoughts-Agent crud-otagent-supabase --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/open-thoughts/OpenThoughts-Agent.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/crud-otagent-supabase .claude/skills/crud-otagent-supabase && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
crud-otagent-supabase
GitHub stars
301
Token cost
~6.2k tokens
SKILL.md length
2,151 words
Files
1
Skills in repo
44
Repo updated
First seen
Licence
Apache-2.0

At a glance

Read, aggregate, and (carefully) write OT-Agent eval/model data in the Supabase registry.

  • Works in 3 steps: Multiple entries per (model, benchmark):… → Sibling model rows: the same HF model… → Benchmark families (duplicate_of): a…
  • Asked to look up a models ID/OOD benchmark scores
  • SKILL.md covers Connect (run LOCALLY — faster…, Schema (the tables you'll touch), GOTCHA 1 — the metrics field… and GOTCHA 2 — multiple entries…, plus 10 more sections
  • Calls python; reaches huggingface.co; needs SUPABASE_SERVICE_ROLE_KEY and HF_TOKEN

What it does

Crud Otagent Supabase is an agent skill from open-thoughts/OpenThoughts-Agent. Read, aggregate, and (carefully) write OT-Agent eval/model data in the Supabase registry. Use when asked to look up a model's ID/OOD benchmark scores, build/refresh an ablation or paper table from eval results, find unevaluated models, register a model/eval, or reconcile duplicate rows. Covers the sandboxjobs/models/benchmarks schema, the metrics-field shape gotchas, the ID/OOD benchmark master list + per-benchmark task counts (for binomial SE), and the multiple-entries-per-model rule.

Its SKILL.md is about 6.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in AI & LLM Engineering. It works with Supabase. The repository describes itself as: Data recipes and robust infrastructure for training AI agents. The licence is Apache-2.0.

When your agent uses it

  • Asked to look up a models ID/OOD benchmark scores
  • Build/refresh an ablation
  • Paper table from eval results
  • Find unevaluated models

Example prompts

  • “/crud-otagent-supabase”

Requirements

  • Python 3
  • A credential in SUPABASE_SERVICE_ROLE_KEY
  • A credential in ANON_KEY

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Multiple entries per (model, benchmark): there are often a Pending/Started
  2. Sibling model rows: the same HF model may be registered under multiple
  3. Benchmark families (duplicate_of): a benchmark may have family members

What it can do on your machine

Read from SKILL.md and the folder at commit 3bd1917. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • python

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • huggingface.co

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • SUPABASE_SERVICE_ROLE_KEY
    • HF_TOKEN
    • ANON_KEY
    • SUPABASE_ANON_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Crud Otagent Supabase loads about 6.2k tokens when it runs. Until then it costs about 128 tokens; SKILL.md has 2,151 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~128
When it runs · the whole SKILL.md, loaded when a task matches
~6.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from open-thoughts/OpenThoughts-Agent at commit 3bd1917, republished under its Apache-2.0 licence (© open-thoughts). 2,151 words, ~6,157 tokens.

Download SKILL.mdSave it as .claude/skills/crud-otagent-supabase/SKILL.md (or your agent's skills folder).
name
crud-otagent-supabase
description
Read, aggregate, and (carefully) write OT-Agent eval/model data in the Supabase registry. Use when asked to look up a model's ID/OOD benchmark scores, build/refresh an ablation or paper table from eval results, find unevaluated models, register a model/eval, or reconcile duplicate rows. Covers the sandbox_jobs/models/benchmarks schema, the metrics-field shape gotchas, the ID/OOD benchmark master list + per-benchmark task counts (for binomial SE), and the multiple-entries-per-model rule.

crud-otagent-supabase

OT-Agent Supabase is the source of truth for model eval results — the scores live in sandbox_jobs, not in any markdown file. This skill covers querying them, aggregating ID/OOD means + SE as the ablation/paper tables do, and writing rows safely.

Connect (run LOCALLY — faster than ssh-ing a cluster)

Run from the Mac with the otagent env (≈10 s faster than ssh+python on a cluster). Filter by your own username for any write (see Guardrails).

bash
cd /Users/benjaminfeuer/Documents
set -a; source "${DC_AGENT_SECRET_ENV:?set DC_AGENT_SECRET_ENV to the secrets file first}"; set +a   # SUPABASE_URL + SUPABASE_SERVICE_ROLE_KEY (+ ANON_KEY, HF_TOKEN)
/Users/benjaminfeuer/miniconda3/envs/otagent/bin/python - <<'PY'
import os
from supabase import create_client
c = create_client(os.environ["SUPABASE_URL"],
                  os.environ.get("SUPABASE_SERVICE_ROLE_KEY") or os.environ["SUPABASE_ANON_KEY"])
# ... queries ...
PY
  • SUPABASE_SERVICE_ROLE_KEY bypasses RLS (full read/write). Prefer it for reads; for writes it means nothing stops you mutating other users' rows — so the cross-user pre-check in Guardrails is mandatory.
  • Schema DDL lives at /Users/benjaminfeuer/Documents/OpenThoughts-Agent/schema/ (sandbox_jobs, models, benchmarks, …). Read it when unsure of a column.

Schema (the tables you'll touch)

tablewhat it holdskey columns
sandbox_jobsone row per (model × benchmark) eval job — the scoresmodel_id, benchmark_id, metrics (jsonb), stats (jsonb), job_status, n_rep_eval, n_trials, username, hf_traces_link, slurm_job_id
modelsregistered modelsid, name (HF repo, e.g. laion/<run>-<step>-<size>), base_model_id (self-FK → models.id), dataset_id, agent_id, dataset_names, duplicate_of
benchmarksbenchmark catalogid, name, duplicate_of (→ canonical benchmark id, for families)
agentsharness/agent rowsid, name
sandbox_trial_model_usageper-trial model usage (FK→models)model_id — watch for cross-user FKs before deleting a model

job_status is an enum: Pending / Started / Finished (+ failure states). Only Finished rows with a non-null accuracy are real scores — Pending/Started rows have metrics=None.

GOTCHA 1 — the metrics field has TWO shapes

metrics is jsonb and appears as either a list of {"name","value"} dicts or a plain dict. Always extract through a shape-robust helper, never metrics["accuracy"] directly:

python
def get_metric(metrics, key="accuracy"):   # key: "accuracy" or "accuracy_stderr"
    if metrics is None: return None
    if isinstance(metrics, dict):           # {"accuracy": 0.25, ...}
        return metrics.get(key)
    if isinstance(metrics, list):           # [{"name":"accuracy","value":0.25}, {"name":"accuracy_stderr",...}]
        for e in metrics:
            if isinstance(e, dict):
                if e.get("name") == key:    return e.get("value")
                if e.get(key) is not None:  return e.get(key)
    return None

The list-of-dicts form also carries accuracy_stderr (the eval's own reported SE) — available if you want it, but the ablation tables recompute a pooled binomial SE (see "Aggregation").

GOTCHA 2 — multiple entries per model; sibling model rows

A single logical model can have more than one score per benchmark, and even more than one models row. Three rules:

  1. Multiple entries per (model, benchmark): there are often a Pending/Started row (acc None) and a Finished row for the same benchmark, or two reruns.
    • Drop non-Finished/null rows.
    • When ≥2 complete entries exist with identical evaluation settings, AVERAGE them (don't pick max, don't pick first). Different settings (e.g. a different n_rep_eval or harness) are not "identical settings" — keep them separate / pick the canonical one.
  2. Sibling model rows: the same HF model may be registered under multiple models.id (trainer auto-push + a manual -<step>-<size> row, or a duplicate). Query models by ilike on a name stub, not exact match, and union the sandbox_jobs across all matching model_ids before aggregating — a benchmark "missing" on one row may be Finished on a sibling.
  3. Benchmark families (duplicate_of): a benchmark may have family members (e.g. dev_set_v2 → DCAgent_dev_set_v2, dev_set_v2_2.0x). Resolve via the duplicate_of field (follow it to the canonical row) the way scripts/database/query_unevaled_models.py does, when a score seems absent under the exact name.
python
def get_model_scores(name_stub):
    bm = {b["id"]: b["name"] for b in c.table("benchmarks").select("id,name").execute().data}
    mods = c.table("models").select("id,name").ilike("name", f"%{name_stub}%").execute().data   # sibling rows
    perb = {}                                   # benchmark name -> list of (acc, status)
    for m in mods:
        for j in c.table("sandbox_jobs").select("benchmark_id,metrics,job_status").eq("model_id", m["id"]).execute().data:
            bn = bm.get(j["benchmark_id"], j["benchmark_id"])
            perb.setdefault(bn, []).append((get_metric(j["metrics"]), j["job_status"]))
    scores = {}                                 # benchmark -> averaged fraction over complete entries
    for bn, entries in perb.items():
        done = [a for a, s in entries if a is not None and s == "Finished"]
        if done:
            scores[bn] = sum(done) / len(done)  # AVERAGE identical-setting complete repeats
    return scores, mods, perb

ID / OOD benchmark master list (memorize — easy to get wrong)

The ablation tables split the agent benchmarks into ID ("Core") and OOD. The split is NOT stored in the schema and is NOT the CORE_BENCHMARKS list in eval/check_progress.py (that grouping is display-ordering only and gives wrong table numbers). Use exactly this:

setbenchmarkstask count N (for SE)
ID (Core)swebench-verified-random-100-folders100
terminal_bench_289
dev_set_v2 (partial-credit — see SE note below)— (excluded from binomial SE)
OODswebench-verified (the full 500-task set)500
aider_polyglot225
bfcl-parity123
financeagent_terminal50
gaia_127127
medagentbench300

dev_set_v2 is ID (3-member set: {swebench, v2, tb2}) but partial-credit — it's in the ID mean but excluded from the pooled binomial SE (SE pools only over swebench-100 + tb2; see Aggregation). For model-vs-model rankings, compare on a shared binary benchmark (swebench-100 or tb2), never on dev_set_v2.

The #1 trap: swebench-verified (full, 500) is OOD; the swebench-verified-random-100-folders subset (100) is ID. Same accuracy range, so a wrong pick barely moves the mean but flips ID↔OOD membership and changes the SE N (100 vs 500). Always check which swebench row is Finished.

python
ID  = {"swebench-verified-random-100-folders", "terminal_bench_2", "dev_set_v2"}
OOD = {"swebench-verified", "aider_polyglot", "bfcl-parity",
       "financeagent_terminal", "gaia_127", "medagentbench"}
# dev_set_v2 is partial-credit → in ID for the MEAN, but NOT in NTASK / the binomial SE.
ID_SE_BENCHMARKS = {"swebench-verified-random-100-folders", "terminal_bench_2"}  # SE pools over these only
NTASK = {"swebench-verified-random-100-folders": 100, "terminal_bench_2": 89,
         "swebench-verified": 500, "aider_polyglot": 225, "bfcl-parity": 123,
         "financeagent_terminal": 50, "gaia_127": 127, "medagentbench": 300}

Aggregation (reproduces the ablation/paper tables exactly)

Per set (ID or OOD): the cell mean is the unweighted average of the per-benchmark averaged accuracies; the SE is a pooled binomial over the total tasks of the present benchmarks. (Verified: this reproduces the existing rl_ablation_table.tex rows.) For ID, the SE pools over ID_SE_BENCHMARKS only (swebench-100 + tb2) — dev_set_v2 is in the ID mean but partial-credit, so it has no clean binomial N and is excluded from the SE pool.

python
import math
def set_stat(S, scores):                        # scores from get_model_scores()
    present = {b: scores[b] for b in S if scores.get(b) is not None}
    missing = sorted(set(S) - set(present))
    if not present: return None
    mean = sum(present.values()) / len(present) # fraction
    N    = sum(NTASK[b] for b in present)
    se   = math.sqrt(mean * (1 - mean) / N) * 100
    return round(mean*100, 1), round(se, 1), sorted(present), missing   # (mean%, SE, present, missing)
  • Completeness: a set is complete only if missing == []. Report partial means with the missing-benchmark list (e.g. a paper-table dagger). A model can be ID-complete but OOD-incomplete (or vice-versa) — check each set separately.
  • SE scales with N: ID SE ≈ 2.6–3.0 (N=189), OOD SE ≈ 1.1–1.2 (N=1325 when all 6 present). If you see ID SE ≈ 1.7 you (or a prior table) used the full 500-task swebench in ID by mistake — the membership trap above.

CREATE / UPDATE (registration)

Do not hand-insert rows; use the maintained scripts. Full flags are in OpenThoughts-Agent/CLAUDE.md.

  • Register a model (after an HF upload): scripts/database/manual_db_push.py --hf-model-id <repo> --base-model <hf> --dataset-name <name|comma,list> [--training-type RL] (defaults to SFT; pass RL for RL models). Multi-dataset → comma-list sets dataset_names. The --base-model <hf> flag is NOT stored as text — it's resolved to the models row of that base and stored as base_model_id (the self-FK). So a wrong --base-model registers a wrong uuid pointer, fixed by repointing it (next bullet), not by editing a string.
  • Repair a mis-registered base model (base_model_id points at the wrong base, e.g. a 27B model registered against the 9B base): a single-column repoint, NOT a re-register. Both the model and its correct base are models rows — find both by name (ilike), then update only base_model_id. It does not touch sandbox_jobs/scores or the row's own id (so no cross-user FK breakage — the models table has no per-row owner; writes are scoped by id), and the new value must be a valid models.id. Guard the write on the old value so it's idempotent + can't clobber a since-fixed row:
    python
    idname = {m["id"]: m["name"] for m in c.table("models").select("id,name").execute().data}
    wrong  = c.table("models").select("id,name,base_model_id").ilike("name","%<model-stub>%").execute().data
    RIGHT  = next(i for i,n in idname.items() if n == "<correct/base-hf-name>")   # the base's models.id
    for m in wrong:                                  # may be >1 sibling row — check each
        assert idname.get(RIGHT)                     # target base row exists
        c.table("models").update({"base_model_id": RIGHT}).eq("id", m["id"]).eq("base_model_id", m["base_model_id"]).execute()
    Then re-read to confirm the new base resolves correctly, that sibling rows you did NOT mean to touch (e.g. the real 9B model) still point at their own base, and that the sandbox_jobs count is unchanged.
  • Register/repair an eval job (auto-upload failed): scripts/database/manual_db_eval_push.py --job-dir trace_jobs/<RUN_TAG> [--hf-repo …] [--skip-hf] [--forced-update]. Verify the registered model name afterward — for vLLM-served models the auto-detected name can be a numeric served-id, not the HF repo; the CLAUDE.md "Manual Eval Upload" section has the fix-up queries.
  • Per-series exceptions: some series are HF-upload-ONLY (e.g. the Delphi RL scaling-laws SFT grid) — do not register those. Honor any enable_db_registration: false and documented no-DB series.

After an eval's HF trace dataset is uploaded, the leaderboard's trace icon keys off the sandbox_jobs.hf_traces_link column (a text URL on the job row, NOT on models) — see .agents/projects/ota-leaderboard/ota-leaderboard.md (DB-contract §5). Cross-linking = setting that one column to the trace repo URL. Touch nothing else (never scores/metrics, model_id, status).

Discover the eval → HF-repo mapping (don't guess the repo from the run-tag — the auto-push often fails or truncates). For each eval, the run dir is $EVAL_JOBS_DIR/eval-<safe_model>_<safe_dataset> (safe_* = /→_); read its two files:

  • meta.env → DB_JOB_ID (the sandbox_jobs.id to update), SLURM_JOB_ID, MODEL, REPO_ID.
  • upload.log → the [uploader] upload_eval_results(... hf_repo_id='<org>/<run_tag>') line is the repo the auto-harvest attempted. It is frequently NOT the live repo — the auto-push targets DCAgent2/<run_tag> (no -traces suffix) and on the shared DCAgent2 org it commonly 403s on storage quota (exceeded your public storage space). The real, manually re-uploaded dataset lands in laion/<run_tag>-traces (the canonical <org>/<run_tag>-traces convention; rl-agentic-job-cleanup §8 / eval-agentic-cleanup §1). Always confirm on HF which repo actually exists + is non-empty before linking — do not link the failed DCAgent2 attempt.
python
from huggingface_hub import HfApi; api = HfApi(token=os.environ["HF_TOKEN"])
rid = f"laion/{run_tag}-traces"                 # run_tag = the eval run-dir basename
info = api.dataset_info(rid, files_metadata=True)   # raises if missing
assert any(s.rfilename.endswith(".parquet") for s in info.siblings), f"{rid} empty"
url  = f"https://huggingface.co/datasets/{rid}"

96-char trap: HF repo names cap at 96 chars after the org/. A long run-tag (e.g. eval-laion_swesmith-coldstart-complete-lt32k-2ep-8B_DCAgent2_swebench-verified-random-100-folders-traces, 109 chars) cannot be created — the uploader truncates+hashes it (…swebench-verified80dacb91) or the push silently never lands. If dataset_info raises HFValidationError on length, the canonical-named repo does not exist → flag that eval as un-linkable, do NOT invent a link.

FK-safe, idempotent, single-column update (same cross-user rule as DELETE/MUTATE below — assert ownership before writing, scope the write to id + username, never overwrite a good link):

python
ME = "feuer1"   # the cluster username that OWNS the rows — NOT the Mac's os.environ["USER"]
row = c.table("sandbox_jobs").select("id,username,hf_traces_link").eq("id", job_id).execute().data[0]
assert row["username"] == ME, f"FK-SAFETY STOP: owned by {row['username']} != {ME} — do NOT mutate"
if row["hf_traces_link"] == url:    pass                      # idempotent: already correct → skip
elif row["hf_traces_link"]:         pass                      # a DIFFERENT good link exists → don't clobber
else:
    c.table("sandbox_jobs").update({"hf_traces_link": url}).eq("id", job_id).eq("username", ME).execute()

Then re-read each row to confirm the link set and that metrics/model_id/job_status are unchanged. Report any eval whose trace repo was missing/empty/over-length (couldn't link).

Show full SKILL.md (872 more words)Show less

DELETE / MUTATE — cross-user FK safety (MANDATORY pre-check)

Before deleting or updating ANY row, confirm no other user's rows depend on it. Restrict every write to rows you own; if an FK forces touching someone else's row, STOP and ask — do not repoint/delete it.

python
import os
me = os.environ.get("USER", "<your_user>")
fk = (c.table("sandbox_jobs").select("id,username,model_id")
        .eq("model_id", target_model_id).neq("username", me).execute().data)
if fk:
    print(f"STOP: {len(fk)} other-user sandbox_jobs FK this model — leave it, surface to user.")
else:
    ...  # safe to delete the model row / your own jobs

Also check sandbox_trial_model_usage (FK→models) the same way. Reads are always safe; the danger is exclusively delete/update.

Purging stale placeholder evals → separate skill

Removing dead, never-populated Pending/Started placeholder rows (eval launches that died/stalled before scoring) is its own guardrailed DELETE skill: crud-purge-stale-eval-placeholders — the >36h qualifier, the cross-user FK-safety pre-check, and the grandchild→child→job cascade delete all live there. Reach for it when the registry is clogged with stale Pending/Started/"Running" placeholders or when the eval listener's dedup is mis-firing on dead rows.

Quick recipes

  • "What are model X's ID/OOD scores?" → get_model_scores(stub) → set_stat(ID,…), set_stat(OOD,…); report mean±SE + any missing benchmarks.
  • "Build/refresh an ablation row." → same, then format mean_{SE}. Means use the averaged-complete-entries rule; SE uses the binomial N from NTASK.
  • "Find models not yet evaluated on benchmark Y." → scripts/database/query_unevaled_models.py --benchmark <family> --size <8|32> (resolves families via duplicate_of).
  • "Reconcile a duplicate model row." → find sibling rows by ilike, run the cross-user FK pre-check, then dedup only your own rows.

Recipe: ALL models NOT yet evaled (on ANY benchmark)

The general "which models have no eval at all" (vs query_unevaled_models.py, which is benchmark-specific and counts a Started/Pending job as "evaluated"). A model is EVALED iff it has ≥1 sandbox_jobs row that is Finished AND has a non-null accuracy; everything else (no jobs, only Started/Pending, or Finished-but-null) is UN-EVALED. Sibling-aware: a model NAME is evaled if ANY of its models.id rows is evaled (§GOTCHA 2). PAGINATE — models (~1300) and sandbox_jobs (~9000) both exceed the 1000-row default.

python
def page(table, cols):
    out=[]; off=0
    while True:
        d=c.table(table).select(cols).range(off,off+999).execute().data
        out+=d
        if len(d)<1000: break
        off+=1000
    return out
models=page("models","id,name"); jobs=page("sandbox_jobs","model_id,job_status,metrics")
evaled_ids={j["model_id"] for j in jobs if j["job_status"]=="Finished" and get_metric(j["metrics"]) is not None}  # get_metric = the shape-robust helper (§GOTCHA 1)
id2name={m["id"]:m["name"] for m in models}
evaled_names={id2name[i] for i in evaled_ids if i in id2name}
unevaled=sorted({m["name"] for m in models if m["name"] not in evaled_names})

**⚠️ TRIAGE the result before reporting it — it is mostly DATA-QUALITY NOISE, not real eval gaps:

  • (A) Real trained checkpoints (the actionable set) — DCAgent*/…, laion/…, bare run-names. Cross-check: in-progress (Started row — evaled right NOW, no Finished yet) vs CONCLUDED series (a3-*); flag both.
  • (B) API / served baselines — openai/, together_ai/, or bare o4-mini/gpt-*. Reference models, intentionally outside our eval pipeline.
  • (C) FILESYSTEM-PATH junk registrations — names that are a local path (^/…/models--<org>--<name>/snapshots/<hash>): registered by on-disk path instead of HF repo name (path-analog of the served-id trap, §eval-agentic-cleanup §2). The underlying model is usually ALREADY evaled under its proper HF name → a cleanup candidate, not a re-eval candidate. So report it bucketed A/B/C with the in-progress / concluded flags — never a raw name dump (the raw count wildly overstates the real eval gap).

Recipe: per-task timeouts + turn counts + outcome breakdown (model × benchmark)

To answer "what timeout/turns did model X actually get on benchmark Y, and how did its trials end?" — the numbers are split across three sources; no single column has them:

  1. The multiplier is in sandbox_jobs.config (jsonb). Pull the job row and read: config.timeout_multiplier (the scalar applied to every task's declared timeout), config.agents[0].max_timeout_sec (the hard ceiling — effective timeout is capped here), config.verifier.max_timeout_sec, n_attempts, orchestrator.n_concurrent_trials.

    python
    j = c.table("sandbox_jobs").select("config,stats,metrics,hf_traces_link") \
          .eq("model_id", model_id).eq("benchmark_id", tb2_id).eq("job_status","Finished").execute().data[0]
    mult = j["config"]["timeout_multiplier"]           # e.g. 2.0 for the eval team's real tb2 runs
    cap  = j["config"]["agents"][0]["max_timeout_sec"]  # 7200 ceiling

    Note: the eval team runs terminal_bench_2 at timeout_multiplier: 2.0 (the terminal_bench_2_2.0x benchmark family + the listener's per-bench EVAL_TIMEOUT_MULTIPLIER); the sbatch default of 1.0 is NOT what TB2 actually uses.

  2. The real per-task timeout (seconds) = each task's declared agent.timeout_sec × timeout_multiplier, hard-capped at agents[0].max_timeout_sec. The declared base is in the benchmark's task set (one task.toml per task), NOT in supabase. For TB2 the task set is DCAgent2/terminal_bench_2:

    python
    import tomllib; from huggingface_hub import HfApi, hf_hub_download
    api=HfApi()
    tomls=[s.rfilename for s in api.dataset_info("DCAgent2/terminal_bench_2").siblings if s.rfilename.endswith("task.toml")]
    base={tl.split("/")[0]: tomllib.load(open(hf_hub_download("DCAgent2/terminal_bench_2",tl,repo_type="dataset"),"rb"))["agent"]["timeout_sec"] for tl in tomls}
    eff = {t: min(b*mult, cap) for t,b in base.items()}   # real per-task effective timeout

    (TB2 base spans 600–12000s, median 900s → at 2.0× the median task gets 1800s/30min, long tail capped at 7200s.)

  3. Turn count + per-trial outcome are in the consolidated traces at sandbox_jobs.hf_traces_link (an HF dataset). The traces do NOT carry per-trial timing/config (the result field is a short status string, not the full result.json) — so don't look for agent_execution seconds there; derive the timeout from #1×#2. What the trace columns DO give:

    • conversations (list) → turn count = number of role=="assistant" messages (fallback: len(conversations)); report min/median/mean/max.
    • result (string) → per-trajectory terminal status: a reward ("1.0"/"0.0") or an exception type (SummarizationTimeoutError, AgentTimeoutError, VerifierTimeoutError, …). collections.Counter over it = the outcome breakdown (e.g. how many timed out vs passed, and which timeout dominates).
    • episode, trial_name, task → group turns/outcomes per task.
    python
    import pyarrow.parquet as pq, collections
    t=pq.read_table(hf_hub_download(traces_repo,"data/train-00000-of-00001.parquet",repo_type="dataset")).to_pylist()
    turns=[sum(1 for m in r["conversations"] if m.get("role")=="assistant") for r in t]
    outcome=collections.Counter(str(r["result"]) for r in t)   # rewards + exception types

Aggregate-only accuracy/error counts are also in sandbox_jobs.stats (stats.evals.<key>.n_errors / n_trials / reward_stats.reward lists tasks by reward), but stats does NOT have per-task timeouts or turns.

Guardrails

  • Reads are free; writes are dangerous. The service-role key bypasses RLS — always run the cross-user FK pre-check before any delete/update, and never mutate another user's rows.
  • Average complete identical-setting reruns; never silently pick one. Check ALL entries per (model, benchmark) AND all sibling models rows by ilike.
  • ID vs OOD: swebench-verified-random-100-folders = ID; full swebench-verified = OOD; dev_set_v2 = neither. Don't trust check_progress.py's CORE list.
  • metrics is list-OR-dict — always go through get_metric.
  • Honor no-DB series (enable_db_registration: false, Delphi grid, etc.).
  • A Finished SLURM/eval job is necessary but not sufficient — confirm a numeric accuracy in metrics (evalchemy can exit 0 with empty results).

© open-thoughts, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/crud-otagent-supabase of open-thoughts/OpenThoughts-Agent.

Open the folder on GitHubat commit 3bd1917

Compare with similar skills

Crud Otagent Supabase next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Crud Otagent Supabase compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Crud Otagent Supabase this skillopen-thoughts/OpenThoughts-Agent301—~6.2kAutomated safety check: PassApache-2.0
Opt Librarygridaco/grida2.7k—~1.4kAutomated safety check: PassApache-2.0
Docs Eval Planningsupabase/evals144—~2.9kAutomated safety check: PassApache-2.0
Supabasesundial-org/awesome-openclaw-skills663—~1.6kAutomated safety check: PassNone
Telemetry Standardssupabase/supabase111k—~2kAutomated safety check: PassApache-2.0
Aliyun Rds Supabasecinience/alicloud-skills397—~971Automated safety check: PassMIT

Similar skills

  • Opt Library

    gridaco/grida

    Set up, download, verify, and seed the optional Grida Library developer corpus into local Supabase.

    2.7k GitHub stars~1.4k tokensUpdated yesterday
    AI & LLM EngineeringAuto-check passed
  • Docs Eval Planning

    supabase/evals

    Official

    Plan a documentation eval for supabase/evals, where a docs guide is the subject under test.

    144 GitHub stars~2.9k tokensUpdated today
    AI & LLM EngineeringAuto-check passed
  • Supabase

    sundial-org/awesome-openclaw-skills

    Connect to Supabase for database operations, vector search, and storage.

    663 GitHub stars~1.6k tokensUpdated 7 mo ago
    DatabasesAuto-check passed
  • Telemetry Standards

    supabase/supabase

    Official

    PostHog event tracking standards for Supabase Studio. An agent skill from supabase/supabase.

    111k GitHub stars~2k tokensUpdated today
    Data & AnalyticsAuto-check passed
  • Aliyun Rds Supabase

    cinience/alicloud-skills

    A skill your agent uses when managing Alibaba Cloud RDS Supabase (RDS AI Service 2025-05-07) via OpenAPI, including creating, starting/stopping/restarting instances, resetting passwords, querying…

    397 GitHub stars~971 tokensUpdated 2 mo ago
    Backend & APIsAuto-check passed
  • Signal Scanner

    gooseworks-ai/goose-skills

    Detect buying signals across TAM companies and watchlist personas.

    1.2k GitHub starsUsed in 1 repo~1.4k tokens
    Data & AnalyticsAuto-check: notes

More from open-thoughts/OpenThoughts-Agent

All 44 skills in this repo
  • Analyze Dataset Token Length

    open-thoughts/OpenThoughts-Agent

    Analyze the token length of an OT-Agent conversation-format (ShareGPT-style) dataset — the per-trace distribution (median/p90/max) and/or counts under a token threshold + a metadata predicate (e.g.

    301 GitHub stars~1.5k tokensUpdated 12 days ago
    Auto-check passed
  • Analyze Id Eval Ranking

    open-thoughts/OpenThoughts-Agent

    Given a list of models (HF name stubs) that have valid agentic ID eval scores in Supabase, build a ranking table: raw per-benchmark accuracy on the 3 ID benchmarks (SWE-Bench-100…

    301 GitHub stars~3.1k tokensUpdated 12 days ago
    Auto-check passed
  • Analyze Job History Iris

    open-thoughts/OpenThoughts-Agent

    Run the Iris harbor job-history analyzer (scripts/iris/analyzeirisharborjob.py) on a datagen/eval job and read its JSON sidecar for trustworthy throughput / preemption / productive-trial stats.

    301 GitHub stars~2.9k tokensUpdated 12 days ago
    Auto-check passed
  • Analyze Rl Behavior

    open-thoughts/OpenThoughts-Agent

    Run the full RL behavioral-analysis pipeline (scripts/analysis/analyzerlbehavior.py) on a trained RL model to understand WHAT changed vs its pre-RL baseline, WHY, whether it PERSISTS, and its EVAL…

    301 GitHub stars~4.2k tokensUpdated 12 days ago
    Auto-check passed
  • Analyze Training Run Iris

    open-thoughts/OpenThoughts-Agent

    Detailed health check for a Levanter/executor TRAINING run on the marin Iris cluster (e.g.

    301 GitHub stars~2k tokensUpdated 12 days ago
    Auto-check passed
  • Code Create Staged Plan

    open-thoughts/OpenThoughts-Agent

    DESIGN a non-trivial codebase change (Harbor / MarinSkyRL / vLLM / OT-Agent / LLaMA-Factory) as a dependency-ordered STAGED PLAN before writing code — a feature port, a multi-step fix with parity…

    301 GitHub stars~1.5k tokensUpdated 12 days ago
    Auto-check passed

Works with

Questions about Crud Otagent Supabase

What does Crud Otagent Supabase do?

Read, aggregate, and (carefully) write OT-Agent eval/model data in the Supabase registry. Crud Otagent Supabase is an agent skill from open-thoughts/OpenThoughts-Agent. Read, aggregate, and (carefully) write OT-Agent eval/model data in the Supabase registry.

When should I use Crud Otagent Supabase?

Crud Otagent Supabase fits situations like: asked to look up a models ID/OOD benchmark scores; build/refresh an ablation; paper table from eval results; find unevaluated models.

How do I install Crud Otagent Supabase in Claude Code?

Run `npx skills add open-thoughts/OpenThoughts-Agent --skill crud-otagent-supabase -a claude-code`. Or copy the skill folder (.agents/skills/crud-otagent-supabase in open-thoughts/OpenThoughts-Agent) into .claude/skills/crud-otagent-supabase in your project. Claude Code loads it when a task matches its description.

How do I install Crud Otagent Supabase in Codex?

Run `npx skills add open-thoughts/OpenThoughts-Agent --skill crud-otagent-supabase -a codex`. Or copy the skill folder (.agents/skills/crud-otagent-supabase in open-thoughts/OpenThoughts-Agent) into .agents/skills/crud-otagent-supabase in your project. Codex loads it when a task matches its description.

Can I use Crud Otagent Supabase in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add open-thoughts/OpenThoughts-Agent --skill crud-otagent-supabase -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/crud-otagent-supabase, .gemini/skills/crud-otagent-supabase, .github/skills/crud-otagent-supabase and .opencode/skills/crud-otagent-supabase in your project.

What does Crud Otagent Supabase need to run?

Going by SKILL.md and its folder, Crud Otagent Supabase needs the command-line tools its instructions call (python) and credentials named SUPABASE_SERVICE_ROLE_KEY, HF_TOKEN, ANON_KEY and SUPABASE_ANON_KEY. Our summary lists: Python 3; A credential in SUPABASE_SERVICE_ROLE_KEY; A credential in ANON_KEY.

Does Crud Otagent Supabase access the network?

SKILL.md names 1 domain. In commands or code: huggingface.co; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Crud Otagent Supabase safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Crud Otagent Supabase use?

Crud Otagent Supabase is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Crud Otagent Supabase use?

About 6.2k tokens (SKILL.md is roughly 25k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Crud Otagent Supabase?

Skills that share tags, products or a category with Crud Otagent Supabase: Opt Library (gridaco/grida, 2.7k stars), Docs Eval Planning (supabase/evals, 144 stars), Supabase (sundial-org/awesome-openclaw-skills, 663 stars) and Telemetry Standards (supabase/supabase, 111k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Crud Otagent Supabase?

open-thoughts (a GitHub organization) maintains it in open-thoughts/OpenThoughts-Agent, which has 301 GitHub stars. The repository holds 44 skills in this directory. The repository was last updated on September 28, 2026.

Source: open-thoughts/OpenThoughts-Agent on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.