Repository navigation
examples(tau2_custom/blackbox): type the seed's structured tool params - #693
Conversation
book_reservation, update_reservation_flights and update_reservation_passengers declared their structured arguments as bare `str` and `list`, so the vMCP published one flat type per parameter and the model had to guess field names and allowed values. Declare the types the benchmark's own tools declare, copied verbatim from its data_model.py, and give the optimizer that file as read-only context — the editable code cannot import it, since the store derives each tool's schema from that one script. Rule 2 of the optimizer instructions required JSON-shaped annotations, which told the optimizer to strip them. It now freezes the seed's signatures and says how a new tool copies a class. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Avi Weit <weit@il.ibm.com>
|
🏷️ Automatic Labeling I've analyzed this pull request and added the following labels:
These labels were selected based on the PR title, description, and changed files. If you believe any labels are incorrect or missing, feel free to adjust them manually. |
First paired direct-vs-blackbox run with the typed seedHeadline: the two arms measure the same thing, which is the objective. A store-delivered Both arms, same 7 tasks (
The blackbox arm ran against a store that does derive the schema from the annotations, so
1. The two sealed numbers are indistinguishable. 0.543 vs 0.429 is 0.114 apart with an SE 2. Delivery parity is the solid finding, and it is what this PR is for. The two seeds The one asymmetry left is on the optimizer side, not the delivery side: direct's optimizer 3. Everything else is below the measurement floor. 7 tasks × 5 trials gives ±0.20 per-task One detail worth recording: no pass anywhere came from an error masquerading as success. The |
The pinned store tag publishes one flat JSON type per tool parameter, so a store-delivered tool advertises less than the same tool does in-process: no enum for a Literal, no fields for a nested model. Point the clone at the fork commit that derives the published inputSchema from the annotations. An exact SHA, not a branch: a branch re-points the store under a run whenever it moves, and two runs days apart stop being comparable. Moving it forward is deliberate — bump the SHA, re-run, then commit. A SHA cannot be cloned with `--branch`, so the store now takes the clone-then-checkout path (`ref_is_tag=False`); the log-rotation patch anchors still match at this commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Avi Weit <weit@il.ibm.com>
…issing doc For the blackbox arm the prompt delegated the seed shape and the wrapper authoring rules to "the seeding reference" the intervention skill points to. No such reference exists: the skill has no references/ directory and its SKILL.md never mentions a seed. An onboarding driven by this prompt had nowhere to learn either. Scope the skill to what it owns — provisioning, lifecycle, store import order, per-candidate deploy — and name the committed seed as the normative example. State the four invariants inline so the pointer is not load-bearing: one public top-level def per script file, reach the environment only by bare-name primitive, signature/parameter names and docstring matching the benchmark's own tool, empty SKILL.md. Also correct `capability_sources` for the arm: it read `[]`, but the optimizer needs the benchmark's airline data model to write tool code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Avi Weit <weit@il.ibm.com>
Closes #692
What changed
6 files, +372/-10.
FlightType,CabinClassandInsuranceliterals and theFlightInfo,PassengerandPaymentmodels, copied verbatim from the pinned build's
data_model.py. Parameter names,docstrings and the
env_*call bodies are untouched.schema from that one module and resolves no import from a sibling script, so a shared
types module would silently yield a flat schema. The duplication is deliberate.
seed_capability/reference/data_model.py(new) — the benchmark's data model,byte-identical to the pinned build's and to the direct arm's copy, declared as
capability_sourcesso it is materialized into the optimizer's./guidance/sources/data_model.py. Previouslycapability_sources: [], so the blackboxoptimizer had no focused data model while the direct one did.
protected_pathsgainsreference/*.optimizer/INSTRUCTIONS.mdrule 2 rewritten: the signature and docstring togetherare the schema; the seed's signatures are frozen; a new tool uses plain types by default;
a new tool with a genuinely structured parameter copies the real class from the reference
file, with its dependencies and without any
tau2.*import or DB class; and the fourconstraints whose breach yields a flat schema with no error (same file, one-line
def,no self-referential model, no missing dependency).
Verification
book_reservationandupdate_reservation_flightsisidentical to what the benchmark sends its in-process agent, after resolving that
side's
$refs: same properties, enums, nested fields, descriptions andrequiredlists.That is the point — the two arms now advertise one tool surface.
nested item schemas, the other 11 are unchanged.
./guidance/sources/data_model.pyplacement confirmed against the direct arm's run dirs,where every
work/cand_*/guidance/sources/data_model.pyexists and is byte-identical tothe benchmark's file.
num_trials,max_iterationsand the gate settings are untouched.Dependency
Against the pinned store (
0.2.1) this change is a no-op — not a degradation. Thatstore derives a tool's params from the docstring and the signature's top-level annotation,
where
CabinClasscollapses to the samestringasstrdid andList[FlightInfo | dict]to the same
arrayaslistdid. Verified on all three tools by running 0.2.1's code path:the stored params, the description and the returns come out identical to the current
mainversions, so the published schema, the generated handler and therefore the score stayexactly as they are today.
The annotations only start to matter against a store that derives the schema from them. That
fix lives on
aviweit/skillberry-store@fix/vmcp-rich-tool-schemaand is not upstreamyet; the
blackbox_env.pypin that selects it is a separate cap-evolve branch, deliberatelynot in this PR. So this can merge on its own, with no behaviour change until the store moves.
Known gaps, not addressed here
arm's
reference/), plus class blocks inside the three scripts, and the optimizer editsthose scripts every iteration. A deleted class makes the derivation raise, which is
swallowed, and the schema silently falls back to flat. One test should assert the copies
match and that exactly those three tools derive a non-flat schema. Note
direct/seed_capability/tools/tools.pyclaims it is "Generated byexamples/tau2_custom/direct/seed_from_tau2.py" — that script does not exist.
List[X | dict]is kept for fidelity with the benchmark, though it publishes "anXor any object", which weakens the constraint it exists to express.
pip installin the docker executor, whosefailure is silently ignored. The three seed tools are affected; this is the reason the new
rule defaults new tools to plain types.
🤖 Generated with Claude Code