tau2 airline — SPA variant (tau2_airline_spa) - #316
Conversation
|
❌ Automatic Labeling Failed An error occurred while trying to automatically label this pull request. Please check the workflow logs for details and add labels manually. |
|
Thanks for this, @aviweit — this is a substantial piece of integration work and it's clear how much plumbing went into it. I reviewed the diff and then actually stood the whole stack up on a clean machine (real LLM via an OpenAI-compatible LiteLLM gateway, What's good
What I ran
Run B's accept line, for the record: {"kind": "step", "candidate": "cand_0001", "accept": true,
"reason": "paired Δ̄=+0.5000 > 0.0·SE=0.0000 (SE=0.2887, n=4)",
"val": 0.5, "parent": "seed", "parent_val": 0.0,
"optimizer_seconds": 794.11, "runner_seconds": 185.53, "opt_cost_usd": 9.404635}Per task, tasks 11 and 19 flipped So the design is sound and the whole pipeline — eval, diagnose, propose, upload, restart, re-eval, gate — does work. Run A vs Run B is the diff between "works" and "doesn't": two config/wiring gaps, both fixable in this PR. Details below. Blocking0. The frozen seed mis-declares the primitive signatures, which artificially depresses the baseline. This is the one I'd fix first, because it affects what any number from this example means. def book_reservation(..., flight_type: str, cabin: str, flights: str,
passengers: str, payment_methods: str,
total_baggages: 0, nonfree_baggages: 0, insurance: str): ...tau2's actual airline tool is: def book_reservation(..., flight_type: FlightType, cabin: CabinClass,
flights: List[FlightInfo | dict], passengers: List[Passenger | dict],
payment_methods: List[Payment | dict],
total_baggages: int, nonfree_baggages: int, insurance: Insurance): ...Same for That's not theoretical — it's what I measured. Four tasks (8, 11, 19, 22), one trial: baseline val 0.000, all four "Database state does NOT match the expected final state". And the optimizer's own
Three of its five design choices ( 1. The per-candidate SPA restart crashes the whole run. The optimizer created Three things stack up here:
2. skill_name = skill_dirs[-1].name
if skill_name != Adapter._current_skill_name:
spa_env.restart_spa(skill_name)
3. 4. LLM-authored code runs unsandboxed on the host. 5. The guard-bypass claim doesn't hold as shipped.
Medium6. The quick-test spec can't do what it claims. It's described as "verify the full eval+optimize pipeline end-to-end", but:
7. 8. No holdout in {"kind": "splits_warning", "msg": "test overlaps train/val (no-holdout fit) — the test number is NOT held out; report it as a fit metric"}That's a legitimate deliberate choice ( 9. Runner cost and tokens are always zero. From a real rollout: 10. The custom optimizer instructions can silently not apply. 11. 12. No smoke/run entrypoint, no docs, not on the site. Every other example ships 13. Setup is fragile on a cold machine. Two things I hit:
Small stuff
Suggested orderIf it were me: #0 first (it decides what any number here means), then #1 and #2 (the difference between "a run finishes" and "a run reports a trustworthy number"), then #6 so the shipped quick-test can actually exercise the loop out of the box, then #3/#4/#5, then docs + None of this changes the headline: the architecture works, and the loop closed with a gate-accepted |
|
Addendum — Run B's Same four task ids in
Two things fall out of that:
Credit where due on the same output: the infra failure was handled exactly per the contract — |
|
Last addendum — the run finished, and the {"kind": "finalize", "test_reward": 0.3333, "test_baseline_reward": 0.5,
"test_delta": -0.166667, "best_id": "cand_0001"}The seed scored higher on test than the optimized candidate. Laid out per task (same four ids in
The seed went 0.000 → 0.500 on identical tasks between its val and test evaluations — it passed tasks 8 and 19 on the second roll having failed both on the first. Task 19 is precisely the task the candidate's SKILL.md cancellation prose was written to fix, and the unmodified seed passes it too on a re-roll. So the
That's everything from my side. Net read unchanged: the integration is real, the loop closes, and the work needed is in |
tau2 airline — SPA variant (
tau2_airline_spa)Adds a new end-to-end cap-evolve example that optimizes tau2 airline tasks with
LLM calls routed through Skillberry Proxy-Agent (SPA) + Skillberry Store,
instead of calling the upstream LLM directly.
What's new
adapters/adapter.pyrun_tasksto SPAadapters/spa_env.pyseed_capability/primitive_skill/optimizer/INSTRUCTIONS.mdsetup.sh/teardown.shcapevolve.yamlcapevolve.smoke.yamlcapevolve.quick-test.yamlsplit_ids*.jsonPROMPT.mdKey design points
createnewcomposite skill packages alongside
primitive_skill/. It cannot edit the seed.adapter.apply()uploads the new composite skillto the store and restarts SPA with
SKILL_NAME=<candidate>before each eval.OPENAI_API_KEY/OPENAI_BASE_URL(or theirIBM_*equivalents) — nothing hardcoded.skillberry-benchmarks @ a3a8326,skillberry-store @ 0.2.1,skillberry-agent @ e359494.How to run